diff --git a/extensions/css-language-features/client/src/cssMain.ts b/extensions/css-language-features/client/src/cssMain.ts index a8aaa53a18a..e12237d3f42 100644 --- a/extensions/css-language-features/client/src/cssMain.ts +++ b/extensions/css-language-features/client/src/cssMain.ts @@ -8,8 +8,9 @@ import * as path from 'path'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); -import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString } from 'vscode'; +import { languages, window, commands, ExtensionContext, Range, Position, TextDocument, CompletionItem, CompletionItemKind, TextEdit, SnippetString, FoldingRangeList, FoldingRange, FoldingContext, CancellationToken } from 'vscode'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient'; +import { FoldingRangesRequest, FoldingRangeRequestParam } from './protocol/foldingProvider.proposed'; // this method is called when vs code is activated export function activate(context: ExtensionContext) { @@ -92,6 +93,24 @@ export function activate(context: ExtensionContext) { } }); + languages.registerFoldingProvider(documentSelector, { + provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken) { + const param: FoldingRangeRequestParam = { + textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document), + maxRanges: context.maxRanges + }; + return client.sendRequest(FoldingRangesRequest.type, param, token).then(res => { + if (res && Array.isArray(res.ranges)) { + return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type))); + } + return null; + }, error => { + client.logFailedRequest(FoldingRangesRequest.type, error); + return null; + }); + } + }); + commands.registerCommand('_css.applyCodeAction', applyCodeAction); function applyCodeAction(uri: string, documentVersion: number, edits: TextEdit[]) { diff --git a/extensions/css-language-features/client/src/protocol/foldingProvider.proposed.ts b/extensions/css-language-features/client/src/protocol/foldingProvider.proposed.ts new file mode 100644 index 00000000000..dd420e5e452 --- /dev/null +++ b/extensions/css-language-features/client/src/protocol/foldingProvider.proposed.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TextDocumentIdentifier } from 'vscode-languageserver-types'; +import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol'; + +// ---- capabilities + +export interface FoldingProviderClientCapabilities { + /** + * The text document client capabilities + */ + textDocument?: { + /** + * Capabilities specific to the foldingProvider + */ + foldingProvider?: { + /** + * Whether implementation supports dynamic registration. If this is set to `true` + * the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)` + * return value for the corresponding server capability as well. + */ + dynamicRegistration?: boolean; + }; + }; +} + +export interface FoldingProviderOptions { +} + +export interface FoldingProviderServerCapabilities { + /** + * The server provides folding provider support. + */ + foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions); +} + +export interface FoldingRangeList { + /** + * The folding ranges. + */ + ranges: FoldingRange[]; +} + +export enum FoldingRangeType { + /** + * Folding range for a comment + */ + Comment = 'comment', + /** + * Folding range for a imports or includes + */ + Imports = 'imports', + /** + * Folding range for a region (e.g. `#region`) + */ + Region = 'region' +} + +export interface FoldingRange { + + /** + * The start line number + */ + startLine: number; + + /** + * The end line number + */ + endLine: number; + + /** + * The actual color value for this folding range. + */ + type?: FoldingRangeType | string; +} + +export interface FoldingRangeRequestParam { + /** + * The text document. + */ + textDocument: TextDocumentIdentifier; + + /** + * The maximum number of ranges to provide + */ + maxRanges?: number; +} + +export namespace FoldingRangesRequest { + export const type: RequestType = new RequestType('textDocument/foldingRanges'); +} diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index 66b473f1a6d..b3bd45f1ada 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -16,6 +16,7 @@ import { getLanguageModelCache } from './languageModelCache'; import { formatError, runSafe } from './utils/errors'; import URI from 'vscode-uri'; import { getPathCompletionParticipant } from './pathCompletion'; +import { FoldingProviderServerCapabilities, FoldingRangesRequest } from './protocol/foldingProvider.proposed'; export interface Settings { css: LanguageSettings; @@ -72,7 +73,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { } let snippetSupport = hasClientCapability('textDocument.completion.completionItem.snippetSupport'); scopedSettingsSupport = hasClientCapability('workspace.configuration'); - let capabilities: ServerCapabilities = { + + let capabilities: ServerCapabilities & FoldingProviderServerCapabilities = { // Tell the client that the server works in FULL text document sync mode textDocumentSync: documents.syncKind, completionProvider: snippetSupport ? { resolveProvider: false } : undefined, @@ -83,7 +85,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { documentHighlightProvider: true, codeActionProvider: true, renameProvider: true, - colorProvider: true + colorProvider: true, + foldingProvider: true }; return { capabilities }; }); @@ -274,5 +277,13 @@ connection.onRenameRequest(renameParameters => { }, null, `Error while computing renames for ${renameParameters.textDocument.uri}`); }); +connection.onRequest(FoldingRangesRequest.type, (params, token) => { + return runSafe(() => { + let document = documents.get(params[0].textDocument.uri); + let stylesheet = stylesheets.get(document); + return getLanguageService(document).findFoldingRegions(document, stylesheet); + }, null, `Error while computing folding ranges for ${params[0].textDocument.uri}`); +}); + // Listen on the connection connection.listen(); \ No newline at end of file diff --git a/extensions/css-language-features/server/src/protocol/foldingProvider.proposed.ts b/extensions/css-language-features/server/src/protocol/foldingProvider.proposed.ts new file mode 100644 index 00000000000..dd420e5e452 --- /dev/null +++ b/extensions/css-language-features/server/src/protocol/foldingProvider.proposed.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TextDocumentIdentifier } from 'vscode-languageserver-types'; +import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol'; + +// ---- capabilities + +export interface FoldingProviderClientCapabilities { + /** + * The text document client capabilities + */ + textDocument?: { + /** + * Capabilities specific to the foldingProvider + */ + foldingProvider?: { + /** + * Whether implementation supports dynamic registration. If this is set to `true` + * the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)` + * return value for the corresponding server capability as well. + */ + dynamicRegistration?: boolean; + }; + }; +} + +export interface FoldingProviderOptions { +} + +export interface FoldingProviderServerCapabilities { + /** + * The server provides folding provider support. + */ + foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions); +} + +export interface FoldingRangeList { + /** + * The folding ranges. + */ + ranges: FoldingRange[]; +} + +export enum FoldingRangeType { + /** + * Folding range for a comment + */ + Comment = 'comment', + /** + * Folding range for a imports or includes + */ + Imports = 'imports', + /** + * Folding range for a region (e.g. `#region`) + */ + Region = 'region' +} + +export interface FoldingRange { + + /** + * The start line number + */ + startLine: number; + + /** + * The end line number + */ + endLine: number; + + /** + * The actual color value for this folding range. + */ + type?: FoldingRangeType | string; +} + +export interface FoldingRangeRequestParam { + /** + * The text document. + */ + textDocument: TextDocumentIdentifier; + + /** + * The maximum number of ranges to provide + */ + maxRanges?: number; +} + +export namespace FoldingRangesRequest { + export const type: RequestType = new RequestType('textDocument/foldingRanges'); +}