Repository navigation
fix(typescript) highlight generic function declarations - #4551
Kernel-Hunter wants to merge 2 commits into
Conversation
The function declaration rule comes from the JavaScript grammar and expects `(` right after the name. With type parameters in between (`function identity<T>(arg: T)`) it never matched, so the name got no title.function scope and the parameters were not scoped as params. Add a TypeScript-only variant that matches when the name is followed by `<`, plus a type parameter mode that handles nested `<...>` and skips the `>` of `=>` inside function types. The parameter list after it is picked up by the existing params rule. Assisted-by: Claude Opus 5.5
kgeminicdev
left a comment
There was a problem hiding this comment.
Thanks, this fixes #4550 nicely. Nested generics, defaults, => in function types and declare function all highlight correctly, and plain functions are unchanged. One regression with string literal types in the type parameters, details and a tested fix inline.
| // `=>` inside a function type must not close the list | ||
| { match: /=>/ }, | ||
| tsLanguage.exports.CLASS_REFERENCE, | ||
| 'self' |
There was a problem hiding this comment.
A > inside a string literal type closes the type parameter list early, since strings aren't in contains here. On main these highlight correctly; with this change:
function f<T extends "a>b">(x: T) {}: the string is cut at>, and">(x: T) {}is highlighted as a string.function f<T extends `${number}>`>(x: T) {}: the template literal is cut, and since template strings span lines, everything after it is highlighted as a string.
Adding the string modes fixed both cases for me, and generic-functions still produces the same output:
contains: [
{ match: /=>/ },
tsLanguage.exports.CLASS_REFERENCE,
hljs.APOS_STRING_MODE,
hljs.QUOTE_STRING_MODE,
tsLanguage.contains.find(m => m.begin === '`'), // or export TEMPLATE_STRING alongside CLASS_REFERENCE
'self'
]Might be worth adding both lines to the markup test.
There was a problem hiding this comment.
Good catch, thanks. Fixed in 0fea703: the type parameter list now contains the quote, apostrophe and template string modes. I exported TEMPLATE_STRING from the JavaScript grammar next to CLASS_REFERENCE instead of looking it up by begin. Both of your examples are in generic-functions now, and the full test suite passes.
|
@joshgoebel this is ready for a look when you have time. The string literal regression that kgeminicdev found in review is fixed in 0fea703, with a markup test for it, and CI is green. |
Fixes #4550
Changes
The function declaration rule comes from the JavaScript grammar and only matches when
(directly follows the name. With type parameters in between, as infunction identity<T>(arg: T), nothing matched: the name got notitle.functionand the arguments weren't scoped asparams.This adds a TypeScript-only variant for
function name<, and a mode for the type parameter list that handles nested<...>(T extends Record<string, unknown>) and ignores the>of=>inside function types (F extends (x: number) => void). After the list closes, the existing params rule picks up the argument list. Output for non-generic functions and plain JS is unchanged.Not covered:
function* gen<T>()and anonymousfunction<T>(). I can do those separately if you want them.Checklist
test/markup/typescript/generic-functions)CHANGES.mdAssisted-by: Claude Opus 5.5