From 01fbe14e2adde08d53f564302f2964d5d94ad071 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 31 Oct 2024 21:16:11 +0100 Subject: [PATCH] feat: add runes mode indicator (#2554) adds a runes mode indicator atop of the file via a code lens. Will show "runes mode" if the components is in that mode, "legacy mode" if not, and nothing if it's not Svelte 5 #2418 --- .../src/plugins/svelte/SvelteDocument.ts | 17 +++++--- .../src/plugins/svelte/SveltePlugin.ts | 40 +++++++++++++++++++ packages/svelte-vscode/src/extension.ts | 10 +++++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/packages/language-server/src/plugins/svelte/SvelteDocument.ts b/packages/language-server/src/plugins/svelte/SvelteDocument.ts index 3213eff66..44ee3de46 100644 --- a/packages/language-server/src/plugins/svelte/SvelteDocument.ts +++ b/packages/language-server/src/plugins/svelte/SvelteDocument.ts @@ -48,6 +48,9 @@ export class SvelteDocument { public get config() { return this.parent.configPromise; } + public get isSvelte5() { + return this.getSvelteVersion()[0] > 4; + } constructor(private parent: Document) { this.script = this.parent.scriptInfo; @@ -70,11 +73,7 @@ export class SvelteDocument { async getTranspiled(): Promise { if (!this.transpiledDoc) { - if (!this.svelteVersion) { - const { major, minor } = getPackageInfo('svelte', this.getFilePath()).version; - this.svelteVersion = [major, minor]; - } - const [major, minor] = this.svelteVersion; + const [major, minor] = this.getSvelteVersion(); if (major > 3 || (major === 3 && minor >= 32)) { this.transpiledDoc = await TranspiledSvelteDocument.create( @@ -103,6 +102,14 @@ export class SvelteDocument { const svelte = importSvelte(this.getFilePath()); return svelte.compile((await this.getTranspiled()).getText(), options); } + + private getSvelteVersion() { + if (!this.svelteVersion) { + const { major, minor } = getPackageInfo('svelte', this.getFilePath()).version; + this.svelteVersion = [major, minor]; + } + return this.svelteVersion; + } } export interface ITranspiledSvelteDocument extends PositionMapper { diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index e9a39f4f5..aedc32e54 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -3,6 +3,7 @@ import { CancellationToken, CodeAction, CodeActionContext, + CodeLens, CompletionContext, CompletionList, Diagnostic, @@ -49,6 +50,45 @@ export class SveltePlugin constructor(private configManager: LSConfigManager) {} + async getCodeLens(document: Document): Promise { + const doc = await this.getSvelteDoc(document); + if (!doc.isSvelte5) return null; + + try { + const result = await doc.getCompiled(); + // @ts-ignore + const runes = result.metadata.runes as boolean; + + return [ + { + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 0 } + }, + command: { + title: runes ? 'Runes mode' : 'Legacy mode', + command: 'svelte.openLink', + arguments: ['https://svelte.dev/docs/svelte/legacy-overview'] + } + } + ]; + } catch (e) { + // show an empty code lens in case of a compilation error to prevent code from jumping around + return [ + { + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 0 } + }, + command: { + title: '', + command: '' + } + } + ]; + } + } + async getDiagnostics( document: Document, cancellationToken?: CancellationToken diff --git a/packages/svelte-vscode/src/extension.ts b/packages/svelte-vscode/src/extension.ts index c159d0a98..267d4772c 100644 --- a/packages/svelte-vscode/src/extension.ts +++ b/packages/svelte-vscode/src/extension.ts @@ -261,6 +261,8 @@ export function activateSvelteLanguageServer(context: ExtensionContext) { addMigrateToSvelte5Command(getLS, context); + addOpenLinkCommand(context); + languages.setLanguageConfiguration('svelte', { indentationRules: { // Matches a valid opening tag that is: @@ -513,6 +515,14 @@ function addMigrateToSvelte5Command(getLS: () => LanguageClient, context: Extens ); } +function addOpenLinkCommand(context: ExtensionContext) { + context.subscriptions.push( + commands.registerCommand('svelte.openLink', (url: string) => { + commands.executeCommand('vscode.open', Uri.parse(url)); + }) + ); +} + function createLanguageServer(serverOptions: ServerOptions, clientOptions: LanguageClientOptions) { return new LanguageClient('svelte', 'Svelte', serverOptions, clientOptions); }