From 7b266abe01ae016eb21eae52f4a5f51f98b6df68 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Fri, 28 Aug 2020 16:33:02 +0800 Subject: [PATCH] Fix #899 --- CHANGELOG.md | 1 + server/src/embeddedSupport/languageModes.ts | 5 +-- server/src/modes/script/javascript.ts | 39 ++++++++++++++++++++- server/src/modes/style/index.ts | 4 +++ server/src/services/vls.ts | 33 +++++++++++++++-- 5 files changed, 76 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de6d718bd5..2149c2767f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### 0.27.0 +- Add `foldingRange` support to support dynamic folding ranges such as `#region`. #899. - Add setting `vetur.validation.interpolation` so interpolation diagnostics and `eslint-plugin-vue` diagnostics can be configed separately. #2131. - Fix VLS crash for *.vue files in node_modules. #2006. - Upgrade to TypeScript 4.0.2 and fix symbol outline issue. #1849. diff --git a/server/src/embeddedSupport/languageModes.ts b/server/src/embeddedSupport/languageModes.ts index aca6bd6490..bd17ea67df 100644 --- a/server/src/embeddedSupport/languageModes.ts +++ b/server/src/embeddedSupport/languageModes.ts @@ -18,9 +18,9 @@ import { ColorInformation, Color, ColorPresentation, - Command, CodeAction, - WorkspaceEdit + WorkspaceEdit, + FoldingRange } from 'vscode-languageserver-types'; import { getLanguageModelCache, LanguageModelCache } from './languageModelCache'; @@ -69,6 +69,7 @@ export interface LanguageMode { format?(document: TextDocument, range: Range, options: FormattingOptions): TextEdit[]; findDocumentColors?(document: TextDocument): ColorInformation[]; getColorPresentations?(document: TextDocument, color: Color, range: Range): ColorPresentation[]; + getFoldingRanges?(document: TextDocument): FoldingRange[]; onDocumentChanged?(filePath: string): void; onDocumentRemoved(document: TextDocument): void; diff --git a/server/src/modes/script/javascript.ts b/server/src/modes/script/javascript.ts index 49d480837d..2d5e2a7dbf 100644 --- a/server/src/modes/script/javascript.ts +++ b/server/src/modes/script/javascript.ts @@ -24,7 +24,8 @@ import { MarkupContent, CodeAction, CodeActionKind, - WorkspaceEdit + WorkspaceEdit, + FoldingRangeKind } from 'vscode-languageserver-types'; import { LanguageMode } from '../../embeddedSupport/languageModes'; import { VueDocumentRegions, LanguageRange } from '../../embeddedSupport/embeddedSupport'; @@ -469,6 +470,28 @@ export async function getJavascriptMode( }); return referenceResults; }, + getFoldingRanges(doc) { + const { scriptDoc, service } = updateCurrentVueTextDocument(doc); + if (!languageServiceIncludesFile(service, doc.uri)) { + return []; + } + + const fileFsPath = getFileFsPath(doc.uri); + const spans = service.getOutliningSpans(fileFsPath); + + return spans.map(s => { + const range = convertRange(scriptDoc, s.textSpan); + const kind = getFoldingRangeKind(s); + + return { + startLine: range.start.line, + startCharacter: range.start.character, + endLine: range.end.line, + endCharacter: range.end.character, + kind + }; + }); + }, getCodeActions(doc, range, _formatParams, context) { const { scriptDoc, service } = updateCurrentVueTextDocument(doc); const fileName = getFileFsPath(scriptDoc.uri); @@ -799,3 +822,17 @@ function getFilterText(insertText: string | undefined): string | undefined { // In all other cases, fallback to using the insertText return insertText; } + +function getFoldingRangeKind(span: ts.OutliningSpan): FoldingRangeKind | undefined { + switch (span.kind) { + case 'comment': + return FoldingRangeKind.Comment; + case 'region': + return FoldingRangeKind.Region; + case 'imports': + return FoldingRangeKind.Imports; + case 'code': + default: + return undefined; + } +} diff --git a/server/src/modes/style/index.ts b/server/src/modes/style/index.ts index fd6687b857..9fb9bdebd3 100644 --- a/server/src/modes/style/index.ts +++ b/server/src/modes/style/index.ts @@ -121,6 +121,10 @@ function getStyleMode( const embedded = embeddedDocuments.refreshAndGet(document); return languageService.findDocumentColors(embedded, stylesheets.refreshAndGet(embedded)); }, + getFoldingRanges(document) { + const embedded = embeddedDocuments.refreshAndGet(document); + return languageService.getFoldingRanges(embedded); + }, getColorPresentations(document, color, range) { const embedded = embeddedDocuments.refreshAndGet(document); return languageService.getColorPresentations(embedded, stylesheets.refreshAndGet(embedded), color, range); diff --git a/server/src/services/vls.ts b/server/src/services/vls.ts index 3bfce7cb26..e66fceb715 100644 --- a/server/src/services/vls.ts +++ b/server/src/services/vls.ts @@ -20,7 +20,8 @@ import { CompletionParams, CompletionTriggerKind, ExecuteCommandParams, - ApplyWorkspaceEditRequest + ApplyWorkspaceEditRequest, + FoldingRangeParams } from 'vscode-languageserver'; import { ColorInformation, @@ -38,7 +39,8 @@ import { TextDocumentChangeEvent, TextEdit, ColorPresentation, - Range + Range, + FoldingRange } from 'vscode-languageserver-types'; import { URI } from 'vscode-uri'; @@ -54,6 +56,7 @@ import { logger } from '../log'; import { getDefaultVLSConfig, VLSFullConfig, VLSConfig } from '../config'; import { LanguageId } from '../embeddedSupport/embeddedSupport'; import { APPLY_REFACTOR_COMMAND } from '../modes/script/javascript'; +import { EndOfLine } from 'vscode'; export class VLS { // @Todo: Remove this and DocumentContext @@ -156,6 +159,7 @@ export class VLS { this.lspConnection.onHover(this.onHover.bind(this)); this.lspConnection.onReferences(this.onReferences.bind(this)); this.lspConnection.onSignatureHelp(this.onSignatureHelp.bind(this)); + this.lspConnection.onFoldingRanges(this.onFoldingRanges.bind(this)); this.lspConnection.onCodeAction(this.onCodeAction.bind(this)); this.lspConnection.onDocumentColor(this.onDocumentColors.bind(this)); @@ -459,6 +463,28 @@ export class VLS { return NULL_SIGNATURE; } + onFoldingRanges({ textDocument }: FoldingRangeParams): FoldingRange[] { + const doc = this.documentService.getDocument(textDocument.uri)!; + const lmrs = this.languageModes.getAllLanguageModeRangesInDocument(doc); + + const result: FoldingRange[] = []; + + lmrs.forEach(lmr => { + if (lmr.mode.getFoldingRanges) { + lmr.mode.getFoldingRanges(doc).forEach(r => result.push(r)); + } + + result.push({ + startLine: lmr.start.line, + startCharacter: lmr.start.character, + endLine: lmr.end.line, + endCharacter: lmr.end.character + }); + }); + + return result; + } + onCodeAction({ textDocument, range, context }: CodeActionParams) { const doc = this.documentService.getDocument(textDocument.uri)!; const mode = this.languageModes.getModeAtPosition(doc, range.start); @@ -563,7 +589,8 @@ export class VLS { colorProvider: true, executeCommandProvider: { commands: [APPLY_REFACTOR_COMMAND] - } + }, + foldingRangeProvider: true }; } }