From a605dc0a6642f041a6ed61fb4d2b0022487c4d88 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Fri, 29 Nov 2024 21:10:45 +0100 Subject: [PATCH] fix: ensure imports without semicolon doesn't break intellisense ...by adding a generated semicolon at the end. That prevents TypeScript from going up until the next semicolon it finds, which may be from another generated code, messing up the generated->original end position #2608 #2607 --- .../features/CodeActionsProvider.test.ts | 15 ++------------- .../svelte2tsx/nodes/handleImportDeclaration.ts | 13 ++++++++++--- .../test/svelte2tsx/samples/imports/expectedv2.ts | 2 +- .../jsdoc-before-first-import/expectedv2.ts | 2 +- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts b/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts index 1ad7ac620..53fadc529 100644 --- a/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts +++ b/packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts @@ -1755,20 +1755,9 @@ describe('CodeActionsProvider', function () { line: 1 } } - }, - { - newText: "import { } from './somepng.png';\n", - range: { - end: { - character: 0, - line: 4 - }, - start: { - character: 4, - line: 3 - } - } } + // Because the generated code adds a ; after the last import, the + // second import is not appearing in the edits here ], textDocument: { uri: getUri('organize-imports-leading-comment.svelte'), diff --git a/packages/svelte2tsx/src/svelte2tsx/nodes/handleImportDeclaration.ts b/packages/svelte2tsx/src/svelte2tsx/nodes/handleImportDeclaration.ts index 9a0b4a5e9..4f022260b 100644 --- a/packages/svelte2tsx/src/svelte2tsx/nodes/handleImportDeclaration.ts +++ b/packages/svelte2tsx/src/svelte2tsx/nodes/handleImportDeclaration.ts @@ -25,9 +25,8 @@ export function handleFirstInstanceImport( hasModuleScript: boolean, str: MagicString ) { - const firstImport = tsAst.statements - .filter(ts.isImportDeclaration) - .sort((a, b) => a.end - b.end)[0]; + const imports = tsAst.statements.filter(ts.isImportDeclaration).sort((a, b) => a.end - b.end); + const firstImport = imports[0]; if (!firstImport) { return; } @@ -42,4 +41,12 @@ export function handleFirstInstanceImport( : firstImport.getStart(); str.appendRight(start + astOffset, '\n' + (hasModuleScript ? '\n' : '')); + + // Add a semi-colon to the last import if it doesn't have one, to prevent auto completion + // and imports from being added at the wrong position + const lastImport = imports[imports.length - 1]; + const end = lastImport.end + astOffset - 1; + if (str.original[end] !== ';') { + str.overwrite(end, lastImport.end + astOffset, str.original[end] + ';\n'); + } } diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/imports/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/imports/expectedv2.ts index ae4e57e82..b80485ccf 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/imports/expectedv2.ts +++ b/packages/svelte2tsx/test/svelte2tsx/samples/imports/expectedv2.ts @@ -2,7 +2,7 @@ ; import { a as b } from "./test.svelte" -import * as c from "b.ts" +import * as c from "b.ts"; function render() { diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/jsdoc-before-first-import/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/jsdoc-before-first-import/expectedv2.ts index 3e8c7c047..138ef5946 100644 --- a/packages/svelte2tsx/test/svelte2tsx/samples/jsdoc-before-first-import/expectedv2.ts +++ b/packages/svelte2tsx/test/svelte2tsx/samples/jsdoc-before-first-import/expectedv2.ts @@ -2,7 +2,7 @@ ;// non-leading comment /**@typedef {{ a: string }} Foo */ -import '' +import ''; function render() {