diff --git a/src/cssMode.ts b/src/cssMode.ts index 387f1cf6..39aae4b8 100644 --- a/src/cssMode.ts +++ b/src/cssMode.ts @@ -30,5 +30,6 @@ export function setupMode(defaults: LanguageServiceDefaultsImpl): void { monaco.languages.registerRenameProvider(languageId, new languageFeatures.RenameAdapter(worker)); monaco.languages.registerColorProvider(languageId, new languageFeatures.DocumentColorAdapter(worker)); monaco.languages.registerFoldingRangeProvider(languageId, new languageFeatures.FoldingRangeAdapter(worker)); + monaco.languages.registerSelectionRangeProvider(languageId, new languageFeatures.SelectionRangeAdapter(worker)); new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults); } diff --git a/src/cssWorker.ts b/src/cssWorker.ts index c7d94993..b32074e7 100644 --- a/src/cssWorker.ts +++ b/src/cssWorker.ts @@ -8,7 +8,6 @@ import Thenable = monaco.Thenable; import IWorkerContext = monaco.worker.IWorkerContext; import * as cssService from 'vscode-css-languageservice'; -import * as ls from 'vscode-languageserver-types'; export class CSSWorker { @@ -41,7 +40,7 @@ export class CSSWorker { // --- language service host --------------- - doValidation(uri: string): Thenable { + doValidation(uri: string): Thenable { let document = this._getTextDocument(uri); if (document) { let stylesheet = this._languageService.parseStylesheet(document); @@ -50,76 +49,82 @@ export class CSSWorker { } return Promise.resolve([]); } - doComplete(uri: string, position: ls.Position): Thenable { + doComplete(uri: string, position: cssService.Position): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let completions = this._languageService.doComplete(document, position, stylesheet); return Promise.resolve(completions); } - doHover(uri: string, position: ls.Position): Thenable { + doHover(uri: string, position: cssService.Position): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let hover = this._languageService.doHover(document, position, stylesheet); return Promise.resolve(hover); } - findDefinition(uri: string, position: ls.Position): Thenable { + findDefinition(uri: string, position: cssService.Position): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let definition = this._languageService.findDefinition(document, position, stylesheet); return Promise.resolve(definition); } - findReferences(uri: string, position: ls.Position): Thenable { + findReferences(uri: string, position: cssService.Position): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let references = this._languageService.findReferences(document, position, stylesheet); return Promise.resolve(references); } - findDocumentHighlights(uri: string, position: ls.Position): Thenable { + findDocumentHighlights(uri: string, position: cssService.Position): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let highlights = this._languageService.findDocumentHighlights(document, position, stylesheet); return Promise.resolve(highlights); } - findDocumentSymbols(uri: string): Thenable { + findDocumentSymbols(uri: string): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let symbols = this._languageService.findDocumentSymbols(document, stylesheet); return Promise.resolve(symbols); } - doCodeActions(uri: string, range: ls.Range, context: ls.CodeActionContext): Thenable { + doCodeActions(uri: string, range: cssService.Range, context: cssService.CodeActionContext): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let actions = this._languageService.doCodeActions(document, range, context, stylesheet); return Promise.resolve(actions); } - findDocumentColors(uri: string): Thenable { + findDocumentColors(uri: string): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let colorSymbols = this._languageService.findDocumentColors(document, stylesheet); return Promise.resolve(colorSymbols); } - getColorPresentations(uri: string, color: ls.Color, range: ls.Range): Thenable { + getColorPresentations(uri: string, color: cssService.Color, range: cssService.Range): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let colorPresentations = this._languageService.getColorPresentations(document, stylesheet, color, range); return Promise.resolve(colorPresentations); } - provideFoldingRanges(uri: string, context?: { rangeLimit?: number; }): Thenable { + getFoldingRanges(uri: string, context?: { rangeLimit?: number; }): Thenable { let document = this._getTextDocument(uri); let ranges = this._languageService.getFoldingRanges(document, context); return Promise.resolve(ranges); } - doRename(uri: string, position: ls.Position, newName: string): Thenable { + getSelectionRanges(uri: string, positions: cssService.Position[]): Thenable { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let ranges = this._languageService.getSelectionRanges(document, positions, stylesheet); + return Promise.resolve(ranges); + } + doRename(uri: string, position: cssService.Position, newName: string): Thenable { let document = this._getTextDocument(uri); let stylesheet = this._languageService.parseStylesheet(document); let renames = this._languageService.doRename(document, position, newName, stylesheet); return Promise.resolve(renames); } - private _getTextDocument(uri: string): ls.TextDocument { + private _getTextDocument(uri: string): cssService.TextDocument { let models = this._ctx.getMirrorModels(); for (let model of models) { if (model.uri.toString() === uri) { - return ls.TextDocument.create(uri, this._languageId, model.version, model.getValue()); + return cssService.TextDocument.create(uri, this._languageId, model.version, model.getValue()); } } return null; diff --git a/src/fillers/vscode-nls.ts b/src/fillers/vscode-nls.ts index 51166074..cfb4e55b 100644 --- a/src/fillers/vscode-nls.ts +++ b/src/fillers/vscode-nls.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import {LocalizeInfo, LocalizeFunc, Options, LoadFunc} from 'vscode-nls'; - export interface Options { locale?: string; cacheLanguageResolution?: boolean; @@ -22,7 +20,7 @@ export interface LoadFunc { } function format(message: string, args: any[]): string { - let result:string; + let result: string; if (args.length === 0) { result = message; diff --git a/src/languageFeatures.ts b/src/languageFeatures.ts index a3f09781..6b9e95d6 100644 --- a/src/languageFeatures.ts +++ b/src/languageFeatures.ts @@ -7,7 +7,7 @@ import { LanguageServiceDefaultsImpl } from './monaco.contribution'; import { CSSWorker } from './cssWorker'; -import * as ls from 'vscode-languageserver-types'; +import * as cssService from 'vscode-css-languageservice'; import Uri = monaco.Uri; import Position = monaco.Position; @@ -106,16 +106,16 @@ export class DiagnosticsAdapter { function toSeverity(lsSeverity: number): monaco.MarkerSeverity { switch (lsSeverity) { - case ls.DiagnosticSeverity.Error: return monaco.MarkerSeverity.Error; - case ls.DiagnosticSeverity.Warning: return monaco.MarkerSeverity.Warning; - case ls.DiagnosticSeverity.Information: return monaco.MarkerSeverity.Info; - case ls.DiagnosticSeverity.Hint: return monaco.MarkerSeverity.Hint; + case cssService.DiagnosticSeverity.Error: return monaco.MarkerSeverity.Error; + case cssService.DiagnosticSeverity.Warning: return monaco.MarkerSeverity.Warning; + case cssService.DiagnosticSeverity.Information: return monaco.MarkerSeverity.Info; + case cssService.DiagnosticSeverity.Hint: return monaco.MarkerSeverity.Hint; default: return monaco.MarkerSeverity.Info; } } -function toDiagnostics(resource: Uri, diag: ls.Diagnostic): monaco.editor.IMarkerData { +function toDiagnostics(resource: Uri, diag: cssService.Diagnostic): monaco.editor.IMarkerData { let code = typeof diag.code === 'number' ? String(diag.code) : diag.code; return { @@ -132,21 +132,21 @@ function toDiagnostics(resource: Uri, diag: ls.Diagnostic): monaco.editor.IMarke // --- completion ------ -function fromPosition(position: Position): ls.Position { +function fromPosition(position: Position): cssService.Position { if (!position) { return void 0; } return { character: position.column - 1, line: position.lineNumber - 1 }; } -function fromRange(range: IRange): ls.Range { +function fromRange(range: IRange): cssService.Range { if (!range) { return void 0; } return { start: { line: range.startLineNumber - 1, character: range.startColumn - 1 }, end: { line: range.endLineNumber - 1, character: range.endColumn - 1 } }; } -function toRange(range: ls.Range): Range { +function toRange(range: cssService.Range): Range { if (!range) { return void 0; } @@ -157,29 +157,29 @@ function toCompletionItemKind(kind: number): monaco.languages.CompletionItemKind let mItemKind = monaco.languages.CompletionItemKind; switch (kind) { - case ls.CompletionItemKind.Text: return mItemKind.Text; - case ls.CompletionItemKind.Method: return mItemKind.Method; - case ls.CompletionItemKind.Function: return mItemKind.Function; - case ls.CompletionItemKind.Constructor: return mItemKind.Constructor; - case ls.CompletionItemKind.Field: return mItemKind.Field; - case ls.CompletionItemKind.Variable: return mItemKind.Variable; - case ls.CompletionItemKind.Class: return mItemKind.Class; - case ls.CompletionItemKind.Interface: return mItemKind.Interface; - case ls.CompletionItemKind.Module: return mItemKind.Module; - case ls.CompletionItemKind.Property: return mItemKind.Property; - case ls.CompletionItemKind.Unit: return mItemKind.Unit; - case ls.CompletionItemKind.Value: return mItemKind.Value; - case ls.CompletionItemKind.Enum: return mItemKind.Enum; - case ls.CompletionItemKind.Keyword: return mItemKind.Keyword; - case ls.CompletionItemKind.Snippet: return mItemKind.Snippet; - case ls.CompletionItemKind.Color: return mItemKind.Color; - case ls.CompletionItemKind.File: return mItemKind.File; - case ls.CompletionItemKind.Reference: return mItemKind.Reference; + case cssService.CompletionItemKind.Text: return mItemKind.Text; + case cssService.CompletionItemKind.Method: return mItemKind.Method; + case cssService.CompletionItemKind.Function: return mItemKind.Function; + case cssService.CompletionItemKind.Constructor: return mItemKind.Constructor; + case cssService.CompletionItemKind.Field: return mItemKind.Field; + case cssService.CompletionItemKind.Variable: return mItemKind.Variable; + case cssService.CompletionItemKind.Class: return mItemKind.Class; + case cssService.CompletionItemKind.Interface: return mItemKind.Interface; + case cssService.CompletionItemKind.Module: return mItemKind.Module; + case cssService.CompletionItemKind.Property: return mItemKind.Property; + case cssService.CompletionItemKind.Unit: return mItemKind.Unit; + case cssService.CompletionItemKind.Value: return mItemKind.Value; + case cssService.CompletionItemKind.Enum: return mItemKind.Enum; + case cssService.CompletionItemKind.Keyword: return mItemKind.Keyword; + case cssService.CompletionItemKind.Snippet: return mItemKind.Snippet; + case cssService.CompletionItemKind.Color: return mItemKind.Color; + case cssService.CompletionItemKind.File: return mItemKind.File; + case cssService.CompletionItemKind.Reference: return mItemKind.Reference; } return mItemKind.Property; } -function toTextEdit(textEdit: ls.TextEdit): monaco.editor.ISingleEditOperation { +function toTextEdit(textEdit: cssService.TextEdit): monaco.editor.ISingleEditOperation { if (!textEdit) { return void 0; } @@ -228,7 +228,7 @@ export class CompletionAdapter implements monaco.languages.CompletionItemProvide if (entry.additionalTextEdits) { item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit) } - if (entry.insertTextFormat === ls.InsertTextFormat.Snippet) { + if (entry.insertTextFormat === cssService.InsertTextFormat.Snippet) { item.insertTextRules = monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet; } return item; @@ -243,11 +243,11 @@ export class CompletionAdapter implements monaco.languages.CompletionItemProvide } -function isMarkupContent(thing: any): thing is ls.MarkupContent { - return thing && typeof thing === 'object' && typeof (thing).kind === 'string'; +function isMarkupContent(thing: any): thing is cssService.MarkupContent { + return thing && typeof thing === 'object' && typeof (thing).kind === 'string'; } -function toMarkdownString(entry: ls.MarkupContent | ls.MarkedString): monaco.IMarkdownString { +function toMarkdownString(entry: cssService.MarkupContent | cssService.MarkedString): monaco.IMarkdownString { if (typeof entry === 'string') { return { value: entry @@ -267,7 +267,7 @@ function toMarkdownString(entry: ls.MarkupContent | ls.MarkedString): monaco.IMa return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' }; } -function toMarkedStringArray(contents: ls.MarkupContent | ls.MarkedString | ls.MarkedString[]): monaco.IMarkdownString[] { +function toMarkedStringArray(contents: cssService.MarkupContent | cssService.MarkedString | cssService.MarkedString[]): monaco.IMarkdownString[] { if (!contents) { return void 0; } @@ -306,9 +306,9 @@ export class HoverAdapter implements monaco.languages.HoverProvider { function toDocumentHighlightKind(kind: number): monaco.languages.DocumentHighlightKind { switch (kind) { - case ls.DocumentHighlightKind.Read: return monaco.languages.DocumentHighlightKind.Read; - case ls.DocumentHighlightKind.Write: return monaco.languages.DocumentHighlightKind.Write; - case ls.DocumentHighlightKind.Text: return monaco.languages.DocumentHighlightKind.Text; + case cssService.DocumentHighlightKind.Read: return monaco.languages.DocumentHighlightKind.Read; + case cssService.DocumentHighlightKind.Write: return monaco.languages.DocumentHighlightKind.Write; + case cssService.DocumentHighlightKind.Text: return monaco.languages.DocumentHighlightKind.Text; } return monaco.languages.DocumentHighlightKind.Text; } @@ -340,7 +340,7 @@ export class DocumentHighlightAdapter implements monaco.languages.DocumentHighli // --- definition ------ -function toLocation(location: ls.Location): monaco.languages.Location { +function toLocation(location: cssService.Location): monaco.languages.Location { return { uri: Uri.parse(location.uri), range: toRange(location.range) @@ -389,7 +389,7 @@ export class ReferenceAdapter implements monaco.languages.ReferenceProvider { // --- rename ------ -function toWorkspaceEdit(edit: ls.WorkspaceEdit): monaco.languages.WorkspaceEdit { +function toWorkspaceEdit(edit: cssService.WorkspaceEdit): monaco.languages.WorkspaceEdit { if (!edit || !edit.changes) { return void 0; } @@ -428,28 +428,28 @@ export class RenameAdapter implements monaco.languages.RenameProvider { // --- document symbols ------ -function toSymbolKind(kind: ls.SymbolKind): monaco.languages.SymbolKind { +function toSymbolKind(kind: cssService.SymbolKind): monaco.languages.SymbolKind { let mKind = monaco.languages.SymbolKind; switch (kind) { - case ls.SymbolKind.File: return mKind.Array; - case ls.SymbolKind.Module: return mKind.Module; - case ls.SymbolKind.Namespace: return mKind.Namespace; - case ls.SymbolKind.Package: return mKind.Package; - case ls.SymbolKind.Class: return mKind.Class; - case ls.SymbolKind.Method: return mKind.Method; - case ls.SymbolKind.Property: return mKind.Property; - case ls.SymbolKind.Field: return mKind.Field; - case ls.SymbolKind.Constructor: return mKind.Constructor; - case ls.SymbolKind.Enum: return mKind.Enum; - case ls.SymbolKind.Interface: return mKind.Interface; - case ls.SymbolKind.Function: return mKind.Function; - case ls.SymbolKind.Variable: return mKind.Variable; - case ls.SymbolKind.Constant: return mKind.Constant; - case ls.SymbolKind.String: return mKind.String; - case ls.SymbolKind.Number: return mKind.Number; - case ls.SymbolKind.Boolean: return mKind.Boolean; - case ls.SymbolKind.Array: return mKind.Array; + case cssService.SymbolKind.File: return mKind.Array; + case cssService.SymbolKind.Module: return mKind.Module; + case cssService.SymbolKind.Namespace: return mKind.Namespace; + case cssService.SymbolKind.Package: return mKind.Package; + case cssService.SymbolKind.Class: return mKind.Class; + case cssService.SymbolKind.Method: return mKind.Method; + case cssService.SymbolKind.Property: return mKind.Property; + case cssService.SymbolKind.Field: return mKind.Field; + case cssService.SymbolKind.Constructor: return mKind.Constructor; + case cssService.SymbolKind.Enum: return mKind.Enum; + case cssService.SymbolKind.Interface: return mKind.Interface; + case cssService.SymbolKind.Function: return mKind.Function; + case cssService.SymbolKind.Variable: return mKind.Variable; + case cssService.SymbolKind.Constant: return mKind.Constant; + case cssService.SymbolKind.String: return mKind.String; + case cssService.SymbolKind.Number: return mKind.Number; + case cssService.SymbolKind.Boolean: return mKind.Boolean; + case cssService.SymbolKind.Array: return mKind.Array; } return mKind.Function; } @@ -530,7 +530,7 @@ export class FoldingRangeAdapter implements monaco.languages.FoldingRangeProvide public provideFoldingRanges(model: monaco.editor.IReadOnlyModel, context: monaco.languages.FoldingContext, token: CancellationToken): Thenable { const resource = model.uri; - return this._worker(resource).then(worker => worker.provideFoldingRanges(resource.toString(), context)).then(ranges => { + return this._worker(resource).then(worker => worker.getFoldingRanges(resource.toString(), context)).then(ranges => { if (!ranges) { return; } @@ -540,7 +540,7 @@ export class FoldingRangeAdapter implements monaco.languages.FoldingRangeProvide end: range.endLine + 1 }; if (typeof range.kind !== 'undefined') { - result.kind = toFoldingRangeKind(range.kind); + result.kind = toFoldingRangeKind(range.kind); } return result; }); @@ -549,11 +549,35 @@ export class FoldingRangeAdapter implements monaco.languages.FoldingRangeProvide } -function toFoldingRangeKind(kind: ls.FoldingRangeKind): monaco.languages.FoldingRangeKind { +function toFoldingRangeKind(kind: cssService.FoldingRangeKind): monaco.languages.FoldingRangeKind { switch (kind) { - case ls.FoldingRangeKind.Comment: return monaco.languages.FoldingRangeKind.Comment; - case ls.FoldingRangeKind.Imports: return monaco.languages.FoldingRangeKind.Imports; - case ls.FoldingRangeKind.Region: return monaco.languages.FoldingRangeKind.Region; + case cssService.FoldingRangeKind.Comment: return monaco.languages.FoldingRangeKind.Comment; + case cssService.FoldingRangeKind.Imports: return monaco.languages.FoldingRangeKind.Imports; + case cssService.FoldingRangeKind.Region: return monaco.languages.FoldingRangeKind.Region; } - return void 0; +} + +export class SelectionRangeAdapter implements monaco.languages.SelectionRangeProvider { + + constructor(private _worker: WorkerAccessor) { + } + + public provideSelectionRanges(model: monaco.editor.IReadOnlyModel, positions: Position[], token: CancellationToken): Thenable { + const resource = model.uri; + + return this._worker(resource).then(worker => worker.getSelectionRanges(resource.toString(), positions.map(fromPosition))).then(selectionRanges => { + if (!selectionRanges) { + return; + } + return selectionRanges.map(selectionRange => { + const result: monaco.languages.SelectionRange[] = []; + while (selectionRange) { + result.push({ range: toRange(selectionRange.range) }); + selectionRange = selectionRange.parent; + } + return result; + }); + }); + } + } diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index e69cf321..ee46e9f7 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -8,7 +8,6 @@ import * as mode from './cssMode'; import Emitter = monaco.Emitter; import IEvent = monaco.IEvent; -import IDisposable = monaco.IDisposable; // --- CSS configuration and defaults ---------