-
-
Notifications
You must be signed in to change notification settings - Fork 219
Description
Describe the bug
1. Description
Describe the bug clearly and concisely.
When using the "Rename Symbol" (F2) refactoring feature in VS Code on a TypeScript type within a .ts
file, the Svelte language extension incorrectly modifies and corrupts the code of a .svelte
file that imports and uses this type. Instead of just updating the type name, the refactoring injects malformed code and extraneous function calls throughout the Svelte component's script block, rendering it syntactically invalid.
2. To Reproduce
Note: It's not easy to reproduce, because I already converted my commit. But these are some samples:
-
Create a
forms.types.ts
file with several exported TypeScript types:// src/lib/forms.types.ts export type SubmitCallback<T = any> = (data: T) => unknown | Promise<unknown>; // ... other types
-
Create a
FormShell.svelte
component that imports and uses these types in its props definition:<!-- src/lib/components/FormShell.svelte --> <script lang="ts" generics="T extends Record<string, any>"> import type { SubmitCallback, /* other types */ } from '$lib/forms.types'; import { coerceErrorMessage } from "$lib/utils/errorUtils"; // This was a new import, intended to replace existing, local "coerceMessage()" interface FormShellProps<T> { submitCbk: SubmitCallback<T>; // ... other props } const { submitCbk }: FormShellProps<T> = $props(); // ... component logic </script>
-
Perform the refactoring:
- Open the
forms.types.ts
file. - Place the cursor on the
SubmitCallback
type name. - Press
F2
to trigger "Rename Symbol". - Rename it to
SubmitFn
and press Enter.
- Open the
3. Expected behavior
I expected the refactoring to only change the type name SubmitCallback
to SubmitFn
within the FormShell.svelte
component, leaving the rest of the code untouched.
The expected result in FormShell.svelte
should be:
<script lang="ts" generics="T extends Record<string, any>">
import type { SubmitFn, /* other types */ } from '$lib/forms.types';
interface FormShellProps<T> {
submitCbk: SubmitFn<T>; // Correctly renamed
// ... other props
}
// ...
</script>
4. Actual behavior
The FormShell.svelte
file was corrupted with multiple syntax errors. The refactoring tool seems to have incorrectly injected code fragments into various places within the <script>
block.
Here is a snippet of the corrupted code:
// ...
import type {
Errors,
ValidateFn, // This was renamed from ValidateCallback
SubmitFn, // This was renamed from SubmitCallback
CancelFn, // This was renamed from CancelCallback
// ...
} from "./forms.types";
// ...
function internalSet<P extends NonEmptyPath<T>>(
path: readonly [...P],
value: PathValue<T, P>,
) {
try {
coerceErrorMessage[it added additional characters here].set<T, P>(formState.data, path, value); // ERROR
} catch (e) {
// ...
}
}
function get<P extends NonEmptyPath<T>>(
path: readonly [...P],
): PathValue<T, P> | undefined {
try {
return pathUtils.get(formState.data, path);
} catch (e) {
log.error("get failed", {
//...
error: coerceErrorMessage(e),coerceErrorMessage
});
return undefined;
}
}
function markTouched(path: string) {
formState.touched.add(path);
if (autoValidate === "blur") {
void runValidate(path);
}
}coerceErrorMessage // ERROR!
// ....
log.error("get failed", {
// ...
error: coerceErrorMessage(e),coerceErrorMessage // Error
});
5. System Info
- Svelte for VS Code extension version: 109.11.0
- VS Code version: v103.2.0
- OS: Windows 11
- SvelteKit version: ^2.22.0"
- Node.js version: 24.4.1
6. Additional context
This issue makes refactoring TypeScript types that are consumed by Svelte components very unreliable and potentially destructive. It seems to be related to how the language server processes changes across .ts
and .svelte
file boundaries, especially when dealing with generic types.
Reproduction
Note: It's not easy to reproduce, because I already converted my commit. But these are some samples:
-
Create a
forms.types.ts
file with several exported TypeScript types:// src/lib/forms.types.ts export type SubmitCallback<T = any> = (data: T) => unknown | Promise<unknown>; // ... other types
-
Create a
FormShell.svelte
component that imports and uses these types in its props definition:<!-- src/lib/components/FormShell.svelte --> <script lang="ts" generics="T extends Record<string, any>"> import type { SubmitCallback, /* other types */ } from '$lib/forms.types'; import { coerceErrorMessage } from "$lib/utils/errorUtils"; // This was a new import, intended to replace existing, local "coerceMessage()" interface FormShellProps<T> { submitCbk: SubmitCallback<T>; // ... other props } const { submitCbk }: FormShellProps<T> = $props(); // ... component logic </script>
-
Perform the refactoring:
- Open the
forms.types.ts
file. - Place the cursor on the
SubmitCallback
type name. - Press
F2
to trigger "Rename Symbol". - Rename it to
SubmitFn
and press Enter.
- Open the
Expected behaviour
I expected the refactoring to only change the type name SubmitCallback
to SubmitFn
within the FormShell.svelte
component, leaving the rest of the code untouched.
The expected result in FormShell.svelte
should be:
<script lang="ts" generics="T extends Record<string, any>">
import type { SubmitFn, /* other types */ } from '$lib/forms.types';
interface FormShellProps<T> {
submitCbk: SubmitFn<T>; // Correctly renamed
// ... other props
}
// ...
</script>
System Info
- Svelte for VS Code extension version: 109.11.0
- VS Code version: v103.2.0
- OS: Windows 11
- SvelteKit version: ^2.22.0"
- Node.js version: 24.4.1
Which package is the issue about?
No response
Additional Information, eg. Screenshots
This issue makes refactoring TypeScript types that are consumed by Svelte components very unreliable and potentially destructive. It seems to be related to how the language server processes changes across .ts
and .svelte
file boundaries, especially when dealing with generic types.