From 71f285c5d6ab083cdfb969dfc8ca98c5ae908ab9 Mon Sep 17 00:00:00 2001 From: Lyu Jason Date: Tue, 23 Mar 2021 16:33:37 +0800 Subject: [PATCH 01/20] ts, html, css --- .../language-server/src/plugins/PluginHost.ts | 17 ++++++ .../src/plugins/css/CSSPlugin.ts | 26 +++++++- .../src/plugins/html/HTMLPlugin.ts | 36 ++++++++++- .../language-server/src/plugins/interfaces.ts | 13 +++- .../plugins/typescript/TypeScriptPlugin.ts | 17 +++++- .../features/DocumentHighlightProvider.ts | 61 +++++++++++++++++++ packages/language-server/src/server.ts | 7 ++- packages/language-server/src/utils.ts | 4 ++ 8 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts diff --git a/packages/language-server/src/plugins/PluginHost.ts b/packages/language-server/src/plugins/PluginHost.ts index c32c47228..b8bda479e 100644 --- a/packages/language-server/src/plugins/PluginHost.ts +++ b/packages/language-server/src/plugins/PluginHost.ts @@ -10,6 +10,7 @@ import { CompletionList, DefinitionLink, Diagnostic, + DocumentHighlight, FormattingOptions, Hover, LinkedEditingRanges, @@ -432,6 +433,22 @@ export class PluginHost implements LSProvider, OnWatchFileChanges { ); } + findDocumentHighlight( + textDocument: TextDocumentIdentifier, + position: Position + ): Promise { + const document = this.getDocument(textDocument.uri); + if (!document) { + throw new Error('Cannot call methods on an unopened document'); + } + + return this.execute( + 'findDocumentHighlight', + [document, position], + ExecuteMode.FirstNonNull + ); + } + onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesPara[]): void { for (const support of this.plugins) { support.onWatchFileChanges?.(onWatchFileChangesParas); diff --git a/packages/language-server/src/plugins/css/CSSPlugin.ts b/packages/language-server/src/plugins/css/CSSPlugin.ts index b1e3709a8..63b6fef86 100644 --- a/packages/language-server/src/plugins/css/CSSPlugin.ts +++ b/packages/language-server/src/plugins/css/CSSPlugin.ts @@ -13,7 +13,8 @@ import { SymbolInformation, CompletionItem, CompletionItemKind, - SelectionRange + SelectionRange, + DocumentHighlight } from 'vscode-languageserver'; import { Document, @@ -33,6 +34,7 @@ import { CompletionsProvider, DiagnosticsProvider, DocumentColorsProvider, + DocumentHighlightProvider, DocumentSymbolsProvider, HoverProvider, SelectionRangeProvider @@ -51,7 +53,8 @@ export class CSSPlugin DocumentColorsProvider, ColorPresentationsProvider, DocumentSymbolsProvider, - SelectionRangeProvider { + SelectionRangeProvider, + DocumentHighlightProvider { private configManager: LSConfigManager; private cssDocuments = new WeakMap(); private triggerCharacters = ['.', ':', '-', '/']; @@ -70,6 +73,7 @@ export class CSSPlugin ); docManager.on('documentClose', (document) => this.cssDocuments.delete(document)); } + getSelectionRange(document: Document, position: Position): SelectionRange | null { if (!this.featureEnabled('selectionRange') || !isInTag(position, document.styleInfo)) { return null; @@ -282,6 +286,24 @@ export class CSSPlugin .map((symbol) => mapSymbolInformationToOriginal(cssDocument, symbol)); } + findDocumentHighlight(document: Document, position: Position): DocumentHighlight[] | null { + const cssDocument = this.getCSSDoc(document); + + if (!cssDocument.isInGenerated(position)) { + return null; + } + + const kind = extractLanguage(cssDocument); + + const result = getLanguageService(kind).findDocumentHighlights( + cssDocument, + cssDocument.getGeneratedPosition(position), + cssDocument.stylesheet + ).map(highlight => mapObjWithRangeToOriginal(cssDocument, highlight)); + + return result; + } + private getCSSDoc(document: Document) { let cssDoc = this.cssDocuments.get(document); if (!cssDoc || cssDoc.version < document.version) { diff --git a/packages/language-server/src/plugins/html/HTMLPlugin.ts b/packages/language-server/src/plugins/html/HTMLPlugin.ts index 874376b95..54d9a3456 100644 --- a/packages/language-server/src/plugins/html/HTMLPlugin.ts +++ b/packages/language-server/src/plugins/html/HTMLPlugin.ts @@ -15,7 +15,8 @@ import { TextEdit, Range, WorkspaceEdit, - LinkedEditingRanges + LinkedEditingRanges, + DocumentHighlight } from 'vscode-languageserver'; import { DocumentManager, @@ -29,12 +30,18 @@ import { HoverProvider, CompletionsProvider, RenameProvider, - LinkedEditingRangesProvider + LinkedEditingRangesProvider, + DocumentHighlightProvider } from '../interfaces'; import { isInsideMoustacheTag, toRange } from '../../lib/documents/utils'; export class HTMLPlugin - implements HoverProvider, CompletionsProvider, RenameProvider, LinkedEditingRangesProvider { + implements + HoverProvider, + CompletionsProvider, + RenameProvider, + LinkedEditingRangesProvider, + DocumentHighlightProvider { private configManager: LSConfigManager; private lang = getLanguageService({ customDataProviders: [svelteHtmlDataProvider], @@ -275,6 +282,29 @@ export class HTMLPlugin return { ranges }; } + findDocumentHighlight( + document: Document, + position: Position + ): DocumentHighlight[] | null { + const html = this.documents.get(document); + if (!html) { + return null; + } + + // const node = html.findNodeAt(document.offsetAt(position)); + // if (!node || this.possiblyComponent(node)) { + // return null; + // } + + const result = this.lang.findDocumentHighlights(document, position, html); + + if (!result.length) { + return null; + } + + return result; + } + /** * * The language service is case insensitive, and would provide diff --git a/packages/language-server/src/plugins/interfaces.ts b/packages/language-server/src/plugins/interfaces.ts index a4d1122c5..8897427c0 100644 --- a/packages/language-server/src/plugins/interfaces.ts +++ b/packages/language-server/src/plugins/interfaces.ts @@ -27,7 +27,8 @@ import { TextEdit, WorkspaceEdit, SelectionRange, - SignatureHelp + SignatureHelp, + DocumentHighlight } from 'vscode-languageserver-types'; import { Document } from '../lib/documents'; @@ -159,6 +160,13 @@ export interface LinkedEditingRangesProvider { ): Resolvable; } +export interface DocumentHighlightProvider { + findDocumentHighlight( + document: Document, + position: Position + ): Resolvable +} + export interface OnWatchFileChangesPara { fileName: string; changeType: FileChangeType; @@ -186,7 +194,8 @@ type ProviderBase = DiagnosticsProvider & RenameProvider & SignatureHelpProvider & SemanticTokensProvider & - LinkedEditingRangesProvider; + LinkedEditingRangesProvider & + DocumentHighlightProvider; export type LSProvider = ProviderBase & BackwardsCompatibleDefinitionsProvider; diff --git a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts index fb66043b4..955572120 100644 --- a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts +++ b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts @@ -19,7 +19,8 @@ import { SignatureHelp, SignatureHelpContext, SemanticTokens, - TextDocumentContentChangeEvent + TextDocumentContentChangeEvent, + DocumentHighlight } from 'vscode-languageserver'; import { Document, @@ -47,7 +48,8 @@ import { UpdateImportsProvider, OnWatchFileChangesPara, SemanticTokensProvider, - UpdateTsOrJsFile + UpdateTsOrJsFile, + DocumentHighlightProvider } from '../interfaces'; import { CodeActionsProviderImpl } from './features/CodeActionsProvider'; import { @@ -67,6 +69,7 @@ import { SignatureHelpProviderImpl } from './features/SignatureHelpProvider'; import { SnapshotManager } from './SnapshotManager'; import { SemanticTokensProviderImpl } from './features/SemanticTokensProvider'; import { isNoTextSpanInGeneratedCode, SnapshotFragmentMap } from './features/utils'; +import { DocumentHighlightProviderImpl } from './features/DocumentHighlightProvider'; export class TypeScriptPlugin implements @@ -81,6 +84,7 @@ export class TypeScriptPlugin SelectionRangeProvider, SignatureHelpProvider, SemanticTokensProvider, + DocumentHighlightProvider, OnWatchFileChanges, CompletionsProvider, UpdateTsOrJsFile { @@ -96,6 +100,7 @@ export class TypeScriptPlugin private readonly selectionRangeProvider: SelectionRangeProviderImpl; private readonly signatureHelpProvider: SignatureHelpProviderImpl; private readonly semanticTokensProvider: SemanticTokensProviderImpl; + private readonly documentHeightProvider: DocumentHighlightProviderImpl; constructor( docManager: DocumentManager, @@ -123,6 +128,7 @@ export class TypeScriptPlugin this.selectionRangeProvider = new SelectionRangeProviderImpl(this.lsAndTsDocResolver); this.signatureHelpProvider = new SignatureHelpProviderImpl(this.lsAndTsDocResolver); this.semanticTokensProvider = new SemanticTokensProviderImpl(this.lsAndTsDocResolver); + this.documentHeightProvider = new DocumentHighlightProviderImpl(this.lsAndTsDocResolver); } async getDiagnostics(document: Document): Promise { @@ -432,6 +438,13 @@ export class TypeScriptPlugin return this.semanticTokensProvider.getSemanticTokens(textDocument, range); } + async findDocumentHighlight( + document: Document, + position: Position + ): Promise { + return this.documentHeightProvider.findDocumentHighlight(document, position); + } + private getLSAndTSDoc(document: Document) { return this.lsAndTsDocResolver.getLSAndTSDoc(document); } diff --git a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts new file mode 100644 index 000000000..55dd98e95 --- /dev/null +++ b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts @@ -0,0 +1,61 @@ +import ts from 'typescript'; +import { Position, DocumentHighlight } from 'vscode-languageserver-protocol'; +import { DocumentHighlightKind } from 'vscode-languageserver-types'; +import { Document } from '../../../lib/documents'; +import { flatten, isInRange, isSamePosition } from '../../../utils'; +import { DocumentHighlightProvider } from '../../interfaces'; +import { LSAndTSDocResolver } from '../LSAndTSDocResolver'; +import { convertToLocationRange } from '../utils'; +import { isNoTextSpanInGeneratedCode } from './utils'; + +export class DocumentHighlightProviderImpl implements DocumentHighlightProvider { + constructor(private readonly lsAndTsDocResolver: LSAndTSDocResolver) {} + async findDocumentHighlight( + document: Document, + position: Position + ): Promise { + const { lang, tsDoc } = this.lsAndTsDocResolver.getLSAndTSDoc(document); + const fragment = await tsDoc.getFragment(); + + const offset = fragment.offsetAt(fragment.getGeneratedPosition(position)); + const highlights = lang.getDocumentHighlights(tsDoc.filePath, offset, [tsDoc.filePath]); + if (!highlights?.length) { + return null; + } + + const result = flatten(highlights.map((highlight) => highlight.highlightSpans)) + .filter(notInGeneratedCode(tsDoc.getFullText())) + .map((highlight) => + DocumentHighlight.create( + convertToLocationRange(fragment, highlight.textSpan), + this.convertHighlightKind(highlight) + ) + ) + .filter((highlight) => !isSamePosition(highlight.range.start, highlight.range.end)); + + if (!result.length || !this.containsOriginalPosition(result, position)) { + return null; + } + + return result; + } + + /** + * If position in not in any of the ranges. It's probably got a generated position in a weird places + */ + private containsOriginalPosition(result: DocumentHighlight[], position: Position): boolean { + return result.some((highlight) => isInRange(highlight.range, position)); + } + + private convertHighlightKind(highlight: ts.HighlightSpan): DocumentHighlightKind | undefined { + return highlight.kind === ts.HighlightSpanKind.writtenReference + ? DocumentHighlightKind.Write + : DocumentHighlightKind.Read; + } +} + +function notInGeneratedCode(text: string) { + return (ref: ts.HighlightSpan) => { + return isNoTextSpanInGeneratedCode(text, ref.textSpan); + }; +} diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index 41a798a9f..153351cf9 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -222,7 +222,8 @@ export function startServer(options?: LSOptions) { range: true, full: true }, - linkedEditingRangeProvider: true + linkedEditingRangeProvider: true, + documentHighlightProvider: true } }; }); @@ -310,6 +311,10 @@ export function startServer(options?: LSOptions) { pluginHost.getSelectionRanges(evt.textDocument, evt.positions) ); + connection.onDocumentHighlight((evt) => + pluginHost.findDocumentHighlight(evt.textDocument, evt.position) + ); + const diagnosticsManager = new DiagnosticsManager( connection.sendDiagnostics, docManager, diff --git a/packages/language-server/src/utils.ts b/packages/language-server/src/utils.ts index be736d82e..8ab0d3db8 100644 --- a/packages/language-server/src/utils.ts +++ b/packages/language-server/src/utils.ts @@ -126,3 +126,7 @@ export function modifyLines( ) .join('\r\n'); } + +export function isSamePosition(position: Position, another: Position) { + return position.line === another.line && position.character === another.character; +} From 62f5cc380194cfb2305b398b24a6aea13e117e01 Mon Sep 17 00:00:00 2001 From: Lyu Jason Date: Wed, 21 Apr 2021 16:03:15 +0800 Subject: [PATCH 02/20] WIP --- .../src/plugins/svelte/SveltePlugin.ts | 17 ++++++- .../svelte/features/getDocumentHighlight.ts | 49 +++++++++++++++++++ .../plugins/svelte/features/getHoverInfo.ts | 6 +-- .../svelte/features/getSelectionRanges.ts | 16 +++--- .../src/plugins/svelte/utils.ts | 9 ++++ 5 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts create mode 100644 packages/language-server/src/plugins/svelte/utils.ts diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index 3f314c0fe..4f8421cdf 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -9,7 +9,8 @@ import { Range, TextEdit, WorkspaceEdit, - SelectionRange + SelectionRange, + DocumentHighlight } from 'vscode-languageserver'; import { Document } from '../../lib/documents'; import { LSConfigManager, LSSvelteConfig } from '../../ls-config'; @@ -18,6 +19,7 @@ import { CodeActionsProvider, CompletionsProvider, DiagnosticsProvider, + DocumentHighlightProvider, FormattingProvider, HoverProvider, SelectionRangeProvider @@ -30,6 +32,7 @@ import { SvelteCompileResult, SvelteDocument } from './SvelteDocument'; import { Logger } from '../../logger'; import { getSelectionRange } from './features/getSelectionRanges'; import { merge } from 'lodash'; +import { getDocumentHighlight } from './features/getDocumentHighlight'; export class SveltePlugin implements @@ -38,7 +41,8 @@ export class SveltePlugin CompletionsProvider, HoverProvider, CodeActionsProvider, - SelectionRangeProvider { + SelectionRangeProvider, + DocumentHighlightProvider { private docManager = new Map(); constructor(private configManager: LSConfigManager) {} @@ -200,6 +204,15 @@ export class SveltePlugin return getSelectionRange(svelteDoc, position); } + async findDocumentHighlight( + document: Document, + position: Position + ): Promise { + const svelteDoc = await this.getSvelteDoc(document); + + return getDocumentHighlight(document, svelteDoc, position); + } + private featureEnabled(feature: keyof LSSvelteConfig) { return ( this.configManager.enabled('svelte.enable') && diff --git a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts new file mode 100644 index 000000000..dcf1d710b --- /dev/null +++ b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts @@ -0,0 +1,49 @@ +import { BaseNode } from 'estree'; +import { walk } from 'svelte/compiler'; +import { Position } from 'vscode-languageserver-types'; +import { Document, offsetAt } from '../../../lib/documents'; +import { SvelteDocument } from '../SvelteDocument'; +import { inStyleOrScript } from '../utils'; + +export async function getDocumentHighlight( + document: Document, + svelteDoc: SvelteDocument, + position: Position +) { + if (inStyleOrScript(svelteDoc, position)) { + return null; + } + + const { + ast: { html } + } = await svelteDoc.getCompiled(); + const transpiled = await svelteDoc.getTranspiled(); + const content = transpiled.getText(); + const offset = offsetAt(transpiled.getGeneratedPosition(position), content); + + walk(html, { + enter(node: BaseNode, parent: BaseNode) { + if ( + !( + node.type.includes('Block') && + node.start && + node.end && + node.start > offset && + node.end < offset + ) + ) { + this.skip(); + return; + } + + switch (node.type) { + case 'AwaitBlock': + node. + break; + + default: + break; + } + } + }); +} diff --git a/packages/language-server/src/plugins/svelte/features/getHoverInfo.ts b/packages/language-server/src/plugins/svelte/features/getHoverInfo.ts index cc12537ad..6f78acc9d 100644 --- a/packages/language-server/src/plugins/svelte/features/getHoverInfo.ts +++ b/packages/language-server/src/plugins/svelte/features/getHoverInfo.ts @@ -3,6 +3,7 @@ import { SvelteDocument } from '../SvelteDocument'; import { documentation, SvelteTag, getLatestOpeningTag } from './SvelteTags'; import { flatten } from '../../../utils'; import { isInTag } from '../../../lib/documents'; +import { inStyleOrScript } from '../utils'; /** * Get hover information for special svelte tags within moustache tags. @@ -10,10 +11,7 @@ import { isInTag } from '../../../lib/documents'; export function getHoverInfo(svelteDoc: SvelteDocument, position: Position): Hover | null { const offset = svelteDoc.offsetAt(position); - const isInStyleOrScript = - isInTag(position, svelteDoc.style) || - isInTag(position, svelteDoc.script) || - isInTag(position, svelteDoc.moduleScript); + const isInStyleOrScript = inStyleOrScript(svelteDoc, position); const offsetStart = Math.max(offset - 10, 0); const charactersAroundOffset = svelteDoc diff --git a/packages/language-server/src/plugins/svelte/features/getSelectionRanges.ts b/packages/language-server/src/plugins/svelte/features/getSelectionRanges.ts index c9cbdadc5..f085dbdbb 100644 --- a/packages/language-server/src/plugins/svelte/features/getSelectionRanges.ts +++ b/packages/language-server/src/plugins/svelte/features/getSelectionRanges.ts @@ -1,7 +1,8 @@ import { walk } from 'estree-walker'; import { Position, SelectionRange } from 'vscode-languageserver'; -import { isInTag, mapSelectionRangeToParent, offsetAt, toRange } from '../../../lib/documents'; +import { mapSelectionRangeToParent, offsetAt, toRange } from '../../../lib/documents'; import { SvelteDocument } from '../SvelteDocument'; +import { inStyleOrScript } from '../utils'; // estree does not have start/end in their public Node interface, // but the AST returned by svelte/compiler does. Type as any as a workaround. @@ -13,7 +14,10 @@ type OffsetRange = { }; export async function getSelectionRange(svelteDoc: SvelteDocument, position: Position) { - const { script, style, moduleScript } = svelteDoc; + if (inStyleOrScript(svelteDoc, position)) { + return null; + } + const { ast: { html } } = await svelteDoc.getCompiled(); @@ -21,14 +25,6 @@ export async function getSelectionRange(svelteDoc: SvelteDocument, position: Pos const content = transpiled.getText(); const offset = offsetAt(transpiled.getGeneratedPosition(position), content); - const embedded = [script, style, moduleScript]; - for (const info of embedded) { - if (isInTag(position, info)) { - // let other plugins do it - return null; - } - } - let nearest: OffsetRange = html; let result: SelectionRange | undefined; diff --git a/packages/language-server/src/plugins/svelte/utils.ts b/packages/language-server/src/plugins/svelte/utils.ts new file mode 100644 index 000000000..9d0ef1de7 --- /dev/null +++ b/packages/language-server/src/plugins/svelte/utils.ts @@ -0,0 +1,9 @@ +import { Position } from 'vscode-languageserver-protocol'; +import { isInTag } from '../../lib/documents'; +import { SvelteDocument } from './SvelteDocument'; + +export function inStyleOrScript(svelteDoc: SvelteDocument, position: Position) { + return isInTag(position, svelteDoc.style) || + isInTag(position, svelteDoc.script) || + isInTag(position, svelteDoc.moduleScript); +} From 376b24a3aa501684e0c459e76aa9647c88172625 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Wed, 23 Feb 2022 09:17:06 +0800 Subject: [PATCH 03/20] fast forward --- packages/language-server/src/plugins/PluginHost.ts | 3 ++- packages/language-server/src/plugins/svelte/SveltePlugin.ts | 1 - .../language-server/src/plugins/typescript/TypeScriptPlugin.ts | 1 + .../plugins/typescript/features/DocumentHighlightProvider.ts | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/language-server/src/plugins/PluginHost.ts b/packages/language-server/src/plugins/PluginHost.ts index 3b829dd98..2448c055a 100644 --- a/packages/language-server/src/plugins/PluginHost.ts +++ b/packages/language-server/src/plugins/PluginHost.ts @@ -511,7 +511,8 @@ export class PluginHost implements LSProvider, OnWatchFileChanges { return this.execute( 'findDocumentHighlight', [document, position], - ExecuteMode.FirstNonNull + ExecuteMode.FirstNonNull, + 'high' ); } diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index e829c76bc..8df12f772 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -33,7 +33,6 @@ import { getDiagnostics } from './features/getDiagnostics'; import { getHoverInfo } from './features/getHoverInfo'; import { getSelectionRange } from './features/getSelectionRanges'; import { SvelteCompileResult, SvelteDocument } from './SvelteDocument'; -import { merge } from 'lodash'; import { getDocumentHighlight } from './features/getDocumentHighlight'; export class SveltePlugin diff --git a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts index b1730ecb2..9e10c767d 100644 --- a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts +++ b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts @@ -34,6 +34,7 @@ import { CompletionsProvider, DefinitionsProvider, DiagnosticsProvider, + DocumentHighlightProvider, DocumentSymbolsProvider, FileRename, FindReferencesProvider, diff --git a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts index 55dd98e95..f1135f361 100644 --- a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts @@ -14,7 +14,7 @@ export class DocumentHighlightProviderImpl implements DocumentHighlightProvider document: Document, position: Position ): Promise { - const { lang, tsDoc } = this.lsAndTsDocResolver.getLSAndTSDoc(document); + const { lang, tsDoc } = await this.lsAndTsDocResolver.getLSAndTSDoc(document); const fragment = await tsDoc.getFragment(); const offset = fragment.offsetAt(fragment.getGeneratedPosition(position)); From c2f7afa4a0e9f6d98bb97ba132000bef59fef5e0 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Tue, 1 Mar 2022 17:09:01 +0800 Subject: [PATCH 04/20] general svelte blocks and tag --- .../svelte/features/getDocumentHighlight.ts | 149 +++++++++++++++--- 1 file changed, 129 insertions(+), 20 deletions(-) diff --git a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts index dcf1d710b..3c4a65744 100644 --- a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts +++ b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts @@ -1,7 +1,8 @@ -import { BaseNode } from 'estree'; import { walk } from 'svelte/compiler'; -import { Position } from 'vscode-languageserver-types'; -import { Document, offsetAt } from '../../../lib/documents'; +import { TemplateNode } from 'svelte/types/compiler/interfaces'; +import { Range } from 'vscode-languageserver'; +import { Position, DocumentHighlight, DocumentHighlightKind } from 'vscode-languageserver-types'; +import { Document, mapObjWithRangeToOriginal, offsetAt, positionAt } from '../../../lib/documents'; import { SvelteDocument } from '../SvelteDocument'; import { inStyleOrScript } from '../utils'; @@ -9,7 +10,7 @@ export async function getDocumentHighlight( document: Document, svelteDoc: SvelteDocument, position: Position -) { +): Promise { if (inStyleOrScript(svelteDoc, position)) { return null; } @@ -21,29 +22,137 @@ export async function getDocumentHighlight( const content = transpiled.getText(); const offset = offsetAt(transpiled.getGeneratedPosition(position), content); + const offsetStart = Math.max(offset - 10, 0); + const charactersAroundOffset = transpiled + .getText() + // use last 10 and next 10 characters, should cover 99% of all cases + .substr(offsetStart, 20); + + if (!['#', '/', ':', '@'].some((char) => charactersAroundOffset.includes(char))) { + return null; + } + + const nearest = findNearestSvelteTag(html, offset); + + if (!nearest) { + return null; + } + + if (nearest.type.endsWith('Tag')) { + return ( + getTagHighlight(offset, content, nearest)?.map((highlight) => + mapObjWithRangeToOriginal(transpiled, highlight) + ) ?? null + ); + } + + if (nearest.type.endsWith('Block')) { + return ( + getBlockHighlight(offset, content, nearest)?.map((highlight) => + mapObjWithRangeToOriginal(transpiled, highlight) + ) ?? null + ); + } + + return null; +} + +function findNearestSvelteTag(html: TemplateNode, offset: number) { + let nearest: TemplateNode | undefined; + const independentBlocks = ['EachBlock', 'IfBlock', 'AwaitBlock', 'KeyBlock']; + walk(html, { - enter(node: BaseNode, parent: BaseNode) { - if ( - !( - node.type.includes('Block') && - node.start && - node.end && - node.start > offset && - node.end < offset - ) - ) { + enter(node, parent, key) { + if (node.type === 'Fragment') { + return; + } + + const templateNode = node as TemplateNode; + const isWithin = templateNode.start <= offset && templateNode.end >= offset; + if (!isWithin) { this.skip(); return; } - switch (node.type) { - case 'AwaitBlock': - node. - break; + if ( + (node.type.endsWith('Block') && independentBlocks.includes(node.type)) || + node.type.endsWith('Tag') + ) { + nearest = templateNode; + return; + } - default: - break; + if (key === 'attributes') { + this.skip(); } } }); + + return nearest; +} + +function getTagHighlight( + offset: number, + content: string, + nearest: TemplateNode +): DocumentHighlight[] | null { + const name = + nearest.type === 'RawMustacheTag' + ? 'html' + : nearest.type.replace('Tag', '').toLocaleLowerCase(); + + const startTag = '@' + name; + const indexOfName = content.indexOf(startTag, nearest.start); + + if (indexOfName < 0 || indexOfName > offset || nearest.start + startTag.length < offset) { + return null; + } + + return [ + { + range: Range.create( + positionAt(indexOfName, content), + positionAt(indexOfName + startTag.length, content) + ) + } + ]; +} + +function getBlockHighlight( + offset: number, + content: string, + nearest: TemplateNode +): DocumentHighlight[] | null { + const name = nearest.type.replace('Block', '').toLowerCase(); + + const startTag = '#' + name; + const startTagStart = content.indexOf(startTag, nearest.start); + + if (startTagStart < 0) { + return null; + } + + const ranges: Array<[start: number, end: number]> = []; + + ranges.push([startTagStart, startTagStart + startTag.length]); + + const endTag = '/' + name; + const endTagStart = content.lastIndexOf(endTag, nearest.end); + + ranges.push([endTagStart, endTagStart + endTag.length]); + + if (nearest.type === 'EachBlock' && nearest.else) { + const elseStart = content.lastIndexOf(':else', nearest.else.start); + + ranges.push([elseStart, elseStart + ':else'.length]); + } + + if (!ranges.some(([start, end]) => offset >= start && offset <= end)) { + return null; + } + + return ranges.map(([start, end]) => ({ + range: Range.create(positionAt(start, content), positionAt(end, content)), + kind: DocumentHighlightKind.Read + })); } From a9111cfea744d276e68fa58cfea513fde74e57d2 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Tue, 1 Mar 2022 17:17:26 +0800 Subject: [PATCH 05/20] only same file highlights --- .../plugins/typescript/features/DocumentHighlightProvider.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts index f1135f361..786547c73 100644 --- a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts @@ -18,7 +18,10 @@ export class DocumentHighlightProviderImpl implements DocumentHighlightProvider const fragment = await tsDoc.getFragment(); const offset = fragment.offsetAt(fragment.getGeneratedPosition(position)); - const highlights = lang.getDocumentHighlights(tsDoc.filePath, offset, [tsDoc.filePath]); + const highlights = lang + .getDocumentHighlights(tsDoc.filePath, offset, [tsDoc.filePath]) + ?.filter((highlight) => highlight.fileName === tsDoc.filePath); + if (!highlights?.length) { return null; } From a191b1ceb99e847b99dc08c427cfa2b0eccceb04 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Tue, 1 Mar 2022 18:14:36 +0800 Subject: [PATCH 06/20] else highlights for if block --- .../svelte/features/getDocumentHighlight.ts | 92 ++++++++++++------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts index 3c4a65744..73a5dbe4b 100644 --- a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts +++ b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts @@ -32,23 +32,23 @@ export async function getDocumentHighlight( return null; } - const nearest = findNearestSvelteTag(html, offset); + const candidate = findCandidateSvelteTag(html, offset); - if (!nearest) { + if (!candidate) { return null; } - if (nearest.type.endsWith('Tag')) { + if (candidate.type.endsWith('Tag')) { return ( - getTagHighlight(offset, content, nearest)?.map((highlight) => + getTagHighlight(offset, content, candidate)?.map((highlight) => mapObjWithRangeToOriginal(transpiled, highlight) ) ?? null ); } - if (nearest.type.endsWith('Block')) { + if (candidate.type.endsWith('Block')) { return ( - getBlockHighlight(offset, content, nearest)?.map((highlight) => + getBlockHighlight(offset, content, candidate)?.map((highlight) => mapObjWithRangeToOriginal(transpiled, highlight) ) ?? null ); @@ -57,54 +57,46 @@ export async function getDocumentHighlight( return null; } -function findNearestSvelteTag(html: TemplateNode, offset: number) { - let nearest: TemplateNode | undefined; - const independentBlocks = ['EachBlock', 'IfBlock', 'AwaitBlock', 'KeyBlock']; +function findCandidateSvelteTag(html: TemplateNode, offset: number) { + let candidate: TemplateNode | undefined; walk(html, { - enter(node, parent, key) { + enter(node, _, key) { if (node.type === 'Fragment') { return; } const templateNode = node as TemplateNode; const isWithin = templateNode.start <= offset && templateNode.end >= offset; - if (!isWithin) { + if (!isWithin || key !== 'children') { this.skip(); return; } - if ( - (node.type.endsWith('Block') && independentBlocks.includes(node.type)) || - node.type.endsWith('Tag') - ) { - nearest = templateNode; + if (node.type.endsWith('Block') || node.type.endsWith('Tag')) { + candidate = templateNode; return; } - - if (key === 'attributes') { - this.skip(); - } } }); - return nearest; + return candidate; } function getTagHighlight( offset: number, content: string, - nearest: TemplateNode + candidate: TemplateNode ): DocumentHighlight[] | null { const name = - nearest.type === 'RawMustacheTag' + candidate.type === 'RawMustacheTag' ? 'html' - : nearest.type.replace('Tag', '').toLocaleLowerCase(); + : candidate.type.replace('Tag', '').toLocaleLowerCase(); const startTag = '@' + name; - const indexOfName = content.indexOf(startTag, nearest.start); + const indexOfName = content.indexOf(startTag, candidate.start); - if (indexOfName < 0 || indexOfName > offset || nearest.start + startTag.length < offset) { + if (indexOfName < 0 || indexOfName > offset || candidate.start + startTag.length < offset) { return null; } @@ -121,12 +113,12 @@ function getTagHighlight( function getBlockHighlight( offset: number, content: string, - nearest: TemplateNode + candidate: TemplateNode ): DocumentHighlight[] | null { - const name = nearest.type.replace('Block', '').toLowerCase(); + const name = candidate.type.replace('Block', '').toLowerCase(); const startTag = '#' + name; - const startTagStart = content.indexOf(startTag, nearest.start); + const startTagStart = content.indexOf(startTag, candidate.start); if (startTagStart < 0) { return null; @@ -137,16 +129,18 @@ function getBlockHighlight( ranges.push([startTagStart, startTagStart + startTag.length]); const endTag = '/' + name; - const endTagStart = content.lastIndexOf(endTag, nearest.end); + const endTagStart = content.lastIndexOf(endTag, candidate.end); ranges.push([endTagStart, endTagStart + endTag.length]); - if (nearest.type === 'EachBlock' && nearest.else) { - const elseStart = content.lastIndexOf(':else', nearest.else.start); + if (candidate.type === 'EachBlock' && candidate.else) { + const elseStart = content.lastIndexOf(':else', candidate.else.start); ranges.push([elseStart, elseStart + ':else'.length]); } + ranges.push(...gatherElseHighlightsForIfBlock(candidate, content)); + if (!ranges.some(([start, end]) => offset >= start && offset <= end)) { return null; } @@ -156,3 +150,37 @@ function getBlockHighlight( kind: DocumentHighlightKind.Read })); } + +function gatherElseHighlightsForIfBlock( + candidate: TemplateNode, + content: string +): Array<[start: number, end: number]> { + if (candidate.type !== 'IfBlock' || !candidate.else) { + return []; + } + + const ranges: Array<[start: number, end: number]> = []; + + walk(candidate.else, { + enter(node) { + const templateNode = node as TemplateNode; + if (templateNode.type === 'IfBlock' && templateNode.elseif) { + const elseIfStart = content.lastIndexOf(':else if', templateNode.expression.start); + + if (elseIfStart > 0) { + ranges.push([elseIfStart, elseIfStart + ':else if'.length]); + } + } + + if (templateNode.type === 'ElseBlock') { + const elseStart = content.lastIndexOf(':else', templateNode.start); + + if (elseStart > 0) { + ranges.push([elseStart, elseStart + ':else'.length]); + } + } + } + }); + + return ranges; +} From 824dca24f81c618680e0fa4d9b766d2e5222d888 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Wed, 2 Mar 2022 10:48:00 +0800 Subject: [PATCH 07/20] await block --- .../svelte/features/getDocumentHighlight.ts | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts index 73a5dbe4b..3eff2216f 100644 --- a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts +++ b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts @@ -6,6 +6,8 @@ import { Document, mapObjWithRangeToOriginal, offsetAt, positionAt } from '../.. import { SvelteDocument } from '../SvelteDocument'; import { inStyleOrScript } from '../utils'; +type RangeTupleArray = Array<[start: number, end: number]>; + export async function getDocumentHighlight( document: Document, svelteDoc: SvelteDocument, @@ -28,7 +30,11 @@ export async function getDocumentHighlight( // use last 10 and next 10 characters, should cover 99% of all cases .substr(offsetStart, 20); - if (!['#', '/', ':', '@'].some((char) => charactersAroundOffset.includes(char))) { + if ( + !['#', '/', ':', '@', 'then', 'catch'].some((keyword) => + charactersAroundOffset.includes(keyword) + ) + ) { return null; } @@ -124,7 +130,7 @@ function getBlockHighlight( return null; } - const ranges: Array<[start: number, end: number]> = []; + const ranges: RangeTupleArray = []; ranges.push([startTagStart, startTagStart + startTag.length]); @@ -139,7 +145,10 @@ function getBlockHighlight( ranges.push([elseStart, elseStart + ':else'.length]); } - ranges.push(...gatherElseHighlightsForIfBlock(candidate, content)); + ranges.push( + ...getElseHighlightsForIfBlock(candidate, content), + ...getAwaitBlockHighlight(candidate, content) + ); if (!ranges.some(([start, end]) => offset >= start && offset <= end)) { return null; @@ -151,15 +160,12 @@ function getBlockHighlight( })); } -function gatherElseHighlightsForIfBlock( - candidate: TemplateNode, - content: string -): Array<[start: number, end: number]> { +function getElseHighlightsForIfBlock(candidate: TemplateNode, content: string): RangeTupleArray { if (candidate.type !== 'IfBlock' || !candidate.else) { return []; } - const ranges: Array<[start: number, end: number]> = []; + const ranges: RangeTupleArray = []; walk(candidate.else, { enter(node) { @@ -184,3 +190,36 @@ function gatherElseHighlightsForIfBlock( return ranges; } + +function getAwaitBlockHighlight(candidate: TemplateNode, content: string): RangeTupleArray { + if (candidate.type !== 'AwaitBlock' || (candidate.then.skip && candidate.catch.skip)) { + return []; + } + + const ranges: RangeTupleArray = []; + + if (candidate.value) { + const thenKeyword = candidate.pending.skip ? 'then' : ':then'; + + const thenStart = content.lastIndexOf(thenKeyword, candidate.value.start); + + ranges.push([thenStart, thenStart + thenKeyword.length]); + } + + // {#await promise catch error} or {:catch error} + if (candidate.error) { + const catchKeyword = candidate.pending.skip && candidate.then.skip ? 'catch' : ':catch'; + + const catchStart = content.lastIndexOf(catchKeyword, candidate.error.start); + + ranges.push([catchStart, catchStart + catchKeyword.length]); + } else if (!candidate.catch.skip) { + // {:catch} + + const catchStart = content.indexOf(':catch', candidate.catch.start); + + ranges.push([catchStart, catchStart + ':catch'.length]); + } + + return ranges; +} From c83869d8a4bd62a264d2c6cb825cb5341b1916ea Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Thu, 3 Mar 2022 17:57:47 +0800 Subject: [PATCH 08/20] highlight in style attribute --- .../src/plugins/css/CSSPlugin.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/language-server/src/plugins/css/CSSPlugin.ts b/packages/language-server/src/plugins/css/CSSPlugin.ts index 9c972ba4b..ba0054814 100644 --- a/packages/language-server/src/plugins/css/CSSPlugin.ts +++ b/packages/language-server/src/plugins/css/CSSPlugin.ts @@ -362,6 +362,29 @@ export class CSSPlugin findDocumentHighlight(document: Document, position: Position): DocumentHighlight[] | null { const cssDocument = this.getCSSDoc(document); + if (cssDocument.isInGenerated(position)) { + return this.findDocumentHighlightInternal(cssDocument, position); + } + + const attributeContext = getAttributeContextAtPosition(document, position); + if ( + attributeContext && + this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText()) + ) { + const [start, end] = attributeContext.valueRange; + return this.findDocumentHighlightInternal( + new StyleAttributeDocument(document, start, end), + position + ); + } + + return null; + } + + findDocumentHighlightInternal( + cssDocument: CSSDocumentBase, + position: Position + ): DocumentHighlight[] | null { if (!cssDocument.isInGenerated(position)) { return null; } From c66512428e8d1e88bc0fbbe0c2ce111f5f501094 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Thu, 3 Mar 2022 17:58:12 +0800 Subject: [PATCH 09/20] exclude unsupported --- .../src/plugins/css/CSSPlugin.ts | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/language-server/src/plugins/css/CSSPlugin.ts b/packages/language-server/src/plugins/css/CSSPlugin.ts index ba0054814..947de6f94 100644 --- a/packages/language-server/src/plugins/css/CSSPlugin.ts +++ b/packages/language-server/src/plugins/css/CSSPlugin.ts @@ -391,11 +391,17 @@ export class CSSPlugin const kind = extractLanguage(cssDocument); - const result = getLanguageService(kind).findDocumentHighlights( - cssDocument, - cssDocument.getGeneratedPosition(position), - cssDocument.stylesheet - ).map(highlight => mapObjWithRangeToOriginal(cssDocument, highlight)); + if (shouldExcludeDocumentHighlights(cssDocument)) { + return null; + } + + const result = getLanguageService(kind) + .findDocumentHighlights( + cssDocument, + cssDocument.getGeneratedPosition(position), + cssDocument.stylesheet + ) + .map((highlight) => mapObjWithRangeToOriginal(cssDocument, highlight)); return result; } @@ -478,6 +484,17 @@ function shouldExcludeColor(document: CSSDocument) { } } +function shouldExcludeDocumentHighlights(document: CSSDocumentBase) { + switch (extractLanguage(document)) { + case 'sass': + case 'stylus': + case 'styl': + return true; + default: + return false; + } +} + function isSASS(document: CSSDocumentBase) { switch (extractLanguage(document)) { case 'sass': From f409412e88487c66b1542ad70946db98420c8fea Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Thu, 3 Mar 2022 18:06:40 +0800 Subject: [PATCH 10/20] don't filter out highlights if original is not in it function and class highlght its name --- .../typescript/features/DocumentHighlightProvider.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts index 786547c73..83248a35f 100644 --- a/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts +++ b/packages/language-server/src/plugins/typescript/features/DocumentHighlightProvider.ts @@ -2,7 +2,7 @@ import ts from 'typescript'; import { Position, DocumentHighlight } from 'vscode-languageserver-protocol'; import { DocumentHighlightKind } from 'vscode-languageserver-types'; import { Document } from '../../../lib/documents'; -import { flatten, isInRange, isSamePosition } from '../../../utils'; +import { flatten, isSamePosition } from '../../../utils'; import { DocumentHighlightProvider } from '../../interfaces'; import { LSAndTSDocResolver } from '../LSAndTSDocResolver'; import { convertToLocationRange } from '../utils'; @@ -36,20 +36,13 @@ export class DocumentHighlightProviderImpl implements DocumentHighlightProvider ) .filter((highlight) => !isSamePosition(highlight.range.start, highlight.range.end)); - if (!result.length || !this.containsOriginalPosition(result, position)) { + if (!result.length) { return null; } return result; } - /** - * If position in not in any of the ranges. It's probably got a generated position in a weird places - */ - private containsOriginalPosition(result: DocumentHighlight[], position: Position): boolean { - return result.some((highlight) => isInRange(highlight.range, position)); - } - private convertHighlightKind(highlight: ts.HighlightSpan): DocumentHighlightKind | undefined { return highlight.kind === ts.HighlightSpanKind.writtenReference ? DocumentHighlightKind.Write From afefc49dd4d75b31395941dc7b0ac6a1646fa91b Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Tue, 8 Mar 2022 17:34:52 +0800 Subject: [PATCH 11/20] config --- packages/language-server/README.md | 20 ++++++++++++++++ packages/language-server/src/ls-config.ts | 22 ++++++++++++++--- .../src/plugins/css/CSSPlugin.ts | 4 ++++ .../src/plugins/html/HTMLPlugin.ts | 9 ++++--- .../src/plugins/svelte/SveltePlugin.ts | 4 ++++ .../plugins/typescript/TypeScriptPlugin.ts | 4 ++++ packages/svelte-vscode/package.json | 24 +++++++++++++++++++ 7 files changed, 79 insertions(+), 8 deletions(-) diff --git a/packages/language-server/README.md b/packages/language-server/README.md index e5e350584..54c18b4c2 100644 --- a/packages/language-server/README.md +++ b/packages/language-server/README.md @@ -151,6 +151,14 @@ Enable semantic tokens (semantic highlight) for TypeScript. _Default_: `true` Enable go to implementation for Typescript. _Default_: `true` +#### `svelte.plugin.typescript.typeDefinition.enable` + +Enable go to Type Definition for Typescript. _Default_: `true` + +#### `svelte.plugin.typescript.documentHighlight.enable` + +Enable document highlight for Typescript. _Default_: `true` + ##### `svelte.plugin.css.enable` Enable the CSS plugin. _Default_: `true` @@ -192,6 +200,10 @@ Enable document symbols for CSS. _Default_: `true` Enable selection range for CSS. _Default_: `true` +#### `svelte.plugin.css.documentHighlight.enable` + +Enable document highlight for CSS. _Default_: `true` + ##### `svelte.plugin.html.enable` Enable the HTML plugin. _Default_: `true` @@ -225,6 +237,10 @@ Enable Linked Editing for HTML. _Default_: `true` Enable rename tags for the opening/closing tag pairs in HTML. _Default_: `true` +#### `svelte.plugin.html.documentHighlight.enable` + +Enable document highlight for HTML. _Default_: `true` + ##### `svelte.plugin.svelte.enable` Enable the Svelte plugin. _Default_: `true` @@ -305,6 +321,10 @@ Enable code actions for Svelte. _Default_: `true` Enable selection range for Svelte. _Default_: `true` +#### `svelte.plugin.svelte.documentHighlight.enable` + +Enable document highlight for Svelte tags or block. _Default_: `true` + ##### `svelte.plugin.svelte.defaultScriptLanguage` The default language to use when generating new script tags in Svelte. _Default_: `none` diff --git a/packages/language-server/src/ls-config.ts b/packages/language-server/src/ls-config.ts index 75278af7f..411ec2d4f 100644 --- a/packages/language-server/src/ls-config.ts +++ b/packages/language-server/src/ls-config.ts @@ -21,7 +21,8 @@ const defaultLSConfig: LSConfig = { signatureHelp: { enable: true }, semanticTokens: { enable: true }, implementation: { enable: true }, - typeDefinition: { enable: true } + typeDefinition: { enable: true }, + documentHighlight: { enable: true } }, css: { enable: true, @@ -32,7 +33,8 @@ const defaultLSConfig: LSConfig = { documentColors: { enable: true }, colorPresentations: { enable: true }, documentSymbols: { enable: true }, - selectionRange: { enable: true } + selectionRange: { enable: true }, + documentHighlight: { enable: true } }, html: { enable: true, @@ -41,7 +43,8 @@ const defaultLSConfig: LSConfig = { tagComplete: { enable: true }, documentSymbols: { enable: true }, renameTags: { enable: true }, - linkedEditing: { enable: true } + linkedEditing: { enable: true }, + documentHighlight: { enable: true } }, svelte: { enable: true, @@ -65,6 +68,7 @@ const defaultLSConfig: LSConfig = { hover: { enable: true }, codeActions: { enable: true }, selectionRange: { enable: true }, + documentHighlight: { enable: true }, defaultScriptLanguage: 'none' } }; @@ -121,6 +125,9 @@ export interface LSTypescriptConfig { typeDefinition: { enable: boolean; }; + documentHighlight: { + enable: boolean; + }; } export interface LSCSSConfig { @@ -148,6 +155,9 @@ export interface LSCSSConfig { selectionRange: { enable: boolean; }; + documentHighlight: { + enable: boolean; + }; } export interface LSHTMLConfig { @@ -171,6 +181,9 @@ export interface LSHTMLConfig { linkedEditing: { enable: boolean; }; + documentHighlight: { + enable: boolean; + }; } export type CompilerWarningsSettings = Record; @@ -209,6 +222,9 @@ export interface LSSvelteConfig { selectionRange: { enable: boolean; }; + documentHighlight: { + enable: boolean; + }; defaultScriptLanguage: 'none' | 'ts'; } diff --git a/packages/language-server/src/plugins/css/CSSPlugin.ts b/packages/language-server/src/plugins/css/CSSPlugin.ts index 947de6f94..4815637d0 100644 --- a/packages/language-server/src/plugins/css/CSSPlugin.ts +++ b/packages/language-server/src/plugins/css/CSSPlugin.ts @@ -360,6 +360,10 @@ export class CSSPlugin } findDocumentHighlight(document: Document, position: Position): DocumentHighlight[] | null { + if (!this.featureEnabled('documentHighlight')) { + return null; + } + const cssDocument = this.getCSSDoc(document); if (cssDocument.isInGenerated(position)) { diff --git a/packages/language-server/src/plugins/html/HTMLPlugin.ts b/packages/language-server/src/plugins/html/HTMLPlugin.ts index 0565afe94..19a204109 100644 --- a/packages/language-server/src/plugins/html/HTMLPlugin.ts +++ b/packages/language-server/src/plugins/html/HTMLPlugin.ts @@ -302,16 +302,15 @@ export class HTMLPlugin document: Document, position: Position ): DocumentHighlight[] | null { + if (!this.featureEnabled('documentHighlight')) { + return null; + } + const html = this.documents.get(document); if (!html) { return null; } - // const node = html.findNodeAt(document.offsetAt(position)); - // if (!node || this.possiblyComponent(node)) { - // return null; - // } - const result = this.lang.findDocumentHighlights(document, position, html); if (!result.length) { diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index 8df12f772..9aaf27c50 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -221,6 +221,10 @@ export class SveltePlugin document: Document, position: Position ): Promise { + if (!this.featureEnabled('documentHighlight')) { + return null; + } + const svelteDoc = await this.getSvelteDoc(document); return getDocumentHighlight(document, svelteDoc, position); diff --git a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts index 9e10c767d..b1a9f8db5 100644 --- a/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts +++ b/packages/language-server/src/plugins/typescript/TypeScriptPlugin.ts @@ -530,6 +530,10 @@ export class TypeScriptPlugin document: Document, position: Position ): Promise { + if (!this.featureEnabled('documentHighlight')) { + return null; + } + return this.documentHeightProvider.findDocumentHighlight(document, position); } diff --git a/packages/svelte-vscode/package.json b/packages/svelte-vscode/package.json index 4da86e2aa..5b0138022 100644 --- a/packages/svelte-vscode/package.json +++ b/packages/svelte-vscode/package.json @@ -186,6 +186,12 @@ "title": "Typescript: Go to Type Definition", "description": "Enable go to Type Definition for Typescript" }, + "svelte.plugin.typescript.documentHighlight.enable": { + "type": "boolean", + "default": true, + "title": "Typescript: Document Highlight", + "description": "Enable document highlight for Typescript" + }, "svelte.plugin.css.enable": { "type": "boolean", "default": true, @@ -246,6 +252,12 @@ "title": "CSS: SelectionRange", "description": "Enable selection range for CSS" }, + "svelte.plugin.css.documentHighlight.enable": { + "type": "boolean", + "default": true, + "title": "CSS: Document Highlight", + "description": "Enable document highlight for CSS" + }, "svelte.plugin.html.enable": { "type": "boolean", "default": true, @@ -294,6 +306,12 @@ "title": "HTML: Rename tags", "description": "Enable rename for the opening/closing tag pairs in HTML" }, + "svelte.plugin.html.documentHighlight.enable": { + "type": "boolean", + "default": true, + "title": "HTML: Document Highlight", + "description": "Enable document highlight for HTML" + }, "svelte.plugin.svelte.enable": { "type": "boolean", "default": true, @@ -403,6 +421,12 @@ "title": "Svelte: Rename", "description": "Enable rename/move Svelte files functionality" }, + "svelte.plugin.svelte.documentHighlight.enable": { + "type": "boolean", + "default": true, + "title": "Svelte: Document Highlight", + "description": "Enable document highlight for svelte tags or block" + }, "svelte.plugin.svelte.defaultScriptLanguage": { "type": "string", "default": "none", From 98892a116d1e6134384eadf706c0faeeef313831 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Tue, 8 Mar 2022 18:05:11 +0800 Subject: [PATCH 12/20] ts, html and css test --- .../src/plugins/css/CSSPlugin.ts | 2 +- .../test/plugins/css/CSSPlugin.test.ts | 63 +++++++++++++- .../test/plugins/html/HTMLPlugin.test.ts | 39 ++++++++- .../DocumentHighlightProvider.test.ts | 86 +++++++++++++++++++ .../document-highlight.svelte | 9 ++ 5 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 packages/language-server/test/plugins/typescript/features/DocumentHighlightProvider.test.ts create mode 100644 packages/language-server/test/plugins/typescript/testfiles/document-highlight/document-highlight.svelte diff --git a/packages/language-server/src/plugins/css/CSSPlugin.ts b/packages/language-server/src/plugins/css/CSSPlugin.ts index 4815637d0..091970cd3 100644 --- a/packages/language-server/src/plugins/css/CSSPlugin.ts +++ b/packages/language-server/src/plugins/css/CSSPlugin.ts @@ -385,7 +385,7 @@ export class CSSPlugin return null; } - findDocumentHighlightInternal( + private findDocumentHighlightInternal( cssDocument: CSSDocumentBase, position: Position ): DocumentHighlight[] | null { diff --git a/packages/language-server/test/plugins/css/CSSPlugin.test.ts b/packages/language-server/test/plugins/css/CSSPlugin.test.ts index cc029d3ee..6754e09b5 100644 --- a/packages/language-server/test/plugins/css/CSSPlugin.test.ts +++ b/packages/language-server/test/plugins/css/CSSPlugin.test.ts @@ -8,7 +8,9 @@ import { TextEdit, CompletionContext, SelectionRange, - CompletionTriggerKind + CompletionTriggerKind, + DocumentHighlight, + DocumentHighlightKind } from 'vscode-languageserver'; import { DocumentManager, Document } from '../../../src/lib/documents'; import { CSSPlugin } from '../../../src/plugins'; @@ -407,4 +409,63 @@ describe('CSS Plugin', () => { assert.equal(selectionRange, null); }); + + describe('document highlight', () => { + it('provide document highlight', () => { + const { plugin, document } = setup(''); + + const highlight = plugin.findDocumentHighlight(document, Position.create(0, 9)); + + assert.deepStrictEqual(highlight, [ + { + range: { + start: { + line: 0, + character: 7 + }, + end: { + line: 0, + character: 10 + } + }, + kind: DocumentHighlightKind.Write + }, + { + range: { + start: { + line: 0, + character: 20 + }, + end: { + line: 0, + character: 23 + } + }, + kind: DocumentHighlightKind.Read + } + ]); + }); + + it('provide document highlight for style attribute', () => { + const { plugin, document } = setup('
'); + + const highlight = plugin.findDocumentHighlight(document, Position.create(0, 13)); + + assert.deepStrictEqual(highlight, [ + { + range: { + start: { + line: 0, + character: 12 + }, + end: { + line: 0, + character: 20 + } + }, + kind: DocumentHighlightKind.Read + } + ]); + }); + }); }); diff --git a/packages/language-server/test/plugins/html/HTMLPlugin.test.ts b/packages/language-server/test/plugins/html/HTMLPlugin.test.ts index 4ef9ae134..93daa41e8 100644 --- a/packages/language-server/test/plugins/html/HTMLPlugin.test.ts +++ b/packages/language-server/test/plugins/html/HTMLPlugin.test.ts @@ -6,11 +6,13 @@ import { CompletionItem, TextEdit, CompletionItemKind, - InsertTextFormat + InsertTextFormat, + DocumentHighlightKind } from 'vscode-languageserver'; import { HTMLPlugin } from '../../../src/plugins'; import { DocumentManager, Document } from '../../../src/lib/documents'; import { LSConfigManager } from '../../../src/ls-config'; +import { DocumentHighlight } from 'vscode-languageserver-types'; describe('HTML Plugin', () => { function setup(content: string) { @@ -199,4 +201,39 @@ describe('HTML Plugin', () => { ] }); }); + + it('provide document highlight', () => { + const { plugin, document } = setup('
'); + + const highlight = plugin.findDocumentHighlight(document, Position.create(0, 1)); + + assert.deepStrictEqual(highlight, [ + { + range: { + start: { + line: 0, + character: 1 + }, + end: { + line: 0, + character: 4 + } + }, + kind: DocumentHighlightKind.Read + }, + { + range: { + start: { + line: 0, + character: 7 + }, + end: { + line: 0, + character: 10 + } + }, + kind: DocumentHighlightKind.Read + } + ]); + }); }); diff --git a/packages/language-server/test/plugins/typescript/features/DocumentHighlightProvider.test.ts b/packages/language-server/test/plugins/typescript/features/DocumentHighlightProvider.test.ts new file mode 100644 index 000000000..325c07874 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/features/DocumentHighlightProvider.test.ts @@ -0,0 +1,86 @@ +import assert from 'assert'; +import path from 'path'; +import ts from 'typescript'; +import { DocumentHighlight, DocumentHighlightKind } from 'vscode-languageserver'; +import { Document, DocumentManager } from '../../../../src/lib/documents'; +import { LSConfigManager } from '../../../../src/ls-config'; +import { LSAndTSDocResolver } from '../../../../src/plugins'; +import { DocumentHighlightProviderImpl } from '../../../../src/plugins/typescript/features/DocumentHighlightProvider'; +import { pathToUrl } from '../../../../src/utils'; + +const testDir = path.join(__dirname, '..'); + +describe('DocumentHighlightProvider', () => { + function getFullPath(filename: string) { + return path.join(testDir, 'testfiles', 'document-highlight', filename); + } + + function setup(filename: string) { + const docManager = new DocumentManager( + (textDocument) => new Document(textDocument.uri, textDocument.text) + ); + const lsAndTsDocResolver = new LSAndTSDocResolver( + docManager, + [testDir], + new LSConfigManager() + ); + const provider = new DocumentHighlightProviderImpl(lsAndTsDocResolver); + const filePath = getFullPath(filename); + const document = docManager.openDocument({ + uri: pathToUrl(filePath), + text: ts.sys.readFile(filePath) || '' + }); + return { provider, document }; + } + + it('find document highlight', async () => { + const { document, provider } = setup('document-highlight.svelte'); + + const highlight = await provider.findDocumentHighlight(document, { + line: 1, + character: 9 + }); + + assert.deepStrictEqual(highlight, [ + { + range: { + start: { + line: 1, + character: 8 + }, + end: { + line: 1, + character: 12 + } + }, + kind: DocumentHighlightKind.Write + }, + { + range: { + start: { + line: 3, + character: 8 + }, + end: { + line: 3, + character: 12 + } + }, + kind: DocumentHighlightKind.Read + }, + { + range: { + start: { + line: 8, + character: 1 + }, + end: { + line: 8, + character: 5 + } + }, + kind: DocumentHighlightKind.Read + } + ]); + }); +}); diff --git a/packages/language-server/test/plugins/typescript/testfiles/document-highlight/document-highlight.svelte b/packages/language-server/test/plugins/typescript/testfiles/document-highlight/document-highlight.svelte new file mode 100644 index 000000000..22626b885 --- /dev/null +++ b/packages/language-server/test/plugins/typescript/testfiles/document-highlight/document-highlight.svelte @@ -0,0 +1,9 @@ + + +{prop} \ No newline at end of file From 68582bd42b92edaa485a990e79ba5febbc8efac2 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Wed, 9 Mar 2022 14:18:07 +0800 Subject: [PATCH 13/20] svelte test --- .../src/plugins/svelte/SveltePlugin.ts | 2 +- .../svelte/features/getDocumentHighlight.ts | 9 +- .../features/getDocumentHighlight.test.ts | 144 ++++++++++++++++++ 3 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 packages/language-server/test/plugins/svelte/features/getDocumentHighlight.test.ts diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index 9aaf27c50..bdb2b275a 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -227,7 +227,7 @@ export class SveltePlugin const svelteDoc = await this.getSvelteDoc(document); - return getDocumentHighlight(document, svelteDoc, position); + return getDocumentHighlight(svelteDoc, position); } private featureEnabled(feature: keyof LSSvelteConfig) { diff --git a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts index 3eff2216f..1c92ffe56 100644 --- a/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts +++ b/packages/language-server/src/plugins/svelte/features/getDocumentHighlight.ts @@ -2,14 +2,13 @@ import { walk } from 'svelte/compiler'; import { TemplateNode } from 'svelte/types/compiler/interfaces'; import { Range } from 'vscode-languageserver'; import { Position, DocumentHighlight, DocumentHighlightKind } from 'vscode-languageserver-types'; -import { Document, mapObjWithRangeToOriginal, offsetAt, positionAt } from '../../../lib/documents'; +import { mapObjWithRangeToOriginal, offsetAt, positionAt } from '../../../lib/documents'; import { SvelteDocument } from '../SvelteDocument'; import { inStyleOrScript } from '../utils'; type RangeTupleArray = Array<[start: number, end: number]>; export async function getDocumentHighlight( - document: Document, svelteDoc: SvelteDocument, position: Position ): Promise { @@ -108,6 +107,7 @@ function getTagHighlight( return [ { + kind: DocumentHighlightKind.Read, range: Range.create( positionAt(indexOfName, content), positionAt(indexOfName + startTag.length, content) @@ -181,7 +181,10 @@ function getElseHighlightsForIfBlock(candidate: TemplateNode, content: string): if (templateNode.type === 'ElseBlock') { const elseStart = content.lastIndexOf(':else', templateNode.start); - if (elseStart > 0) { + if ( + elseStart > 0 && + content.slice(elseStart, elseStart + ':else if'.length) !== ':else if' + ) { ranges.push([elseStart, elseStart + ':else'.length]); } } diff --git a/packages/language-server/test/plugins/svelte/features/getDocumentHighlight.test.ts b/packages/language-server/test/plugins/svelte/features/getDocumentHighlight.test.ts new file mode 100644 index 000000000..6850a9fac --- /dev/null +++ b/packages/language-server/test/plugins/svelte/features/getDocumentHighlight.test.ts @@ -0,0 +1,144 @@ +import * as assert from 'assert'; +import { DocumentHighlight, DocumentHighlightKind } from 'vscode-languageserver'; +import { SvelteDocument } from '../../../../src/plugins/svelte/SvelteDocument'; +import { Document } from '../../../../src/lib/documents'; +import { getDocumentHighlight } from '../../../../src/plugins/svelte/features/getDocumentHighlight'; + +describe('SveltePlugin#getDocumentHighlight', () => { + async function testSameHighlight( + content: string, + tests: number[], + expected: Array<[start: number, end: number]> + ) { + const svelteDoc = createDoc(content); + + for (const position of tests) { + await testOne(svelteDoc, position, expected); + } + } + + function createDoc(content: string) { + return new SvelteDocument(new Document('url', content)); + } + + async function testOne( + svelteDoc: SvelteDocument, + character: number, + expected: Array<[start: number, end: number]> | null + ) { + const documentHighlight = await getDocumentHighlight(svelteDoc, { line: 0, character }); + + assert.deepStrictEqual( + documentHighlight?.sort((a, b) => a.range.start.character - b.range.start.character), + expected?.map( + ([start, end]): DocumentHighlight => ({ + kind: DocumentHighlightKind.Read, + range: { + start: { line: 0, character: start }, + end: { line: 0, character: end } + } + }) + ) + ); + } + + it('should return null for style and script', async () => { + await testOne(createDoc(''), 7, null); + await testOne(createDoc(''), 8, null); + }); + + it('get highlight for key block', async () => { + await testSameHighlight( + '{#key foo}{/key}', + [2, 12], + [ + [1, 5], + [11, 15] + ] + ); + }); + + it('get highlight for each block', async () => { + await testSameHighlight( + '{#each expression as name}{:else}{/each}', + [2, 28, 35], + [ + [1, 6], + [27, 32], + [34, 39] + ] + ); + }); + + it('get highlight for if block', async () => { + await testSameHighlight( + '{#if expression}{:else if foo}{:else}{/if}', + [2, 18, 32, 39], + [ + [1, 4], + [17, 25], + [31, 36], + [38, 41] + ] + ); + }); + + it("doesn't get highlights from another if block nested inside", async () => { + await testOne(createDoc('{#if expression}{:else if hi}{#if hi}{/if}{/if}'), 2, [ + [1, 4], + [17, 25], + [43, 46] + ]); + }); + + it('get highlight for await block', async () => { + await testSameHighlight( + '{#await expression}{:then name}{:catch name}{/await}', + [2, 21, 33, 46], + [ + [1, 7], + [20, 25], + [32, 38], + [45, 51] + ] + ); + }); + + it('get highlight for await block (skip pending)', async () => { + await testSameHighlight( + '{#await expression then name}{/await}', + [2, 20, 30], + [ + [1, 7], + [19, 23], + [30, 36] + ] + ); + }); + + it('get highlight for await block (skip pending and then)', async () => { + await testSameHighlight( + '{#await expression catch name}{/await}', + [2, 20, 31], + [ + [1, 7], + [19, 24], + [31, 37] + ] + ); + }); + + it('get highlight for debug tag', async () => { + await testOne(createDoc('{@debug name}'), 2, [[1, 7]]); + }); + + it('get highlight for html tag', async () => { + await testOne(createDoc('{@html name}'), 2, [[1, 6]]); + }); + + it('get highlight for const tag', async () => { + await testOne(createDoc('{#each expression as item}{@const name = item}{/each}'), 28, [ + [27, 33] + ]); + }); +}); From ac2147cc1a805072b4ba101e8d58310adbfb15ef Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Wed, 9 Mar 2022 14:20:16 +0800 Subject: [PATCH 14/20] format --- packages/language-server/src/plugins/html/HTMLPlugin.ts | 6 +----- packages/language-server/src/plugins/interfaces.ts | 2 +- packages/language-server/src/plugins/svelte/utils.ts | 6 ++++-- packages/language-server/src/server.ts | 7 ++++--- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/language-server/src/plugins/html/HTMLPlugin.ts b/packages/language-server/src/plugins/html/HTMLPlugin.ts index 19a204109..3b0df0813 100644 --- a/packages/language-server/src/plugins/html/HTMLPlugin.ts +++ b/packages/language-server/src/plugins/html/HTMLPlugin.ts @@ -37,7 +37,6 @@ import { isInsideMoustacheTag, toRange } from '../../lib/documents/utils'; import { possiblyComponent } from '../../utils'; export class HTMLPlugin - implements HoverProvider, CompletionsProvider, @@ -298,10 +297,7 @@ export class HTMLPlugin return { ranges }; } - findDocumentHighlight( - document: Document, - position: Position - ): DocumentHighlight[] | null { + findDocumentHighlight(document: Document, position: Position): DocumentHighlight[] | null { if (!this.featureEnabled('documentHighlight')) { return null; } diff --git a/packages/language-server/src/plugins/interfaces.ts b/packages/language-server/src/plugins/interfaces.ts index b382caf49..b98ed9b49 100644 --- a/packages/language-server/src/plugins/interfaces.ts +++ b/packages/language-server/src/plugins/interfaces.ts @@ -180,7 +180,7 @@ export interface DocumentHighlightProvider { findDocumentHighlight( document: Document, position: Position - ): Resolvable + ): Resolvable; } export interface OnWatchFileChangesPara { diff --git a/packages/language-server/src/plugins/svelte/utils.ts b/packages/language-server/src/plugins/svelte/utils.ts index 9d0ef1de7..188bcb894 100644 --- a/packages/language-server/src/plugins/svelte/utils.ts +++ b/packages/language-server/src/plugins/svelte/utils.ts @@ -3,7 +3,9 @@ import { isInTag } from '../../lib/documents'; import { SvelteDocument } from './SvelteDocument'; export function inStyleOrScript(svelteDoc: SvelteDocument, position: Position) { - return isInTag(position, svelteDoc.style) || + return ( + isInTag(position, svelteDoc.style) || isInTag(position, svelteDoc.script) || - isInTag(position, svelteDoc.moduleScript); + isInTag(position, svelteDoc.moduleScript) + ); } diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index 6d7e3ba8d..25275e119 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -353,15 +353,16 @@ export function startServer(options?: LSOptions) { ); connection.onImplementation((evt) => - pluginHost.getImplementation(evt.textDocument, evt.position) + pluginHost.getImplementation(evt.textDocument, evt.position) ); connection.onTypeDefinition((evt) => - pluginHost.getTypeDefinition(evt.textDocument, evt.position) + pluginHost.getTypeDefinition(evt.textDocument, evt.position) ); connection.onDocumentHighlight((evt) => - pluginHost.findDocumentHighlight(evt.textDocument, evt.position)); + pluginHost.findDocumentHighlight(evt.textDocument, evt.position) + ); const diagnosticsManager = new DiagnosticsManager( connection.sendDiagnostics, From 6ca9eb702a8bf020fcf86051cd6e352df12fdcd8 Mon Sep 17 00:00:00 2001 From: "Lyu, Wei Da" Date: Wed, 9 Mar 2022 14:25:44 +0800 Subject: [PATCH 15/20] merge two utils files --- .../src/plugins/svelte/features/getCompletions.ts | 10 +++------- .../plugins/svelte/features/getDocumentHighlight.ts | 2 +- .../src/plugins/svelte/features/getHoverInfo.ts | 7 ++----- .../src/plugins/svelte/features/getSelectionRanges.ts | 2 +- .../src/plugins/svelte/features/utils.ts | 11 +++++++++++ packages/language-server/src/plugins/svelte/utils.ts | 11 ----------- 6 files changed, 18 insertions(+), 25 deletions(-) delete mode 100644 packages/language-server/src/plugins/svelte/utils.ts diff --git a/packages/language-server/src/plugins/svelte/features/getCompletions.ts b/packages/language-server/src/plugins/svelte/features/getCompletions.ts index 606b36c0f..8e6aaf462 100644 --- a/packages/language-server/src/plugins/svelte/features/getCompletions.ts +++ b/packages/language-server/src/plugins/svelte/features/getCompletions.ts @@ -9,10 +9,10 @@ import { MarkupKind } from 'vscode-languageserver'; import { SvelteTag, documentation, getLatestOpeningTag } from './SvelteTags'; -import { isInTag, Document } from '../../../lib/documents'; +import { Document } from '../../../lib/documents'; import { AttributeContext, getAttributeContextAtPosition } from '../../../lib/documents/parseHtml'; import { getModifierData } from './getModifierData'; -import { attributeCanHaveEventModifier } from './utils'; +import { attributeCanHaveEventModifier, inStyleOrScript } from './utils'; const HTML_COMMENT_START = '