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: (?=}) diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts index 7dd6633a8..f08e8c960 100644 --- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts +++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/SnippetBlock.ts @@ -116,7 +116,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