Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/language-server/src/ls-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const defaultLSConfig: LSConfig = {
completions: { enable: true, emmet: true },
tagComplete: { enable: true },
documentSymbols: { enable: true },
renameTags: { enable: true }
renameTags: { enable: true },
linkedEditing: { enable: true }
},
svelte: {
enable: true,
Expand Down Expand Up @@ -156,6 +157,9 @@ export interface LSHTMLConfig {
renameTags: {
enable: boolean;
};
linkedEditing: {
enable: boolean;
};
}

export type CompilerWarningsSettings = Record<string, 'ignore' | 'error'>;
Expand Down
17 changes: 17 additions & 0 deletions packages/language-server/src/plugins/PluginHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Diagnostic,
FormattingOptions,
Hover,
LinkedEditingRanges,
Location,
Position,
Range,
Expand Down Expand Up @@ -415,6 +416,22 @@ export class PluginHost implements LSProvider, OnWatchFileChanges {
);
}

async getLinkedEditingRanges(
textDocument: TextDocumentIdentifier,
position: Position
): Promise<LinkedEditingRanges | null> {
const document = this.getDocument(textDocument.uri);
if (!document) {
throw new Error('Cannot call methods on an unopened document');
}

return await this.execute<LinkedEditingRanges>(
'getLinkedEditingRanges',
[document, position],
ExecuteMode.FirstNonNull
);
}

onWatchFileChanges(onWatchFileChangesParas: OnWatchFileChangesPara[]): void {
for (const support of this.plugins) {
support.onWatchFileChanges?.(onWatchFileChangesParas);
Expand Down
33 changes: 30 additions & 3 deletions packages/language-server/src/plugins/html/HTMLPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
CompletionItemKind,
TextEdit,
Range,
WorkspaceEdit
WorkspaceEdit,
LinkedEditingRanges
} from 'vscode-languageserver';
import {
DocumentManager,
Expand All @@ -24,10 +25,16 @@ import {
} from '../../lib/documents';
import { LSConfigManager, LSHTMLConfig } from '../../ls-config';
import { svelteHtmlDataProvider } from './dataProvider';
import { HoverProvider, CompletionsProvider, RenameProvider } from '../interfaces';
import {
HoverProvider,
CompletionsProvider,
RenameProvider,
LinkedEditingRangesProvider
} from '../interfaces';
import { isInsideMoustacheTag, toRange } from '../../lib/documents/utils';

export class HTMLPlugin implements HoverProvider, CompletionsProvider, RenameProvider {
export class HTMLPlugin
implements HoverProvider, CompletionsProvider, RenameProvider, LinkedEditingRangesProvider {
private configManager: LSConfigManager;
private lang = getLanguageService({
customDataProviders: [svelteHtmlDataProvider],
Expand Down Expand Up @@ -210,6 +217,7 @@ export class HTMLPlugin implements HoverProvider, CompletionsProvider, RenamePro
if (!this.featureEnabled('renameTags')) {
return null;
}

const html = this.documents.get(document);
if (!html) {
return null;
Expand Down Expand Up @@ -248,6 +256,25 @@ export class HTMLPlugin implements HoverProvider, CompletionsProvider, RenamePro
return toRange(document.getText(), tagNameStart, tagNameStart + node.tag.length);
}

getLinkedEditingRanges(document: Document, position: Position): LinkedEditingRanges | null {
if (!this.featureEnabled('linkedEditing')) {
return null;
}

const html = this.documents.get(document);
if (!html) {
return null;
}

const ranges = this.lang.findLinkedEditingRanges(document, position, html);

if (!ranges) {
return null;
}

return { ranges };
}

/**
*
* The language service is case insensitive, and would provide
Expand Down
11 changes: 10 additions & 1 deletion packages/language-server/src/plugins/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
CompletionContext,
FileChangeType,
LinkedEditingRanges,
SemanticTokens,
SignatureHelpContext,
TextDocumentContentChangeEvent
Expand Down Expand Up @@ -151,6 +152,13 @@ export interface SemanticTokensProvider {
getSemanticTokens(textDocument: Document, range?: Range): Resolvable<SemanticTokens | null>;
}

export interface LinkedEditingRangesProvider {
getLinkedEditingRanges(
document: Document,
position: Position
): Resolvable<LinkedEditingRanges | null>;
}

export interface OnWatchFileChangesPara {
fileName: string;
changeType: FileChangeType;
Expand All @@ -177,7 +185,8 @@ type ProviderBase = DiagnosticsProvider &
FindReferencesProvider &
RenameProvider &
SignatureHelpProvider &
SemanticTokensProvider;
SemanticTokensProvider &
LinkedEditingRangesProvider;

export type LSProvider = ProviderBase & BackwardsCompatibleDefinitionsProvider;

Expand Down
11 changes: 9 additions & 2 deletions packages/language-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
WorkspaceEdit,
SemanticTokensRequest,
SemanticTokensRangeRequest,
DidChangeWatchedFilesParams
DidChangeWatchedFilesParams,
LinkedEditingRangeRequest
} from 'vscode-languageserver';
import { IPCMessageReader, IPCMessageWriter, createConnection } from 'vscode-languageserver/node';
import { DiagnosticsManager } from './lib/DiagnosticsManager';
Expand Down Expand Up @@ -203,7 +204,8 @@ export function startServer(options?: LSOptions) {
legend: getSemanticTokenLegends(),
range: true,
full: true
}
},
linkedEditingRangeProvider: true
}
};
});
Expand Down Expand Up @@ -329,6 +331,11 @@ export function startServer(options?: LSOptions) {
pluginHost.getSemanticTokens(evt.textDocument, evt.range)
);

connection.onRequest(
LinkedEditingRangeRequest.type,
async (evt) => await pluginHost.getLinkedEditingRanges(evt.textDocument, evt.position)
);

docManager.on(
'documentChange',
_.debounce(async (document: Document) => diagnosticsManager.update(document), 500)
Expand Down
12 changes: 12 additions & 0 deletions packages/language-server/test/plugins/html/HTMLPlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,16 @@ describe('HTML Plugin', () => {
renameInfo
);
});

it('provides linked editing ranges', async () => {
const { plugin, document } = setup('<div></div>');

const ranges = plugin.getLinkedEditingRanges(document, Position.create(0, 3));
assert.deepStrictEqual(ranges, {
ranges: [
{ start: { line: 0, character: 1 }, end: { line: 0, character: 4 } },
{ start: { line: 0, character: 7 }, end: { line: 0, character: 10 } }
]
});
});
});
4 changes: 4 additions & 0 deletions packages/svelte-vscode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ Enable HTML tag auto closing. _Default_: `true`

Enable document symbols for HTML. _Default_: `true`

##### `svelte.plugin.html.linkedEditing.enable`

Enable Linked Editing for HTML. _Default_: `true`

##### `svelte.plugin.html.renameTags.enable`

Enable rename tags for the opening/closing tag pairs in HTML. _Default_: `true`
Expand Down
6 changes: 6 additions & 0 deletions packages/svelte-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@
"title": "HTML: Symbols in Outline",
"description": "Enable document symbols for HTML"
},
"svelte.plugin.html.linkedEditing.enable": {
"type": "boolean",
"default": true,
"title": "HTML: Linked Editing",
"description": "Enable Linked Editing for HTML"
},
"svelte.plugin.html.renameTags.enable": {
"type": "boolean",
"default": true,
Expand Down