Skip to content

Commit a1b4a64

Browse files
authored
fix: ensure hoisted interfaces are moved after hoisted imports (#2597)
#2594 As a drive-by, I also ensures that the dts generation knows about the hoisted interfaces so it does not transform them into types anymore
1 parent c21de66 commit a1b4a64

File tree

10 files changed

+81
-21
lines changed

10 files changed

+81
-21
lines changed

packages/svelte2tsx/src/svelte2tsx/nodes/HoistableInterfaces.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ export class HoistableInterfaces {
332332
}
333333

334334
const hoistable = this.determineHoistableInterfaces();
335+
335336
if (hoistable.has(this.props_interface.name)) {
336337
for (const [name, node] of hoistable) {
337338
let pos = node.pos + astOffset;
@@ -343,12 +344,17 @@ export class HoistableInterfaces {
343344
}
344345
if (/\s/.test(str.original[pos])) {
345346
pos++;
346-
str.prependRight(pos, '\n');
347347
}
348+
349+
// jsdoc comments would be ignored if they are on the same line as the ;, so we add a newline, too
350+
str.prependRight(pos, ';\n');
351+
str.appendLeft(node.end + astOffset, ';');
348352
}
349353

350354
str.move(pos, node.end + astOffset, scriptStart);
351355
}
356+
357+
return hoistable;
352358
}
353359
}
354360

packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,21 +310,30 @@ export function processInstanceScriptContent(
310310
moveNode(node, str, astOffset, script.start, tsAst);
311311
}
312312

313+
const hoisted = exportedNames.hoistableInterfaces.moveHoistableInterfaces(
314+
str,
315+
astOffset,
316+
script.start + 1, // +1 because imports are also moved at that position, and we want to move interfaces after imports
317+
generics.getReferences()
318+
);
319+
313320
if (mode === 'dts') {
314321
// Transform interface declarations to type declarations because indirectly
315322
// using interfaces inside the return type of a function is forbidden.
316323
// This is not a problem for intellisense/type inference but it will
317324
// break dts generation (file will not be generated).
318-
transformInterfacesToTypes(tsAst, str, astOffset, nodesToMove);
325+
if (hoisted) {
326+
transformInterfacesToTypes(
327+
tsAst,
328+
str,
329+
astOffset,
330+
[...hoisted.values()].concat(nodesToMove)
331+
);
332+
} else {
333+
transformInterfacesToTypes(tsAst, str, astOffset, nodesToMove);
334+
}
319335
}
320336

321-
exportedNames.hoistableInterfaces.moveHoistableInterfaces(
322-
str,
323-
astOffset,
324-
script.start,
325-
generics.getReferences()
326-
);
327-
328337
return {
329338
exportedNames,
330339
events,
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import type { X } from './x';
12
/** asd */
2-
type Props = {
3+
interface Props {
34
foo: string;
45
bar?: X;
5-
};
6-
import type { X } from './x';
6+
}
77
declare const TestRunes2: import("svelte").Component<Props, {}, "">;
88
type TestRunes2 = ReturnType<typeof TestRunes2>;
99
export default TestRunes2;

packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-1.v5/expectedv2.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
///<reference types="svelte" />
22
;
33
let value = 1;
4-
;
5-
type NoComma = true
4+
;;;
5+
type NoComma = true;;
66
type Dependency = {
77
a: number;
88
b: typeof value;
99
c: NoComma
10-
}
10+
};;
1111

1212
/** A comment */
1313
interface Props<T> {

packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-2.v5/expectedv2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
///<reference types="svelte" />
22
;
33
let value = 1;
4-
;
4+
;;;
55
interface Dependency {
66
a: number;
77
b: typeof value;
8-
};type $$ComponentProps = { a: Dependency, b: string };;function render() {
8+
};;type $$ComponentProps = { a: Dependency, b: string };function render() {
99

1010

1111

packages/svelte2tsx/test/svelte2tsx/samples/ts-runes-hoistable-props-4.v5/expectedv2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
///<reference types="svelte" />
2-
2+
;;
33
interface Dependency {
44
a: number;
5-
}
5+
};;
66

77
interface Props {
88
[k: string]: Dependency;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
///<reference types="svelte" />
2+
;
3+
import X from './X';
4+
;;
5+
6+
import { readable } from 'svelte/store';
7+
;
8+
9+
/** I should not be sandwitched between the imports */
10+
interface Props {
11+
foo?: string;
12+
};function render() {
13+
14+
15+
16+
const store = readable(1)/*Ωignore_startΩ*/;let $store = __sveltets_2_store_get(store);/*Ωignore_endΩ*/
17+
18+
let { foo }: Props = $props()
19+
;
20+
async () => {
21+
22+
23+
24+
$store;};
25+
return { props: {} as any as Props, exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }}
26+
const Input__SvelteComponent_ = __sveltets_2_fn_component(render());
27+
type Input__SvelteComponent_ = ReturnType<typeof Input__SvelteComponent_>;
28+
export default Input__SvelteComponent_;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script module>
2+
import X from './X';
3+
</script>
4+
5+
<script lang="ts">
6+
import { readable } from 'svelte/store';
7+
8+
const store = readable(1)
9+
10+
/** I should not be sandwitched between the imports */
11+
interface Props {
12+
foo?: string;
13+
}
14+
let { foo }: Props = $props()
15+
</script>
16+
17+
{$store}

packages/svelte2tsx/test/svelte2tsx/samples/ts-runes.v5/expectedv2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
///<reference types="svelte" />
2-
;type $$ComponentProps = { a: number, b: string };;function render() {
2+
;;type $$ComponentProps = { a: number, b: string };function render() {
33

44
let { a, b }:/*Ωignore_startΩ*/$$ComponentProps/*Ωignore_endΩ*/ = $props();
55
let x = $state(0);

packages/svelte2tsx/test/svelte2tsx/samples/ts-sveltekit-autotypes-$props-rune-unchanged.v5/expectedv2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
///<reference types="svelte" />
2-
;type $$ComponentProps = {form: boolean, data: true };;function render() {
2+
;;type $$ComponentProps = {form: boolean, data: true };function render() {
33

44
const snapshot: any = {};
55
let { form, data }:/*Ωignore_startΩ*/$$ComponentProps/*Ωignore_endΩ*/ = $props();

0 commit comments

Comments
 (0)