From 5122e08300b9fb464f56ec5eabd03cfa51b12556 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 15 May 2025 00:18:56 +0200 Subject: [PATCH 1/3] feat: support generics on snippets --- .../src/htmlxtojsx_v2/nodes/SnippetBlock.ts | 3 ++- .../samples/snippet-generics.v5/expectedv2.ts | 17 +++++++++++++++++ .../samples/snippet-generics.v5/input.svelte | 10 ++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/expectedv2.ts create mode 100644 packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/input.svelte diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts index 7dd6633a8..8df172145 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts @@ -31,6 +31,7 @@ export function handleSnippet( snippetBlock: BaseNode, component?: InlineComponent | Element ): void { + console.log({ snippetBlock }); const isImplicitProp = component !== undefined; const endSnippet = str.original.lastIndexOf('{', snippetBlock.end - 1); @@ -116,7 +117,7 @@ export function handleSnippet( 'const ', [snippetBlock.expression.start, snippetBlock.expression.end], IGNORE_POSITION_COMMENT, - ' = (' + ` = ${snippetBlock.typeParams ? `<${snippetBlock.typeParams}>` : ''}(` ]; if (parameters) { diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/expectedv2.ts new file mode 100644 index 000000000..460b114ba --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/expectedv2.ts @@ -0,0 +1,17 @@ +/// +;function $$render() { + const generic/*Ωignore_positionΩ*/ = (val: T)/*Ωignore_startΩ*/: ReturnType/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => { + val; +};return __sveltets_2_any(0)}; const complex_generic/*Ωignore_positionΩ*/ = ">>(val: T)/*Ωignore_startΩ*/: ReturnType/*Ωignore_endΩ*/ => { async ()/*Ωignore_positionΩ*/ => { + val; +};return __sveltets_2_any(0)}; +; +async () => { + + + +}; +return { props: /** @type {Record} */ ({}), exports: {}, bindings: "", slots: {}, events: {} }} +const Input__SvelteComponent_ = __sveltets_2_isomorphic_component(__sveltets_2_partial(__sveltets_2_with_any_event($$render()))); +/*Ωignore_startΩ*/type Input__SvelteComponent_ = InstanceType; +/*Ωignore_endΩ*/export default Input__SvelteComponent_; \ No newline at end of file diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/input.svelte new file mode 100644 index 000000000..4ee619728 --- /dev/null +++ b/packages/svelte2tsx/test/svelte2tsx/samples/snippet-generics.v5/input.svelte @@ -0,0 +1,10 @@ + + +{#snippet generic(val: T)} + {val} +{/snippet} + +{#snippet complex_generic">>(val: T)} + {val} +{/snippet} \ No newline at end of file From 378496da32ccf88f84544de4eeaf4c14438564ba Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 15 May 2025 02:00:33 +0200 Subject: [PATCH 2/3] chore: remove log --- packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts index 8df172145..f08e8c960 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts @@ -31,7 +31,6 @@ export function handleSnippet( snippetBlock: BaseNode, component?: InlineComponent | Element ): void { - console.log({ snippetBlock }); const isImplicitProp = component !== undefined; const endSnippet = str.original.lastIndexOf('{', snippetBlock.end - 1); From 59216cf25be58236df02bd3e15a2fe9fda18cdc0 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 15 May 2025 15:47:26 +0200 Subject: [PATCH 3/3] adjust grammar (holy shit that was fucked up) --- .../syntaxes/svelte.tmLanguage.src.yaml | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/svelte-vscode/syntaxes/svelte.tmLanguage.src.yaml b/packages/svelte-vscode/syntaxes/svelte.tmLanguage.src.yaml index e2c689077..e925ff2f2 100644 --- a/packages/svelte-vscode/syntaxes/svelte.tmLanguage.src.yaml +++ b/packages/svelte-vscode/syntaxes/svelte.tmLanguage.src.yaml @@ -234,11 +234,38 @@ repository: special-tags-modes: patterns: # Expressions or simple values. - - begin: (?<=(if|key|then|catch|snippet|html|render).*?)\G + - begin: (?<=(if|key|then|catch|html|render).*?)\G end: (?=}) name: meta.embedded.expression.svelte source.ts patterns: [ include: source.ts ] + # Snippet blocks - special because of how source.ts will parse generics: If it realizes "oh this is a function definition" it will + # go into arrow function parsing mode and not stop until it finds a `=>`, which means it will go past the `}` snippet open boundary + # and fuck up the rest of the file syntax highlighting + - begin: (?<=snippet.*?)\G + end: (?=}) + name: meta.embedded.expression.svelte source.ts + patterns: + # Match an identifier, but only if it is before a generic + - match: \G\s*([_$[:alpha:]][_$[:alnum:]]*)\s*(?=<) + captures: + 1: { name: entity.name.function.ts } + # Match optional `<` ... `>` with inner as source.ts + - begin: (?<=<) + end: (?=>) + contentName: meta.type.parameters.ts + patterns: [ include: source.ts ] + # Match the `(...)` but not starting at `(` because then TS would see it as an arrow function and parse past our snippet open boundary + - begin: (?<=>\s*\() + end: (?=}) + name: meta.embedded.expression.svelte source.ts + patterns: [ include: source.ts ] + # If the above three don't match (because there's no generic) then this one kicks in + - begin: \G + end: (?=}) + name: meta.embedded.expression.svelte source.ts + patterns: [ include: source.ts ] + # Const. - begin: (?<=const.*?)\G end: (?=})