mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-24 18:49:00 +01:00
Add LanguageService as facade
This commit is contained in:
57
extensions/css/server/src/cssLanguageService.ts
Normal file
57
extensions/css/server/src/cssLanguageService.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {TextDocument, Position, CompletionList, Hover, Range, SymbolInformation, Diagnostic,
|
||||
Location, DocumentHighlight, CodeActionContext, Command} from 'vscode-languageserver';
|
||||
|
||||
import {Stylesheet} from './parser/cssNodes';
|
||||
import {Parser} from './parser/cssParser';
|
||||
import {CSSCompletion} from './services/cssCompletion';
|
||||
import {CSSHover} from './services/cssHover';
|
||||
import {CSSNavigation} from './services/cssNavigation';
|
||||
import {CSSCodeActions} from './services/cssCodeActions';
|
||||
import {CSSValidation} from './services/cssValidation';
|
||||
|
||||
export interface LanguageService {
|
||||
configure(raw: LanguageSettings): void;
|
||||
doValidation(document: TextDocument, stylesheet: Stylesheet): Thenable<Diagnostic[]>;
|
||||
parseStylesheet(document: TextDocument): Stylesheet;
|
||||
doComplete(document: TextDocument, position: Position, stylesheet: Stylesheet): Thenable<CompletionList>;
|
||||
doHover(document: TextDocument, position: Position, stylesheet: Stylesheet): Thenable<Hover>;
|
||||
findDefinition(document: TextDocument, position: Position, stylesheet: Stylesheet): Thenable<Location>;
|
||||
findReferences(document: TextDocument, position: Position, stylesheet: Stylesheet): Thenable<Location[]>;
|
||||
findDocumentHighlights(document: TextDocument, position: Position, stylesheet: Stylesheet): Thenable<DocumentHighlight[]>;
|
||||
findDocumentSymbols(document: TextDocument, stylesheet: Stylesheet): Thenable<SymbolInformation[]>;
|
||||
doCodeActions(document: TextDocument, range: Range, context: CodeActionContext, stylesheet: Stylesheet): Thenable<Command[]>;
|
||||
findColorSymbols(document: TextDocument, stylesheet: Stylesheet): Thenable<Range[]>;
|
||||
}
|
||||
|
||||
export interface LanguageSettings {
|
||||
validate?: boolean;
|
||||
lint?: any;
|
||||
}
|
||||
|
||||
export function getCSSLanguageService() : LanguageService {
|
||||
let parser = new Parser();
|
||||
let cssCompletion = new CSSCompletion();
|
||||
let cssHover = new CSSHover();
|
||||
let cssValidation = new CSSValidation();
|
||||
let cssNavigation = new CSSNavigation();
|
||||
let cssCodeActions = new CSSCodeActions();
|
||||
return {
|
||||
configure: cssValidation.configure.bind(cssValidation),
|
||||
doValidation: cssValidation.doValidation.bind(cssValidation),
|
||||
parseStylesheet: parser.parseStylesheet.bind(parser),
|
||||
doComplete: cssCompletion.doComplete.bind(cssCompletion),
|
||||
doHover: cssHover.doHover.bind(cssHover),
|
||||
findDefinition: cssNavigation.findDefinition.bind(cssNavigation),
|
||||
findReferences: cssNavigation.findReferences.bind(cssNavigation),
|
||||
findDocumentHighlights: cssNavigation.findDocumentHighlights.bind(cssNavigation),
|
||||
findDocumentSymbols: cssNavigation.findDocumentSymbols.bind(cssNavigation),
|
||||
doCodeActions: cssCodeActions.doCodeActions.bind(cssCodeActions),
|
||||
findColorSymbols: cssNavigation.findColorSymbols.bind(cssNavigation)
|
||||
};
|
||||
}
|
||||
@@ -9,13 +9,7 @@ import {
|
||||
TextDocuments, TextDocument, InitializeParams, InitializeResult, RequestType
|
||||
} from 'vscode-languageserver';
|
||||
|
||||
import {Parser} from './parser/cssParser';
|
||||
import {CSSCompletion} from './services/cssCompletion';
|
||||
import {CSSHover} from './services/cssHover';
|
||||
import {CSSNavigation} from './services/cssNavigation';
|
||||
import {CSSCodeActions} from './services/cssCodeActions';
|
||||
import {CSSValidation, Settings} from './services/cssValidation';
|
||||
|
||||
import {getCSSLanguageService, LanguageSettings, LanguageService} from './cssLanguageService';
|
||||
import {Stylesheet} from './parser/cssNodes';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
@@ -25,6 +19,12 @@ namespace ColorSymbolRequest {
|
||||
export const type: RequestType<string, Range[], any> = { get method() { return 'css/colorSymbols'; } };
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
css: LanguageSettings;
|
||||
less: LanguageSettings;
|
||||
scss: LanguageSettings;
|
||||
}
|
||||
|
||||
// Create a connection for the server. The connection uses for
|
||||
// stdin / stdout for message passing
|
||||
let connection: IConnection = createConnection(new IPCMessageReader(process), new IPCMessageWriter(process));
|
||||
@@ -55,11 +55,15 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
};
|
||||
});
|
||||
|
||||
let cssCompletion = new CSSCompletion();
|
||||
let cssHover = new CSSHover();
|
||||
let cssValidation = new CSSValidation();
|
||||
let cssNavigation = new CSSNavigation();
|
||||
let cssCodeActions = new CSSCodeActions();
|
||||
let languageServices : { [id:string]: LanguageService} = {
|
||||
css: getCSSLanguageService()
|
||||
};
|
||||
|
||||
function getLanguageService(document: TextDocument) {
|
||||
let service = languageServices[document.languageId];
|
||||
// todo handle unknown servce
|
||||
return service;
|
||||
}
|
||||
|
||||
// The content of a text document has changed. This event is emitted
|
||||
// when the text document first opened or when its content has changed.
|
||||
@@ -73,78 +77,71 @@ connection.onDidChangeConfiguration((change) => {
|
||||
});
|
||||
|
||||
function updateConfiguration(settings: Settings) {
|
||||
cssValidation.configure(settings.css);
|
||||
for (let languageId in languageServices) {
|
||||
languageServices[languageId].configure(settings[languageId]);
|
||||
}
|
||||
// Revalidate any open text documents
|
||||
documents.all().forEach(validateTextDocument);
|
||||
}
|
||||
|
||||
|
||||
function validateTextDocument(textDocument: TextDocument): void {
|
||||
if (textDocument.getText().length === 0) {
|
||||
// ignore empty documents
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: [] });
|
||||
return;
|
||||
}
|
||||
|
||||
let stylesheet = getStylesheet(textDocument);
|
||||
cssValidation.doValidation(textDocument, stylesheet).then(diagnostics => {
|
||||
getLanguageService(textDocument).doValidation(textDocument, stylesheet).then(diagnostics => {
|
||||
// Send the computed diagnostics to VSCode.
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
||||
});
|
||||
}
|
||||
|
||||
let parser = new Parser();
|
||||
|
||||
function getStylesheet(document: TextDocument): Stylesheet {
|
||||
return parser.parseStylesheet(document);
|
||||
return getLanguageService(document).parseStylesheet(document);
|
||||
}
|
||||
|
||||
connection.onCompletion(textDocumentPosition => {
|
||||
let document = documents.get(textDocumentPosition.textDocument.uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssCompletion.doComplete(document, textDocumentPosition.position, stylesheet);
|
||||
return getLanguageService(document).doComplete(document, textDocumentPosition.position, stylesheet);
|
||||
});
|
||||
|
||||
connection.onHover(textDocumentPosition => {
|
||||
let document = documents.get(textDocumentPosition.textDocument.uri);
|
||||
let styleSheet = getStylesheet(document);
|
||||
return cssHover.doHover(document, textDocumentPosition.position, styleSheet);
|
||||
return getLanguageService(document).doHover(document, textDocumentPosition.position, styleSheet);
|
||||
});
|
||||
|
||||
connection.onDocumentSymbol(documentSymbolParams => {
|
||||
let document = documents.get(documentSymbolParams.textDocument.uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssNavigation.findDocumentSymbols(document, stylesheet);
|
||||
return getLanguageService(document).findDocumentSymbols(document, stylesheet);
|
||||
});
|
||||
|
||||
connection.onDefinition(documentSymbolParams => {
|
||||
let document = documents.get(documentSymbolParams.textDocument.uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssNavigation.findDefinition(document, documentSymbolParams.position, stylesheet);
|
||||
return getLanguageService(document).findDefinition(document, documentSymbolParams.position, stylesheet);
|
||||
});
|
||||
|
||||
connection.onDocumentHighlight(documentSymbolParams => {
|
||||
let document = documents.get(documentSymbolParams.textDocument.uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssNavigation.findDocumentHighlights(document, documentSymbolParams.position, stylesheet);
|
||||
return getLanguageService(document).findDocumentHighlights(document, documentSymbolParams.position, stylesheet);
|
||||
});
|
||||
|
||||
connection.onReferences(referenceParams => {
|
||||
let document = documents.get(referenceParams.textDocument.uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssNavigation.findReferences(document, referenceParams.position, stylesheet);
|
||||
return getLanguageService(document).findReferences(document, referenceParams.position, stylesheet);
|
||||
});
|
||||
|
||||
connection.onCodeAction(codeActionParams => {
|
||||
let document = documents.get(codeActionParams.textDocument.uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssCodeActions.doCodeActions(document, codeActionParams.range, codeActionParams.context, stylesheet);
|
||||
return getLanguageService(document).doCodeActions(document, codeActionParams.range, codeActionParams.context, stylesheet);
|
||||
});
|
||||
|
||||
connection.onRequest(ColorSymbolRequest.type, uri => {
|
||||
let document = documents.get(uri);
|
||||
let stylesheet = getStylesheet(document);
|
||||
return cssNavigation.findColorSymbols(document, stylesheet);
|
||||
return getLanguageService(document).findColorSymbols(document, stylesheet);
|
||||
});
|
||||
|
||||
// Listen on the connection
|
||||
|
||||
@@ -32,7 +32,7 @@ export class CSSCompletion {
|
||||
}
|
||||
|
||||
|
||||
public doComplete(document: TextDocument, position: Position, styleSheet: nodes.Stylesheet): CompletionList {
|
||||
public doComplete(document: TextDocument, position: Position, styleSheet: nodes.Stylesheet): Thenable<CompletionList> {
|
||||
this.offset = document.offsetAt(position);
|
||||
this.position = position;
|
||||
this.currentWord = getCurrentWord(document, this.offset);
|
||||
@@ -67,23 +67,23 @@ export class CSSCompletion {
|
||||
this.getCompletionsForFunctionArgument(null, <nodes.Function>node, result);
|
||||
}
|
||||
if (result.items.length > 0) {
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
||||
this.getCompletionsForStylesheet(result);
|
||||
if (result.items.length > 0) {
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
if (this.variablePrefix && this.currentWord.indexOf(this.variablePrefix) === 0) {
|
||||
this.getVariableProposals(result);
|
||||
if (result.items.length > 0) {
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
// no match, don't show text matches
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
public getCompletionsForDeclarationProperty(result: CompletionList): CompletionList {
|
||||
|
||||
@@ -40,7 +40,7 @@ export class CSSHover {
|
||||
if (node instanceof nodes.Declaration) {
|
||||
let propertyName = node.getFullPropertyName();
|
||||
let entry = languageFacts.getProperties()[propertyName];
|
||||
if (entry) {
|
||||
if (entry && entry.description) {
|
||||
return Promise.resolve({
|
||||
contents: entry.description,
|
||||
range: getRange(node)
|
||||
|
||||
@@ -14,7 +14,7 @@ const localize = nls.loadMessageBundle();
|
||||
|
||||
export class CSSNavigation {
|
||||
|
||||
public findDefinition(document: TextDocument, position: Position, stylesheet: nodes.Node): Location {
|
||||
public findDefinition(document: TextDocument, position: Position, stylesheet: nodes.Node): Thenable<Location> {
|
||||
|
||||
let symbols = new Symbols(stylesheet);
|
||||
let offset = document.offsetAt(position);
|
||||
@@ -29,35 +29,35 @@ export class CSSNavigation {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
return Promise.resolve({
|
||||
uri: document.uri,
|
||||
range: getRange(node, document)
|
||||
};
|
||||
range: getRange(symbol.node, document)
|
||||
});
|
||||
}
|
||||
|
||||
public findReferences(document: TextDocument, position: Position, stylesheet: nodes.Node): Location[] {
|
||||
return this.findDocumentHighlights(document, position, stylesheet).map(h => {
|
||||
public findReferences(document: TextDocument, position: Position, stylesheet: nodes.Stylesheet): Thenable<Location[]> {
|
||||
return this.findDocumentHighlights(document, position, stylesheet).then(highlights => highlights.map(h => {
|
||||
return {
|
||||
uri: document.uri,
|
||||
range: h.range
|
||||
};
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public findDocumentHighlights(document: TextDocument, position: Position, stylesheet: nodes.Node): DocumentHighlight[] {
|
||||
public findDocumentHighlights(document: TextDocument, position: Position, stylesheet: nodes.Stylesheet): Thenable<DocumentHighlight[]> {
|
||||
let result: DocumentHighlight[] = [];
|
||||
|
||||
let offset = document.offsetAt(position);
|
||||
let node = nodes.getNodeAtOffset(stylesheet, offset);
|
||||
if (!node || node.type === nodes.NodeType.Stylesheet || node.type === nodes.NodeType.Declarations) {
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
let symbols = new Symbols(stylesheet);
|
||||
let symbol = symbols.findSymbolFromNode(node);
|
||||
let name = node.getText();
|
||||
|
||||
stylesheet.accept((candidate) => {
|
||||
stylesheet.accept(candidate => {
|
||||
if (symbol) {
|
||||
if (symbols.matchesSymbol(candidate, symbol)) {
|
||||
result.push({
|
||||
@@ -76,12 +76,10 @@ export class CSSNavigation {
|
||||
return true;
|
||||
});
|
||||
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public findDocumentSymbols(document: TextDocument, stylesheet: nodes.Stylesheet): SymbolInformation[] {
|
||||
public findDocumentSymbols(document: TextDocument, stylesheet: nodes.Stylesheet): Thenable<SymbolInformation[]> {
|
||||
|
||||
let result: SymbolInformation[] = [];
|
||||
|
||||
@@ -118,10 +116,10 @@ export class CSSNavigation {
|
||||
return true;
|
||||
});
|
||||
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
public findColorSymbols(document: TextDocument, stylesheet: nodes.Stylesheet): Range[] {
|
||||
public findColorSymbols(document: TextDocument, stylesheet: nodes.Stylesheet): Thenable<Range[]> {
|
||||
let result: Range[] = [];
|
||||
stylesheet.accept((node) => {
|
||||
if (isColorValue(node)) {
|
||||
@@ -129,7 +127,7 @@ export class CSSNavigation {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,18 +8,7 @@ import * as nodes from '../parser/cssNodes';
|
||||
import {TextDocument, Range, Diagnostic, DiagnosticSeverity} from 'vscode-languageserver';
|
||||
import {ILintConfigurationSettings, sanitize} from './lintRules';
|
||||
import {LintVisitor} from './lint';
|
||||
|
||||
export interface LanguageSettings {
|
||||
validate?: boolean;
|
||||
lint?: ILintConfigurationSettings;
|
||||
}
|
||||
|
||||
// The settings interface describe the server relevant settings part
|
||||
export interface Settings {
|
||||
css: LanguageSettings;
|
||||
less: LanguageSettings;
|
||||
scss: LanguageSettings;
|
||||
}
|
||||
import {LanguageSettings} from '../cssLanguageService';
|
||||
|
||||
export class CSSValidation {
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ suite('CSS - Completion', () => {
|
||||
}
|
||||
};
|
||||
|
||||
let testCompletionFor = function (value: string, stringBefore: string, expected: { count?: number, items?: ItemDescription[] }): Thenable<CompletionList> {
|
||||
let testCompletionFor = function (value: string, stringBefore: string, expected: { count?: number, items?: ItemDescription[] }): Thenable<void> {
|
||||
let idx = stringBefore ? value.indexOf(stringBefore) + stringBefore.length : 0;
|
||||
|
||||
let completionProvider = new CSSCompletion();
|
||||
@@ -44,16 +44,16 @@ suite('CSS - Completion', () => {
|
||||
let document = TextDocument.create('test://test/test.css', 'css', 0, value);
|
||||
let position = Position.create(0, idx);
|
||||
let jsonDoc = new Parser().parseStylesheet(document);
|
||||
let list = completionProvider.doComplete(document, position, jsonDoc);
|
||||
if (expected.count) {
|
||||
assert.equal(list.items, expected.count);
|
||||
}
|
||||
if (expected.items) {
|
||||
for (let item of expected.items) {
|
||||
assertCompletion(list, item, document);
|
||||
return completionProvider.doComplete(document, position, jsonDoc).then(list => {
|
||||
if (expected.count) {
|
||||
assert.equal(list.items, expected.count);
|
||||
}
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
if (expected.items) {
|
||||
for (let item of expected.items) {
|
||||
assertCompletion(list, item, document);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
test('sylesheet', function (testDone): any {
|
||||
|
||||
@@ -17,7 +17,7 @@ export function assertScopesAndSymbols(p: Parser, input: string, expected: strin
|
||||
assert.equal(scopeToString(global), expected);
|
||||
}
|
||||
|
||||
export function assertHighlights(p: Parser, input: string, marker: string, expectedMatches: number, expectedWrites: number): void {
|
||||
export function assertHighlights(p: Parser, input: string, marker: string, expectedMatches: number, expectedWrites: number): Thenable<void> {
|
||||
let document = TextDocument.create('test://test/test.css', 'css', 0, input);
|
||||
|
||||
let stylesheet = p.parseStylesheet(document);
|
||||
@@ -26,19 +26,20 @@ export function assertHighlights(p: Parser, input: string, marker: string, expec
|
||||
let index = input.indexOf(marker) + marker.length;
|
||||
let position = document.positionAt(index);
|
||||
|
||||
let highlights = new CSSNavigation().findDocumentHighlights(document, position, stylesheet);
|
||||
assert.equal(highlights.length, expectedMatches);
|
||||
return new CSSNavigation().findDocumentHighlights(document, position, stylesheet).then(highlights => {
|
||||
assert.equal(highlights.length, expectedMatches);
|
||||
|
||||
let nWrites = 0;
|
||||
for (let highlight of highlights) {
|
||||
if (highlight.kind === DocumentHighlightKind.Write) {
|
||||
nWrites++;
|
||||
let nWrites = 0;
|
||||
for (let highlight of highlights) {
|
||||
if (highlight.kind === DocumentHighlightKind.Write) {
|
||||
nWrites++;
|
||||
}
|
||||
let range = highlight.range;
|
||||
let start = document.offsetAt(range.start), end = document.offsetAt(range.end);
|
||||
assert.equal(document.getText().substring(start, end), marker);
|
||||
}
|
||||
let range = highlight.range;
|
||||
let start = document.offsetAt(range.start), end = document.offsetAt(range.end);
|
||||
assert.equal(document.getText().substring(start, end), marker);
|
||||
}
|
||||
assert.equal(nWrites, expectedWrites);
|
||||
assert.equal(nWrites, expectedWrites);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -169,10 +170,12 @@ suite('CSS - Symbols', () => {
|
||||
assertScopesAndSymbols(p, '@font-face { font-family: "Bitstream Vera Serif Bold"; }', '[]');
|
||||
});
|
||||
|
||||
test('mark occurrences', function () {
|
||||
test('mark occurrences', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, '@keyframes id {}; #main { animation: id 4s linear 0s infinite alternate; }', 'id', 2, 1);
|
||||
assertHighlights(p, '@keyframes id {}; #main { animation-name: id; foo: id;}', 'id', 2, 1);
|
||||
Promise.all([
|
||||
assertHighlights(p, '@keyframes id {}; #main { animation: id 4s linear 0s infinite alternate; }', 'id', 2, 1),
|
||||
assertHighlights(p, '@keyframes id {}; #main { animation-name: id; foo: id;}', 'id', 2, 1)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
|
||||
test('test variables in root scope', function () {
|
||||
@@ -195,33 +198,45 @@ suite('CSS - Symbols', () => {
|
||||
assertSymbolsInScope(p, '.a{ --var1: abc; } .b{ --var2: abc; } :root{ --var3: abc;}', 2, { name: '--var1', type: nodes.ReferenceType.Variable }, { name: '--var2', type: nodes.ReferenceType.Variable }, { name: '--var3', type: nodes.ReferenceType.Variable });
|
||||
});
|
||||
|
||||
test('mark occurrences for variable defined in root and used in a rule', function () {
|
||||
test('mark occurrences for variable defined in root and used in a rule', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, '.a{ background: let(--var1); } :root{ --var1: abc;}', '--var1', 2, 1);
|
||||
Promise.all([
|
||||
assertHighlights(p, '.a{ background: let(--var1); } :root{ --var1: abc;}', '--var1', 2, 1)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
|
||||
test('mark occurrences for variable defined in a rule and used in a different rule', function () {
|
||||
test('mark occurrences for variable defined in a rule and used in a different rule', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, '.a{ background: let(--var1); } :b{ --var1: abc;}', '--var1', 2, 1);
|
||||
Promise.all([
|
||||
assertHighlights(p, '.a{ background: let(--var1); } :b{ --var1: abc;}', '--var1', 2, 1)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
|
||||
test('mark occurrences for property', function () {
|
||||
test('mark occurrences for property', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, 'body { display: inline } #foo { display: inline }', 'display', 2, 0);
|
||||
Promise.all([
|
||||
assertHighlights(p, 'body { display: inline } #foo { display: inline }', 'display', 2, 0)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
|
||||
test('mark occurrences for value', function () {
|
||||
test('mark occurrences for value', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, 'body { display: inline } #foo { display: inline }', 'inline', 2, 0);
|
||||
Promise.all([
|
||||
assertHighlights(p, 'body { display: inline } #foo { display: inline }', 'inline', 2, 0)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
|
||||
test('mark occurrences for selector', function () {
|
||||
test('mark occurrences for selector', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, 'body { display: inline } #foo { display: inline }', 'body', 1, 1);
|
||||
Promise.all([
|
||||
assertHighlights(p, 'body { display: inline } #foo { display: inline }', 'body', 1, 1)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
|
||||
test('mark occurrences for comment', function () {
|
||||
test('mark occurrences for comment', function (testDone) {
|
||||
let p = new Parser();
|
||||
assertHighlights(p, '/* comment */body { display: inline } ', 'comment', 0, 0);
|
||||
Promise.all([
|
||||
assertHighlights(p, '/* comment */body { display: inline } ', 'comment', 0, 0)
|
||||
]).then(() => testDone(), (error) => testDone(error));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user