diff --git a/packages/language-server/src/plugins/svelte/SveltePlugin.ts b/packages/language-server/src/plugins/svelte/SveltePlugin.ts index 3aeb39cf5..e9a39f4f5 100644 --- a/packages/language-server/src/plugins/svelte/SveltePlugin.ts +++ b/packages/language-server/src/plugins/svelte/SveltePlugin.ts @@ -15,7 +15,7 @@ import { WorkspaceEdit } from 'vscode-languageserver'; import { Plugin } from 'prettier'; -import { getPackageInfo, importPrettier } from '../../importPackage'; +import { getPackageInfo, importPrettier, importSvelte } from '../../importPackage'; import { Document } from '../../lib/documents'; import { Logger } from '../../logger'; import { LSConfigManager, LSSvelteConfig } from '../../ls-config'; @@ -288,6 +288,10 @@ export class SveltePlugin command: string, args?: any[] ): Promise { + if (command === 'migrate_to_svelte_5') { + return this.migrate(document); + } + if (!this.featureEnabled('codeActions')) { return null; } @@ -300,6 +304,36 @@ export class SveltePlugin } } + private migrate(document: Document): WorkspaceEdit | string { + try { + const compiler = importSvelte(document.getFilePath() ?? '') as any; + if (!compiler.migrate) { + return 'Your installed Svelte version does not support migration'; + } + + const migrated = compiler.migrate(document.getText(), { + filename: document.getFilePath() ?? undefined + }); + + return { + changes: { + [document.uri]: [ + TextEdit.replace( + Range.create( + document.positionAt(0), + document.positionAt(document.getTextLength()) + ), + migrated.code + ) + ] + } + }; + } catch (error: any) { + Logger.error('Failed to migrate Svelte file', error); + return error?.message ?? 'Failed to migrate Svelte file'; + } + } + async getSelectionRange( document: Document, position: Position diff --git a/packages/language-server/src/server.ts b/packages/language-server/src/server.ts index d19e56dcc..026edff5d 100644 --- a/packages/language-server/src/server.ts +++ b/packages/language-server/src/server.ts @@ -290,6 +290,7 @@ export function startServer(options?: LSOptions) { 'constant_scope_2', 'constant_scope_3', 'extract_to_svelte_component', + 'migrate_to_svelte_5', 'Infer function return type' ] } @@ -592,15 +593,13 @@ export function startServer(options?: LSOptions) { return null; } - if (doc) { - const compiled = await sveltePlugin.getCompiledResult(doc); - if (compiled) { - const js = compiled.js; - const css = compiled.css; - return { js, css }; - } else { - return null; - } + const compiled = await sveltePlugin.getCompiledResult(doc); + if (compiled) { + const js = compiled.js; + const css = compiled.css; + return { js, css }; + } else { + return null; } }); diff --git a/packages/svelte-vscode/package.json b/packages/svelte-vscode/package.json index a39165e17..12260c440 100644 --- a/packages/svelte-vscode/package.json +++ b/packages/svelte-vscode/package.json @@ -540,6 +540,10 @@ "command": "svelte.extractComponent", "title": "Svelte: Extract Component" }, + { + "command": "svelte.migrate_to_svelte_5", + "title": "Svelte: Migrate Component to Svelte 5 Syntax" + }, { "command": "svelte.typescript.findAllFileReferences", "title": "Svelte: Find File References" diff --git a/packages/svelte-vscode/src/extension.ts b/packages/svelte-vscode/src/extension.ts index d8ae0e166..c159d0a98 100644 --- a/packages/svelte-vscode/src/extension.ts +++ b/packages/svelte-vscode/src/extension.ts @@ -259,6 +259,8 @@ export function activateSvelteLanguageServer(context: ExtensionContext) { addExtracComponentCommand(getLS, context); + addMigrateToSvelte5Command(getLS, context); + languages.setLanguageConfiguration('svelte', { indentationRules: { // Matches a valid opening tag that is: @@ -495,6 +497,22 @@ function addExtracComponentCommand(getLS: () => LanguageClient, context: Extensi ); } +function addMigrateToSvelte5Command(getLS: () => LanguageClient, context: ExtensionContext) { + context.subscriptions.push( + commands.registerTextEditorCommand('svelte.migrate_to_svelte_5', async (editor) => { + if (editor?.document?.languageId !== 'svelte') { + return; + } + + const uri = editor.document.uri.toString(); + getLS().sendRequest(ExecuteCommandRequest.type, { + command: 'migrate_to_svelte_5', + arguments: [uri] + }); + }) + ); +} + function createLanguageServer(serverOptions: ServerOptions, clientOptions: LanguageClientOptions) { return new LanguageClient('svelte', 'Svelte', serverOptions, clientOptions); }