From f19ee2979070e7716ec6cbe3f0e74cf6715b6e54 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 22 Sep 2023 16:17:31 +0200 Subject: [PATCH 01/59] Add highlighting for using keyword FIX: Properly highlight `using` as a keyword. Closes https://github.com/lezer-parser/javascript/issues/23 --- src/highlight.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/highlight.js b/src/highlight.js index 33dc077..212a408 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -4,7 +4,7 @@ export const jsHighlight = styleTags({ "get set async static": t.modifier, "for while do if else switch try catch finally return throw break continue default case": t.controlKeyword, "in of await yield void typeof delete instanceof": t.operatorKeyword, - "let var const function class extends": t.definitionKeyword, + "let var const using function class extends": t.definitionKeyword, "import export from": t.moduleKeyword, "with debugger as new": t.keyword, TemplateString: t.special(t.string), From 22ba574e5465bb1f4626fba6c844565da34eaac0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 5 Oct 2023 17:03:51 +0200 Subject: [PATCH 02/59] Mark version 1.4.8 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23e3ea2..aab83d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.8 (2023-10-05) + +### Bug fixes + +Properly highlight `using` as a keyword. + ## 1.4.7 (2023-08-23) ### Bug fixes diff --git a/package.json b/package.json index 3199d2d..e28e979 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.7", + "version": "1.4.8", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From b9c9e0c270c99e2f78a00e7713eecaf923ff7036 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 30 Oct 2023 09:21:14 +0100 Subject: [PATCH 03/59] Support 'default' binding name in import/export groups FIX: Allow `default` to be used in `import`/`export` binding sets. Closes https://github.com/lezer-parser/javascript/issues/24 --- src/javascript.grammar | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 0a39801..22c2cab 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -77,7 +77,7 @@ ExportDeclaration { } ExportGroup { - "{" commaSep (VariableName { word } | String))?> "}" + "{" commaSep<(VariableName | String | kw<"default">) (ckw<"as"> (VariableName { word } | String | kw<"default">))?> "}" } ImportDeclaration { @@ -87,7 +87,7 @@ ImportDeclaration { } ImportGroup { - "{" commaSep? (VariableDefinition | (VariableName | String) ckw<"as"> VariableDefinition)> "}" + "{" commaSep? (VariableDefinition | (VariableName | String | kw<"default">) ckw<"as"> VariableDefinition)> "}" } ForSpec { From 67e0467b404adeb31f11d6c104828593d6d7aaa4 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 30 Oct 2023 12:38:30 +0100 Subject: [PATCH 04/59] Fix previous patch --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 22c2cab..8175097 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -77,7 +77,7 @@ ExportDeclaration { } ExportGroup { - "{" commaSep<(VariableName | String | kw<"default">) (ckw<"as"> (VariableName { word } | String | kw<"default">))?> "}" + "{" commaSep<(VariableName | String | kw<"default">) (ckw<"as"> (VariableName { word } | String))?> "}" } ImportDeclaration { From 99629d08065e68a2e41e5fdcc2688347b6c8e191 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 30 Oct 2023 12:38:35 +0100 Subject: [PATCH 05/59] Mark version 1.4.9 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aab83d4..fbd003a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.9 (2023-10-30) + +### Bug fixes + +Allow `default` to be used in `import`/`export` binding sets. + ## 1.4.8 (2023-10-05) ### Bug fixes diff --git a/package.json b/package.json index e28e979..d6f4fb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.8", + "version": "1.4.9", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 7512058bd003bc3af12179bfb0ffcb63d96f3e16 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 6 Dec 2023 10:08:10 +0100 Subject: [PATCH 06/59] Support prefix | and & operators in TS types FIX: Support `|` and `&` as prefixes in TypeScript types. Closes https://github.com/lezer-parser/javascript/issues/25 --- src/javascript.grammar | 16 ++++++++++++++-- test/typescript.txt | 20 ++++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 8175097..c574143 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -4,7 +4,9 @@ typeargs, typeMember, typePrefix, + intersectionPrefixed @left, intersection @left, + unionPrefixed @left, union @left, typeExtends @right, else @right, @@ -421,8 +423,14 @@ type[@isGroup=Type] { ArrayType { type "[" "]" | type "[" "]" } | ReadonlyType { tskw<"readonly"> !readonly type } | ObjectType | - UnionType { type !union LogicOp { "|" } type } | - IntersectionType { type !intersection LogicOp { "&" } type } | + UnionType { + type (!union unionOp type)+ | + unionOp type (!unionPrefixed unionOp type)* + } | + IntersectionType { + type (!intersection intersectionOp type)+ | + intersectionOp type (!intersectionPrefixed intersectionOp type)* + } | ConditionalType { type !typeExtends kw<"extends"> type questionOp ~arrow type LogicOp<":"> type } | ParameterizedType { (TypeName | IndexedType) !typeargs TypeArgList } | TypeName @@ -579,6 +587,10 @@ Optional { "?" } questionOp[@name=LogicOp] { "?" } +unionOp[@name=LogicOp] { "|" } + +intersectionOp[@name=LogicOp] { "&" } + @skip { spaces | newline | LineComment | BlockComment } @context trackNewline from "./tokens.js" diff --git a/test/typescript.txt b/test/typescript.txt index dd5dd95..cef51fb 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -91,13 +91,29 @@ let f: (x: number) => boolean Script( VariableDeclaration(let, VariableDefinition, TypeAnnotation( - UnionType(UnionType(TypeofType(typeof, MemberExpression(VariableName, PropertyName)), LogicOp, - IntersectionType(KeyofType(keyof, TypeName), LogicOp, IndexedType(TypeName, LiteralType(String)))), + UnionType(TypeofType(typeof, MemberExpression(VariableName, PropertyName)), LogicOp, + IntersectionType(KeyofType(keyof, TypeName), LogicOp, IndexedType(TypeName, LiteralType(String))), LogicOp, ParameterizedType(TypeName, TypeArgList(TypeName))))), VariableDeclaration(let, VariableDefinition, TypeAnnotation(TupleType(TypeName, TypeName))), VariableDeclaration(let, VariableDefinition, TypeAnnotation(FunctionSignature( ParamList(VariableDefinition, TypeAnnotation(TypeName)), Arrow, TypeName)))) +# Prefix union/intersection + +let x: + | A + | B + | C +let y: & RegExp & (& Date) + +==> + +Script( + VariableDeclaration(let,VariableDefinition,TypeAnnotation( + UnionType(LogicOp,TypeName,LogicOp,TypeName,LogicOp,TypeName))), + VariableDeclaration(let,VariableDefinition,TypeAnnotation( + IntersectionType(LogicOp,TypeName,LogicOp,ParenthesizedType(IntersectionType(LogicOp,TypeName)))))) + # Prefix cast {"dialect": "ts"} foo From 4090f5dae55b30977f63e077d82c36930267c9a1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 6 Dec 2023 10:08:31 +0100 Subject: [PATCH 07/59] Mark version 1.4.10 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbd003a..0b5b37c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.10 (2023-12-06) + +### Bug fixes + +Support `|` and `&` as prefixes in TypeScript types. + ## 1.4.9 (2023-10-30) ### Bug fixes diff --git a/package.json b/package.json index d6f4fb0..19e6600 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.9", + "version": "1.4.10", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 1a9e408ab0e4b565a3b16964c9ffc541eef8169e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 18 Dec 2023 08:41:01 +0100 Subject: [PATCH 08/59] Use commas and 'extends' to disambiguate type parameter lists from JSX tags FIX: In TSX mode, parse `` or `` as type parameters, not JSX tags. See https://discuss.codemirror.net/t/syntax-highlighting-not-working-on-large-documents/7579 --- src/javascript.grammar | 6 ++---- src/tokens.js | 37 +++++++++++++++++++++++++++++++++++-- test/typescript.txt | 13 +++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index c574143..eece57e 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -602,6 +602,8 @@ intersectionOp[@name=LogicOp] { "&" } incdecPrefix[@name=ArithOp] } +@external tokens jsx from "./tokens" { JSXStartTag } + @local tokens { InterpolationStart[closedBy=InterpolationEnd] { "${" } templateEnd { "`" } @@ -693,8 +695,6 @@ intersectionOp[@name=LogicOp] { "&" } JSXAttributeValue { '"' !["]* '"' | "'" ![']* "'" } - JSXStartTag[@dialect=jsx] { "<" } - JSXStartCloseTag { "" } @@ -704,8 +704,6 @@ intersectionOp[@name=LogicOp] { "&" } JSXText { ![<{]+ } tsAngleOpen[@dialect=ts] { "<" } - - @precedence { JSXStartTag, tsAngleOpen } } @external tokens insertSemicolon from "./tokens" { insertSemi } diff --git a/src/tokens.js b/src/tokens.js index 00ffaec..8c8a1d3 100644 --- a/src/tokens.js +++ b/src/tokens.js @@ -3,12 +3,13 @@ import {ExternalTokenizer, ContextTracker} from "@lezer/lr" import {insertSemi, noSemi, incdec, incdecPrefix, - spaces, newline, BlockComment, LineComment} from "./parser.terms.js" + spaces, newline, BlockComment, LineComment, + JSXStartTag, Dialect_jsx} from "./parser.terms.js" const space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232, 8233, 8239, 8287, 12288] -const braceR = 125, semicolon = 59, slash = 47, star = 42, plus = 43, minus = 45 +const braceR = 125, semicolon = 59, slash = 47, star = 42, plus = 43, minus = 45, lt = 60, comma = 44 export const trackNewline = new ContextTracker({ start: false, @@ -43,3 +44,35 @@ export const incdecToken = new ExternalTokenizer((input, stack) => { } } }, {contextual: true}) + +function identifierChar(ch, start) { + return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch == 95 || ch >= 192 || + !start && ch >= 48 && ch <= 57 +} + +export const jsx = new ExternalTokenizer((input, stack) => { + if (input.next != lt || !stack.dialectEnabled(Dialect_jsx)) return + input.advance() + if (input.next == slash) return + // Scan for an identifier followed by a comma or 'extends', don't + // treat this as a start tag if present. + let back = 0 + while (space.indexOf(input.next) > -1) { input.advance(); back++ } + if (identifierChar(input.next, true)) { + input.advance() + back++ + while (identifierChar(input.next, false)) { input.advance(); back++ } + while (space.indexOf(input.next) > -1) { input.advance(); back++ } + if (input.next == comma) return + for (let i = 0;; i++) { + if (i == 7) { + if (!identifierChar(input.next, true)) return + break + } + if (input.next != "extends".charCodeAt(i)) break + input.advance() + back++ + } + } + input.acceptToken(JSXStartTag, -back) +}) diff --git a/test/typescript.txt b/test/typescript.txt index cef51fb..d56a0bc 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -311,3 +311,16 @@ Script( VariableDeclaration(let,VariableDefinition,Equals, CallExpression(VariableName,TypeArgList(TypeName),ArgList(Number))), ReturnStatement(return,Number)) + +# Type parameters vs JSX {"dialect": "jsx ts"} + +let a = (f) => null +let b = () => 1 + +==> + +Script( + VariableDeclaration(let,VariableDefinition,Equals,ArrowFunction( + TypeParamList(TypeDefinition,extends,TypeName),ParamList(VariableDefinition),Arrow,null)), + VariableDeclaration(let,VariableDefinition,Equals,ArrowFunction( + TypeParamList(TypeDefinition),ParamList,Arrow,Number))) From cefe3e5d535189bf352540cb04a68dd8e7006cfd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 18 Dec 2023 08:42:22 +0100 Subject: [PATCH 09/59] Emit tokens for the opening < in a parameter list --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index eece57e..3c710ff 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -686,7 +686,7 @@ intersectionOp[@name=LogicOp] { "&" } "..."[@name=Spread] "=>"[@name=Arrow] - "(" ")" "[" "]" "{" "}" ">" + "(" ")" "[" "]" "{" "}" "<" ">" "?." "." "," ";" ":" "@" From 87124a3040967ef5146bc0316e5588062de5ce13 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 18 Dec 2023 08:42:27 +0100 Subject: [PATCH 10/59] Mark version 1.4.11 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b5b37c..dcc6d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.11 (2023-12-18) + +### Bug fixes + +In TSX mode, parse `` or `` as type parameters, not JSX tags. + ## 1.4.10 (2023-12-06) ### Bug fixes diff --git a/package.json b/package.json index 19e6600..6d3fae5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.10", + "version": "1.4.11", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 946910e4708f963aad0d2416782aee24f188142f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 4 Jan 2024 12:45:01 +0100 Subject: [PATCH 11/59] Add bidi isolate information FIX: Mark strings, comments, and interpolations as isolating for bidirectional text. --- src/javascript.grammar | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 3c710ff..e627d01 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -474,25 +474,25 @@ ParamTypeList[@name=ParamList] { } @skip {} { - TemplateString { + TemplateString[isolate] { templateStart (templateEscape | templateContent | templateExpr)* templateEnd } - TemplateType { + TemplateType[isolate] { templateStart (templateContent | templateType)* templateEnd } - String { + String[isolate] { '"' (stringContentDouble | Escape)* ('"' | "\n") | "'" (stringContentSingle | Escape)* ("'" | "\n") } - BlockComment { "/*" (blockCommentContent | blockCommentNewline)* blockCommentEnd } + BlockComment[isolate] { "/*" (blockCommentContent | blockCommentNewline)* blockCommentEnd } } -templateExpr[@name=Interpolation] { InterpolationStart expression InterpolationEnd } +templateExpr[@name=Interpolation,isolate] { InterpolationStart expression InterpolationEnd } -templateType[@name=Interpolation] { InterpolationStart type InterpolationEnd } +templateType[@name=Interpolation,isolate] { InterpolationStart type InterpolationEnd } @skip {} { JSXElement { @@ -621,7 +621,7 @@ intersectionOp[@name=LogicOp] { "&" } spaces[@export] { $[\u0009 \u000b\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]+ } newline[@export] { $[\r\n\u2028\u2029] } - LineComment { "//" ![\n]* } + LineComment[isolate] { "//" ![\n]* } Hashbang { "#!" ![\n]* } @@ -678,7 +678,7 @@ intersectionOp[@name=LogicOp] { "&" } @precedence { "*", ArithOp } - RegExp { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[gimsuy]*)? } + RegExp[isolate] { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[gimsuy]*)? } LessThan[@name=CompareOp] { "<" } From 1a2c36d0fa24d70825542a2f611007e3519174d0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 4 Jan 2024 12:45:05 +0100 Subject: [PATCH 12/59] Mark version 1.4.12 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc6d7b..82e21db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.12 (2024-01-04) + +### Bug fixes + +Mark strings, comments, and interpolations as isolating for bidirectional text. + ## 1.4.11 (2023-12-18) ### Bug fixes diff --git a/package.json b/package.json index 6d3fae5..c30c848 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.11", + "version": "1.4.12", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 658d372a414062b8fd41093ec80d4b22ebe0cfe6 Mon Sep 17 00:00:00 2001 From: Andy Edwards Date: Wed, 10 Jan 2024 02:51:33 -0600 Subject: [PATCH 13/59] Fix bitwise operator precedence FIX: Fix inverted relative precedence of `&`, `|`, and `^` bitwise operators. Closes #27 --- src/javascript.grammar | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index e627d01..2bacadb 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -26,9 +26,9 @@ rel @left, satisfies, equal @left, - bitOr @left, - bitXor @left, bitAnd @left, + bitXor @left, + bitOr @left, and @left, or @left, ternary @right, From d2d76dbe77482b02bb874d8c4d3556823e19e5be Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 16 Jan 2024 16:44:21 +0100 Subject: [PATCH 14/59] Add missing @lezer/common dependency FIX: Add an explicit dependency on @lezer/common ^1.2.0. Closes https://github.com/lezer-parser/javascript/issues/29 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c30c848..b3cfba5 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "@lezer/lr": "^1.3.0", + "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3" }, "repository": { From e8bbd9d318b2982902efb4267b8fb3836d18d1ff Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 16 Jan 2024 16:44:28 +0100 Subject: [PATCH 15/59] Mark version 1.4.13 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82e21db..f236a54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.13 (2024-01-16) + +### Bug fixes + +Fix inverted relative precedence of `&`, `|`, and `^` bitwise operators. + +Add an explicit dependency on @lezer/common ^1.2.0. + ## 1.4.12 (2024-01-04) ### Bug fixes diff --git a/package.json b/package.json index b3cfba5..ab45fac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.12", + "version": "1.4.13", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 0d864c6b6352ad7be9a3aab395ef2bc847253dd3 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 14 Feb 2024 16:12:46 +0100 Subject: [PATCH 16/59] Add a classPopName wrapper To reduce some combinatory explosions --- src/javascript.grammar | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 2bacadb..adb9b37 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -151,11 +151,13 @@ propModifier { tsPkwMod<"override"> } +classPropName { propName | PrivatePropertyDefinition } + MethodDeclaration[group=ClassItem] { propModifier* pkwMod<"async">? (pkwMod<"get"> | pkwMod<"set"> | Star)? - (propName | PrivatePropertyDefinition) + classPropName functionSignature (Block | semi) } @@ -167,7 +169,7 @@ StaticBlock[group=ClassItem] { PropertyDeclaration[group=ClassItem] { propModifier* (tsPkwMod<"readonly"> | pkwMod<"accessor">)? - (propName | PrivatePropertyDefinition) + classPropName (Optional | LogicOp<"!">)? TypeAnnotation? ("=" expressionNoComma)? From 392c6115647c9e55c147ac2d702f75be127a7b2d Mon Sep 17 00:00:00 2001 From: Alex Errant <109672176+AlexErrant@users.noreply.github.com> Date: Sat, 23 Mar 2024 02:14:11 -0500 Subject: [PATCH 17/59] Add more regex flags (#30) FIX: Recognize the `d` and `v` RegExp flags. --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index adb9b37..7a642ff 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -680,7 +680,7 @@ intersectionOp[@name=LogicOp] { "&" } @precedence { "*", ArithOp } - RegExp[isolate] { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[gimsuy]*)? } + RegExp[isolate] { "/" (![/\\\n[] | "\\" ![\n] | "[" (![\n\\\]] | "\\" ![\n])* "]")+ ("/" $[dgimsuvy]*)? } LessThan[@name=CompareOp] { "<" } From 63d0fc2689cb8e1e437e7c29786b3aa39b36d560 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 30 Mar 2024 19:49:48 +0100 Subject: [PATCH 18/59] Support destructured parameters in function types FIX: Allow destructured parameters in function signature types. Closes https://github.com/codemirror/dev/issues/1364 --- src/javascript.grammar | 10 +++++----- test/typescript.txt | 11 +++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 7a642ff..c3aba6f 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -421,7 +421,7 @@ type[@isGroup=Type] { FunctionSignature { TypeParamList? ParamTypeList "=>" type } | NewSignature { kw<"new"> ParamTypeList "=>" type } | IndexedType | - TupleType { "[" commaSep<(Label ":")? type | "..." type> "]" } | + TupleType { "[" commaSep<(Label ":")? type | "..." type> ~destructure "]" } | ArrayType { type "[" "]" | type "[" "]" } | ReadonlyType { tskw<"readonly"> !readonly type } | ObjectType | @@ -450,7 +450,7 @@ ObjectType { CallSignature { ParamTypeList (TypeAnnotation | TypePredicate) } | NewSignature[@dynamicPrecedence=1] { @extend[@name=new] ParamTypeList TypeAnnotation }) ("," | semi) - )* "}" + )* ~destructure "}" } IndexSignature { @@ -472,7 +472,7 @@ PropertyType { } ParamTypeList[@name=ParamList] { - "(" commaSep<"..."? VariableDefinition ~arrow Optional? ~arrow TypeAnnotation?> ")" + "(" commaSep<"..."? pattern ~arrow Optional? ~arrow TypeAnnotation?> ")" } @skip {} { @@ -577,9 +577,9 @@ TypeName { identifier ~arrow } Label { identifier } -PropertyName { word } +PropertyName { word ~propName } -PropertyDefinition { word } +PropertyDefinition { word ~propName } PrivatePropertyName { privateIdentifier } diff --git a/test/typescript.txt b/test/typescript.txt index d56a0bc..a6f74de 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -324,3 +324,14 @@ Script( TypeParamList(TypeDefinition,extends,TypeName),ParamList(VariableDefinition),Arrow,null)), VariableDeclaration(let,VariableDefinition,Equals,ArrowFunction( TypeParamList(TypeDefinition),ParamList,Arrow,Number))) + +# Destructured parameters in function signature {"dialect": "ts"} + +type F = ([a, b]: [number, number]) => void + +==> + +Script(TypeAliasDeclaration(type,TypeDefinition,Equals,FunctionSignature( + ParamList(ArrayPattern(VariableDefinition,VariableDefinition),TypeAnnotation(TupleType(TypeName,TypeName))), + Arrow, + VoidType(void)))) From b7dd6f073dd06c965cbebc5987bd14a53f02c70f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 30 Mar 2024 19:51:14 +0100 Subject: [PATCH 19/59] Mark version 1.4.14 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f236a54..182db9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.14 (2024-03-30) + +### Bug fixes + +Recognize the `d` and `v` RegExp flags. Support destructured parameters in function types + +Allow destructured parameters in function signature types. + ## 1.4.13 (2024-01-16) ### Bug fixes diff --git a/package.json b/package.json index ab45fac..afda2e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.13", + "version": "1.4.14", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 49aefe8f664a9ea62c5314a284a0891335504d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Z=C3=BCnd?= Date: Tue, 23 Apr 2024 08:43:46 +0200 Subject: [PATCH 20/59] Support new.target FIX: Add support for `new.target` syntax. Issue https://github.com/lezer-parser/javascript/pull/32 --- src/javascript.grammar | 1 + test/statement.txt | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/javascript.grammar b/src/javascript.grammar index c3aba6f..bf225c9 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -285,6 +285,7 @@ expressionNoComma { RegExp | ArrayExpression | ObjectExpression { "{" commaSep ~destructure "}" } | + NewTarget { kw<"new"> "." PropertyName } | NewExpression { kw<"new"> expressionNoComma (!newArgs TypeArgList? ArgList)? } | UnaryExpression | YieldExpression | diff --git a/test/statement.txt b/test/statement.txt index a8313a7..9243488 100644 --- a/test/statement.txt +++ b/test/statement.txt @@ -383,3 +383,18 @@ foo() ==> Script(Hashbang,ExpressionStatement(CallExpression(VariableName,ArgList))) + +# new.target + +function MyObj() { + if (!new.target) { + throw new Error('Must construct MyObj with new'); + } +} + +==> + +Script( + FunctionDeclaration(function,VariableDefinition,ParamList,Block( + IfStatement(if,ParenthesizedExpression(UnaryExpression(LogicOp,NewTarget(new,PropertyName))), Block( + ThrowStatement(throw,NewExpression(new,VariableName,ArgList(String)))))))) From fca757bffc4f302241558a4d7c35062630af8487 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 23 Apr 2024 08:45:48 +0200 Subject: [PATCH 21/59] Mark version 1.4.15 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 182db9b..550bf37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.15 (2024-04-23) + +### Bug fixes + +Add support for `new.target` syntax. + ## 1.4.14 (2024-03-30) ### Bug fixes diff --git a/package.json b/package.json index afda2e7..21ed37e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.14", + "version": "1.4.15", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From d31ea1a7ac6fc36084a71828f235549ca9301e02 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 23 Apr 2024 11:17:43 +0200 Subject: [PATCH 22/59] Don't tokenizer ?. when followed by a digit FIX: Don't consume `?.` tokens when followed by a digit. Closes https://github.com/lezer-parser/javascript/issues/33 --- src/javascript.grammar | 15 ++++++++------- src/tokens.js | 11 ++++++++--- test/expression.txt | 8 ++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index bf225c9..1d3d186 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -226,8 +226,8 @@ AmbientDeclaration { decoratorExpression { VariableName | - MemberExpression { decoratorExpression !member ("." | "?.") (PropertyName | PrivatePropertyName) } | - CallExpression { decoratorExpression !call TypeArgList? "?."? ArgList } | + MemberExpression { decoratorExpression !member ("." | questionDot) (PropertyName | PrivatePropertyName) } | + CallExpression { decoratorExpression !call TypeArgList? questionDot? ArgList } | ParenthesizedExpression } @@ -299,7 +299,7 @@ expressionNoComma { ConditionalExpression { expressionNoComma !ternary questionOp expressionNoComma LogicOp<":"> expressionNoComma } | AssignmentExpression | PostfixExpression { expressionNoComma !postfix (incdec | LogicOp<"!">) } | - CallExpression { expressionNoComma !call TypeArgList? "?."? ArgList } | + CallExpression { expressionNoComma !call TypeArgList? questionDot? ArgList } | TaggedTemplateExpression { expressionNoComma !taggedTemplate TemplateString } | DynamicImport { kw<"import"> "(" expressionNoComma ")" } | ImportMeta { kw<"import"> "." PropertyName } | @@ -378,7 +378,7 @@ AssignmentExpression { } MemberExpression { - expressionNoComma !member (("." | "?.") (PropertyName | PrivatePropertyName) | "?."? "[" expression "]") + expressionNoComma !member (("." | questionDot) (PropertyName | PrivatePropertyName) | questionDot? "[" expression "]") } ArgList { @@ -400,7 +400,7 @@ TypeParamList { typeParam { TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? } typeofMemberExpression[@name=MemberExpression] { - VariableName !member (("." | "?.") PropertyName | "[" expression "]") + VariableName !member (("." | questionDot) PropertyName | "[" expression "]") } type[@isGroup=Type] { @@ -600,9 +600,10 @@ intersectionOp[@name=LogicOp] { "&" } @external tokens noSemicolon from "./tokens" { noSemi } -@external tokens incdecToken from "./tokens" { +@external tokens operatorToken from "./tokens" { incdec[@name=ArithOp], incdecPrefix[@name=ArithOp] + questionDot[@name="?."] } @external tokens jsx from "./tokens" { JSXStartTag } @@ -691,7 +692,7 @@ intersectionOp[@name=LogicOp] { "&" } "(" ")" "[" "]" "{" "}" "<" ">" - "?." "." "," ";" ":" "@" + "." "," ";" ":" "@" JSXIdentifier { $[A-Z_$\u{a1}-\u{10ffff}] (identifierChar | @digit | "-")* } JSXLowerIdentifier[@name=JSXIdentifier] { $[a-z] (identifierChar | @digit | "-")* } diff --git a/src/tokens.js b/src/tokens.js index 8c8a1d3..8cab7b5 100644 --- a/src/tokens.js +++ b/src/tokens.js @@ -2,14 +2,15 @@ expressed by lezer's built-in tokenizer. */ import {ExternalTokenizer, ContextTracker} from "@lezer/lr" -import {insertSemi, noSemi, incdec, incdecPrefix, +import {insertSemi, noSemi, incdec, incdecPrefix, questionDot, spaces, newline, BlockComment, LineComment, JSXStartTag, Dialect_jsx} from "./parser.terms.js" const space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232, 8233, 8239, 8287, 12288] -const braceR = 125, semicolon = 59, slash = 47, star = 42, plus = 43, minus = 45, lt = 60, comma = 44 +const braceR = 125, semicolon = 59, slash = 47, star = 42, plus = 43, minus = 45, lt = 60, comma = 44, + question = 63, dot = 46 export const trackNewline = new ContextTracker({ start: false, @@ -33,7 +34,7 @@ export const noSemicolon = new ExternalTokenizer((input, stack) => { input.acceptToken(noSemi) }, {contextual: true}) -export const incdecToken = new ExternalTokenizer((input, stack) => { +export const operatorToken = new ExternalTokenizer((input, stack) => { let {next} = input if (next == plus || next == minus) { input.advance() @@ -42,6 +43,10 @@ export const incdecToken = new ExternalTokenizer((input, stack) => { let mayPostfix = !stack.context && stack.canShift(incdec) input.acceptToken(mayPostfix ? incdec : incdecPrefix) } + } else if (next == question && input.peek(1) == dot) { + input.advance(); input.advance() + if (input.next < 48 || input.next > 57) // No digit after + input.acceptToken(questionDot) } }, {contextual: true}) diff --git a/test/expression.txt b/test/expression.txt index 6c68d51..2666aa7 100644 --- a/test/expression.txt +++ b/test/expression.txt @@ -676,3 +676,11 @@ Script(ExpressionStatement(ConditionalExpression(Number,LogicOp,Number,⚠))) ==> Script(ExpressionStatement(TemplateString(⚠))) + +# Ternary with leading-dot number + +a?.2:.3 + +==> + +Script(ExpressionStatement(ConditionalExpression(VariableName,LogicOp,Number,LogicOp,Number))) From 034abc88382891bba7bc0369b541fd360ce91a4e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 4 May 2024 06:42:09 +0200 Subject: [PATCH 23/59] Add support for stand-alone instantiated expressions FIX: Support type arguments on non-call expressions. Closes https://github.com/codemirror/dev/issues/1377 --- src/javascript.grammar | 14 +++++++++----- test/typescript.txt | 29 ++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 1d3d186..4e21a97 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -14,6 +14,7 @@ readonly, newArgs, call, + instantiate, taggedTemplate, prefix, postfix, @@ -286,7 +287,7 @@ expressionNoComma { ArrayExpression | ObjectExpression { "{" commaSep ~destructure "}" } | NewTarget { kw<"new"> "." PropertyName } | - NewExpression { kw<"new"> expressionNoComma (!newArgs TypeArgList? ArgList)? } | + NewExpression { kw<"new"> expressionNoComma (!newArgs ArgList)? } | UnaryExpression | YieldExpression | AwaitExpression | @@ -299,7 +300,8 @@ expressionNoComma { ConditionalExpression { expressionNoComma !ternary questionOp expressionNoComma LogicOp<":"> expressionNoComma } | AssignmentExpression | PostfixExpression { expressionNoComma !postfix (incdec | LogicOp<"!">) } | - CallExpression { expressionNoComma !call TypeArgList? questionDot? ArgList } | + CallExpression { expressionNoComma !call questionDot? ArgList } | + InstantiationExpression { (VariableName | MemberExpression) !instantiate TypeArgList } | TaggedTemplateExpression { expressionNoComma !taggedTemplate TemplateString } | DynamicImport { kw<"import"> "(" expressionNoComma ")" } | ImportMeta { kw<"import"> "." PropertyName } | @@ -399,8 +401,10 @@ TypeParamList { typeParam { TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? } -typeofMemberExpression[@name=MemberExpression] { - VariableName !member (("." | questionDot) PropertyName | "[" expression "]") +typeofExpression { + MemberExpression { typeofExpression !member (("." | questionDot) PropertyName | "[" expression "]") } | + InstantiationExpression { typeofExpression !instantiate TypeArgList } | + VariableName } type[@isGroup=Type] { @@ -413,7 +417,7 @@ type[@isGroup=Type] { TemplateType | NullType { kw<"null"> } | VoidType { kw<"void"> } | - TypeofType { kw<"typeof"> (VariableName | typeofMemberExpression) } | + TypeofType { kw<"typeof"> typeofExpression } | KeyofType { !typePrefix tskw<"keyof"> type } | UniqueType { !typePrefix tskw<"unique"> type } | ImportType { kw<"import"> "(" String ")" } | diff --git a/test/typescript.txt b/test/typescript.txt index a6f74de..f67404a 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -76,9 +76,9 @@ x < 10 > 5 Script( ExpressionStatement(BinaryExpression( - CallExpression(VariableName, TypeArgList(TypeName, TypeName), ArgList), + CallExpression(InstantiationExpression(VariableName, TypeArgList(TypeName, TypeName)), ArgList), ArithOp, - NewExpression(new, VariableName, TypeArgList(LiteralType(Number)), ArgList))), + NewExpression(new, InstantiationExpression(VariableName, TypeArgList(LiteralType(Number))), ArgList))), ExpressionStatement(BinaryExpression(BinaryExpression(VariableName, CompareOp, Number), CompareOp, Number))) # Advanced types {"dialect": "ts"} @@ -309,7 +309,7 @@ return 2 Script( VariableDeclaration(let,VariableDefinition,Equals, - CallExpression(VariableName,TypeArgList(TypeName),ArgList(Number))), + CallExpression(InstantiationExpression(VariableName,TypeArgList(TypeName)),ArgList(Number))), ReturnStatement(return,Number)) # Type parameters vs JSX {"dialect": "jsx ts"} @@ -335,3 +335,26 @@ Script(TypeAliasDeclaration(type,TypeDefinition,Equals,FunctionSignature( ParamList(ArrayPattern(VariableDefinition,VariableDefinition),TypeAnnotation(TupleType(TypeName,TypeName))), Arrow, VoidType(void)))) + +# Instantiated expression {"dialect": "ts"} + +let x = a; + +type Foo = Bar>>; + +==> + +Script( + VariableDeclaration(let,VariableDefinition,Equals,InstantiationExpression(VariableName,TypeArgList(TypeName))), + TypeAliasDeclaration(type,TypeDefinition,Equals,ParameterizedType(TypeName,TypeArgList( + TypeofType(typeof,InstantiationExpression(VariableName,TypeArgList( + ParameterizedType(TypeName,TypeArgList(TypeName))))))))) + +# Not instantiated {"dialect": "ts"} + +let x = ac + +==> + +Script(VariableDeclaration(let,VariableDefinition,Equals,BinaryExpression( + BinaryExpression(VariableName,CompareOp,VariableName),CompareOp,VariableName))) From b3775dc544f97b66cee02dc324c0cd6f5a532dea Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 4 May 2024 06:42:51 +0200 Subject: [PATCH 24/59] Mark version 1.4.16 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 550bf37..c8e352c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.16 (2024-05-04) + +### Bug fixes + +Don't consume `?.` tokens when followed by a digit. + +Support type arguments on non-call expressions. + ## 1.4.15 (2024-04-23) ### Bug fixes diff --git a/package.json b/package.json index 21ed37e..399ced5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.15", + "version": "1.4.16", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 0f89f5b25d176b3a087951d5f5e3d41de01fd90b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 11 Jun 2024 17:04:21 +0200 Subject: [PATCH 25/59] Support TS -readonly / -? syntax in mapped object types FIX: Add support for `{-readonly [K in T]-?: U}` TypeScript syntax. Closes https://github.com/lezer-parser/javascript/issues/36 --- src/javascript.grammar | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 4e21a97..32f594d 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -352,14 +352,14 @@ AwaitExpression[@dynamicPrecedence=1] { UnaryExpression { !prefix (kw<"void"> | kw<"typeof"> | kw<"delete"> | - LogicOp<"!"> | BitOp<"~"> | incdec | incdecPrefix | ArithOp<"+" | "-">) + LogicOp<"!"> | BitOp<"~"> | incdec | incdecPrefix | plusMin) expressionNoComma } BinaryExpression { expressionNoComma !exp ArithOp<"**"> expressionNoComma | expressionNoComma !times (divide | ArithOp<"%"> | ArithOp<"*">) expressionNoComma | - expressionNoComma !plus ArithOp<"+" | "-"> expressionNoComma | + expressionNoComma !plus plusMin expressionNoComma | expressionNoComma !shift BitOp<">>" ">"? | "<<"> expressionNoComma | expressionNoComma !rel (LessThan | CompareOp<"<=" | ">" "="?> | kw<"instanceof">) expressionNoComma | expressionNoComma !satisfies tskw<"satisfies"> type | @@ -410,7 +410,7 @@ typeofExpression { type[@isGroup=Type] { ThisType { kw<"this"> } | LiteralType { - ArithOp<"+" | "-">? Number | + plusMin? Number | boolean | String } | @@ -459,7 +459,10 @@ ObjectType { } IndexSignature { - tsPkwMod<"readonly">? "[" PropertyDefinition { identifier } (TypeAnnotation | ~tsIn kw<"in"> type) "]" TypeAnnotation + (plusMin? tsPkwMod<"readonly">)? + "[" PropertyDefinition { identifier } (TypeAnnotation | ~tsIn kw<"in"> type) "]" + (plusMin? Optional)? + TypeAnnotation } MethodType { @@ -470,9 +473,9 @@ MethodType { } PropertyType { - (ArithOp<"+" | "-">? tsPkwMod<"readonly">)? + (plusMin? tsPkwMod<"readonly">)? PropertyDefinition - (ArithOp<"+" | "-">? Optional)? + (plusMin? Optional)? TypeAnnotation } @@ -596,6 +599,8 @@ questionOp[@name=LogicOp] { "?" } unionOp[@name=LogicOp] { "|" } +plusMin { ArithOp<"+" | "-"> } + intersectionOp[@name=LogicOp] { "&" } @skip { spaces | newline | LineComment | BlockComment } From 2c20fdd8771129fffcb8a93591b26f8769a320ba Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 11 Jun 2024 17:04:29 +0200 Subject: [PATCH 26/59] Mark version 1.4.17 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e352c..c5a025e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.17 (2024-06-11) + +### Bug fixes + +Add support for `{-readonly [K in T]-?: U}` TypeScript syntax. + ## 1.4.16 (2024-05-04) ### Bug fixes diff --git a/package.json b/package.json index 399ced5..1bd2bb7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.16", + "version": "1.4.17", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From be6eaf3695d6351d1848c4e1505bc0a3d3e5e5a6 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 17 Jun 2024 13:47:05 +0200 Subject: [PATCH 27/59] Add support for 'as' syntax in mapped types FIX: Support `as` syntax in mapped object types. --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 32f594d..0e85b91 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -460,7 +460,7 @@ ObjectType { IndexSignature { (plusMin? tsPkwMod<"readonly">)? - "[" PropertyDefinition { identifier } (TypeAnnotation | ~tsIn kw<"in"> type) "]" + "[" PropertyDefinition { identifier } (TypeAnnotation | ~tsIn kw<"in"> type (ckw<"as"> type)?) "]" (plusMin? Optional)? TypeAnnotation } From 04ede4af79777370cdb3fbf0751ee3f58d1c9af2 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 25 Jun 2024 08:13:53 +0200 Subject: [PATCH 28/59] Allow empty scripts --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 0e85b91..805e287 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -39,7 +39,7 @@ predicate } -@top Script { Hashbang? statement+ } +@top Script { Hashbang? statement* } @top SingleExpression { expression } From 224d9a66e6a5a33ccd5d382c1f82d2b0ea1c4a90 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 17 Sep 2024 07:57:50 +0200 Subject: [PATCH 29/59] Accept interpolations with missing expressions FIX: Make sure the parser doesn't get confused when a template interpolation is missing its expression. Closes https://github.com/codemirror/dev/issues/1441 --- src/javascript.grammar | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 805e287..bab4f3d 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -500,9 +500,9 @@ ParamTypeList[@name=ParamList] { BlockComment[isolate] { "/*" (blockCommentContent | blockCommentNewline)* blockCommentEnd } } -templateExpr[@name=Interpolation,isolate] { InterpolationStart expression InterpolationEnd } +templateExpr[@name=Interpolation,isolate] { InterpolationStart expression? InterpolationEnd } -templateType[@name=Interpolation,isolate] { InterpolationStart type InterpolationEnd } +templateType[@name=Interpolation,isolate] { InterpolationStart type? InterpolationEnd } @skip {} { JSXElement { From 34e5de4cb57fe3ef3d8d278c231a634b1f2bad9f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 17 Sep 2024 07:58:00 +0200 Subject: [PATCH 30/59] Mark version 1.4.18 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5a025e..cc79f04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.18 (2024-09-17) + +### Bug fixes + +Support `as` syntax in mapped object types. + +Make sure the parser doesn't get confused when a template interpolation is missing its expression. + ## 1.4.17 (2024-06-11) ### Bug fixes diff --git a/package.json b/package.json index 1bd2bb7..b71cd88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.17", + "version": "1.4.18", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From ab896bd331df9f66432db72a39cb51e406f39b27 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Oct 2024 15:44:49 +0200 Subject: [PATCH 31/59] Allow method types to have an optional marker FIX: Support question marks after method names in TypeScript object type notation. Closes https://github.com/lezer-parser/javascript/issues/37 --- src/javascript.grammar | 1 + 1 file changed, 1 insertion(+) diff --git a/src/javascript.grammar b/src/javascript.grammar index bab4f3d..20fae46 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -469,6 +469,7 @@ MethodType { pkwMod<"async">? (pkwMod<"get"> | pkwMod<"set"> | Star)? PropertyDefinition + (plusMin? Optional)? functionSignature } From aef4de7f7d2819d2405238eecdc3113fc1028d35 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Oct 2024 16:16:37 +0200 Subject: [PATCH 32/59] Support computed property notation in object types FIX: Support bracketed property names in TypeScript object types. Closes https://github.com/lezer-parser/javascript/issues/38 --- src/javascript.grammar | 12 +++++++----- src/tokens.js | 8 ++++++-- test/typescript.txt | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 20fae46..3fd49c8 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -318,7 +318,7 @@ ArrayExpression { "[" commaSep1<"..."? expressionNoComma | ""> ~destructure "]" } -propName { PropertyDefinition | "[" expression "]" | Number | String } +propName { PropertyDefinition | "[" expression "]" ~destructure | Number ~destructure | String ~destructure } Property { pkwMod<"async">? (pkwMod<"get"> | pkwMod<"set"> | Star)? propName functionSignature Block | @@ -427,7 +427,7 @@ type[@isGroup=Type] { NewSignature { kw<"new"> ParamTypeList "=>" type } | IndexedType | TupleType { "[" commaSep<(Label ":")? type | "..." type> ~destructure "]" } | - ArrayType { type "[" "]" | type "[" "]" } | + ArrayType { type noSemiType "[" "]" } | ReadonlyType { tskw<"readonly"> !readonly type } | ObjectType | UnionType { @@ -444,7 +444,7 @@ type[@isGroup=Type] { } IndexedType { - type !typeMember ("." TypeName | "[" type "]")+ + type !typeMember ("." TypeName | noSemiType "[" type "]")+ } ObjectType { @@ -468,14 +468,14 @@ IndexSignature { MethodType { pkwMod<"async">? (pkwMod<"get"> | pkwMod<"set"> | Star)? - PropertyDefinition + propName (plusMin? Optional)? functionSignature } PropertyType { (plusMin? tsPkwMod<"readonly">)? - PropertyDefinition + propName (plusMin? Optional)? TypeAnnotation } @@ -610,6 +610,8 @@ intersectionOp[@name=LogicOp] { "&" } @external tokens noSemicolon from "./tokens" { noSemi } +@external tokens noSemicolonType from "./tokens" { noSemiType } + @external tokens operatorToken from "./tokens" { incdec[@name=ArithOp], incdecPrefix[@name=ArithOp] diff --git a/src/tokens.js b/src/tokens.js index 8cab7b5..299102e 100644 --- a/src/tokens.js +++ b/src/tokens.js @@ -2,7 +2,7 @@ expressed by lezer's built-in tokenizer. */ import {ExternalTokenizer, ContextTracker} from "@lezer/lr" -import {insertSemi, noSemi, incdec, incdecPrefix, questionDot, +import {insertSemi, noSemi, noSemiType, incdec, incdecPrefix, questionDot, spaces, newline, BlockComment, LineComment, JSXStartTag, Dialect_jsx} from "./parser.terms.js" @@ -10,7 +10,7 @@ const space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 81 8201, 8202, 8232, 8233, 8239, 8287, 12288] const braceR = 125, semicolon = 59, slash = 47, star = 42, plus = 43, minus = 45, lt = 60, comma = 44, - question = 63, dot = 46 + question = 63, dot = 46, bracketL = 91 export const trackNewline = new ContextTracker({ start: false, @@ -34,6 +34,10 @@ export const noSemicolon = new ExternalTokenizer((input, stack) => { input.acceptToken(noSemi) }, {contextual: true}) +export const noSemicolonType = new ExternalTokenizer((input, stack) => { + if (input.next == bracketL && !stack.context) input.acceptToken(noSemiType) +}, {contextual: true}) + export const operatorToken = new ExternalTokenizer((input, stack) => { let {next} = input if (next == plus || next == minus) { diff --git a/test/typescript.txt b/test/typescript.txt index f67404a..f20e828 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -358,3 +358,17 @@ let x = ac Script(VariableDeclaration(let,VariableDefinition,Equals,BinaryExpression( BinaryExpression(VariableName,CompareOp,VariableName),CompareOp,VariableName))) + +# Allows computed properties in types {"dialect": "ts"} + +interface X { + [Symbol.iterator](): Iterator + [1]: string +} + +==> + +Script(InterfaceDeclaration(interface,TypeDefinition,ObjectType( + MethodType(MemberExpression(VariableName,PropertyName),ParamList, + TypeAnnotation(ParameterizedType(TypeName,TypeArgList(TypeName)))), + PropertyType(Number,TypeAnnotation(TypeName))))) From 075debcf14494e6dc54e73125c9c7a507ae1275f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Oct 2024 16:17:53 +0200 Subject: [PATCH 33/59] Allow interfaces to extend multiple types FIX: Allow TypeScript interface declarations to extend multiple types. Closes https://github.com/lezer-parser/javascript/issues/39 --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 3fd49c8..d75358e 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -190,7 +190,7 @@ TypeAliasDeclaration { } InterfaceDeclaration { - tskw<"interface"> TypeDefinition TypeParamList? (kw<"extends"> type)? ObjectType + tskw<"interface"> TypeDefinition TypeParamList? (kw<"extends"> commaSep1)? ObjectType } EnumDeclaration { From 04cf4a08c03172c119fe26b58452d7a04c238de7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 8 Oct 2024 17:40:45 +0200 Subject: [PATCH 34/59] Mark version 1.4.19 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc79f04..6d92712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 1.4.19 (2024-10-08) + +### Bug fixes + +Support question marks after method names in TypeScript object type notation. + +Support bracketed property names in TypeScript object types. + +Allow TypeScript interface declarations to extend multiple types. + ## 1.4.18 (2024-09-17) ### Bug fixes diff --git a/package.json b/package.json index b71cd88..29db276 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.18", + "version": "1.4.19", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 609878a0279c1a2c4636f1dbeef9c4f697549506 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Sat, 23 Nov 2024 15:06:17 +0100 Subject: [PATCH 35/59] Style variables used with new as class names FIX: Use the `className` style tag for variable names used as constructors with `new`. See https://discuss.codemirror.net/t/javascript-highlighting-class-name-in-a-new-expression/8835 --- src/highlight.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/highlight.js b/src/highlight.js index 212a408..221edca 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -22,6 +22,7 @@ export const jsHighlight = styleTags({ "CallExpression/MemberExpression/PropertyName": t.function(t.propertyName), "FunctionDeclaration/VariableDefinition": t.function(t.definition(t.variableName)), "ClassDeclaration/VariableDefinition": t.definition(t.className), + "NewExpression/VariableName": t.className, PropertyDefinition: t.definition(t.propertyName), PrivatePropertyDefinition: t.definition(t.special(t.propertyName)), UpdateOp: t.updateOperator, From b142c2a50314a2f361c47d624d9d41f70f05f3a1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 26 Nov 2024 08:54:07 +0100 Subject: [PATCH 36/59] Drop outdated ES version in readme Closes https://github.com/lezer-parser/javascript/issues/40 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d4e9fc..f979492 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a JavaScript grammar for the [lezer](https://lezer.codemirror.net/) parser system. -It parses ES2020, and supports a `"ts"` +It parses modern JavaScript, and supports a `"ts"` [dialect](https://lezer.codemirror.net/docs/guide/#dialects) to parse TypeScript, and a `"jsx"` dialect to parse JSX. From eb6fb1d21d7d56d09f2f43d68678f7839d44ea0f Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 2 Dec 2024 15:26:41 +0100 Subject: [PATCH 37/59] Support asserts TypeScript function signatures FIX: Add support for `asserts` syntax in function return types. Closes https://github.com/lezer-parser/javascript/issues/41 --- src/highlight.js | 2 +- src/javascript.grammar | 2 +- test/typescript.txt | 12 +++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/highlight.js b/src/highlight.js index 221edca..71b03df 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -51,7 +51,7 @@ export const jsHighlight = styleTags({ TypeDefinition: t.definition(t.typeName), "type enum interface implements namespace module declare": t.definitionKeyword, "abstract global Privacy readonly override": t.modifier, - "is keyof unique infer": t.operatorKeyword, + "is keyof unique infer asserts": t.operatorKeyword, JSXAttributeValue: t.attributeValue, JSXText: t.content, diff --git a/src/javascript.grammar b/src/javascript.grammar index d75358e..dd74251 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -246,7 +246,7 @@ patternAssign { TypeAnnotation { ":" type } -TypePredicate { ":" (VariableName | kw<"this">) !predicate tskw<"is"> type } +TypePredicate { ":" tskw<"asserts">? (VariableName | kw<"this">) !predicate tskw<"is"> type } patternAssignTyped { pattern Optional? TypeAnnotation? ("=" expressionNoComma)? diff --git a/test/typescript.txt b/test/typescript.txt index f20e828..93c0d06 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -26,11 +26,17 @@ Script(FunctionDeclaration(function, VariableDefinition, ParamList( function isFoo(foo: any): foo is Foo { return true } +function assertFoo(foo: any): asserts foo is "string" { return true } + ==> -Script(FunctionDeclaration(function, VariableDefinition, ParamList( - VariableDefinition, TypeAnnotation(TypeName) -), TypePredicate(VariableName, is, TypeName), Block(ReturnStatement(return, BooleanLiteral)))) +Script( + FunctionDeclaration(function, VariableDefinition, ParamList( + VariableDefinition, TypeAnnotation(TypeName) + ), TypePredicate(VariableName, is, TypeName), Block(ReturnStatement(return, BooleanLiteral))), + FunctionDeclaration(function,VariableDefinition,ParamList( + VariableDefinition,TypeAnnotation(TypeName) + ),TypePredicate(asserts,VariableName,is,LiteralType(String)),Block(ReturnStatement(return,BooleanLiteral)))) # Type alias {"dialect": "ts"} From 4bce3bff438538a0af2651765d3c142b43cadee1 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 2 Dec 2024 15:26:54 +0100 Subject: [PATCH 38/59] Mark version 1.4.20 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d92712..7a5b3a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.20 (2024-12-02) + +### Bug fixes + +Use the `className` style tag for variable names used as constructors with `new`. + +Add support for `asserts` syntax in function return types. + ## 1.4.19 (2024-10-08) ### Bug fixes diff --git a/package.json b/package.json index 29db276..6288549 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.19", + "version": "1.4.20", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 002c1669e43dc1a5cb9393db624a653a0d7ee860 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 2 Dec 2024 15:42:54 +0100 Subject: [PATCH 39/59] Support const modifier on type parameters FIX: Add support for `const` modifiers on TypeScript type parameters. Closes https://github.com/lezer-parser/javascript/issues/42 --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index dd74251..a1105ad 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -399,7 +399,7 @@ TypeParamList { "<" commaSep ">" } -typeParam { TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? } +typeParam { kw<"const">? TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? } typeofExpression { MemberExpression { typeofExpression !member (("." | questionDot) PropertyName | "[" expression "]") } | From eb9561878b2f272e5f7e70cfa596a490aa0a30d9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2024 12:57:04 +0100 Subject: [PATCH 40/59] Support asserts syntax without predicate FIX: Allow TypeScript syntax, where the condition is just a variable. Issue https://github.com/lezer-parser/javascript/issues/41 --- src/javascript.grammar | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index a1105ad..b4e5423 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -246,7 +246,12 @@ patternAssign { TypeAnnotation { ":" type } -TypePredicate { ":" tskw<"asserts">? (VariableName | kw<"this">) !predicate tskw<"is"> type } +TypePredicate { + ":" ( + tskw<"asserts">? (VariableName | kw<"this">) (tskw<"is"> type)? | + (VariableName | kw<"this">) !predicate tskw<"is"> type + ) +} patternAssignTyped { pattern Optional? TypeAnnotation? ("=" expressionNoComma)? From 30f42b3479311e90e6ffd798fe5de592eb1fa5b9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2024 13:00:08 +0100 Subject: [PATCH 41/59] Solve conflict caused by previous patch --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index b4e5423..b6c2b1f 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -248,7 +248,7 @@ TypeAnnotation { ":" type } TypePredicate { ":" ( - tskw<"asserts">? (VariableName | kw<"this">) (tskw<"is"> type)? | + tskw<"asserts">? (VariableName | kw<"this">) !predicate (tskw<"is"> type)? | (VariableName | kw<"this">) !predicate tskw<"is"> type ) } From d10ec797ca5b1fca0d84ee08149164558b2d36dc Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2024 13:00:46 +0100 Subject: [PATCH 42/59] Give the tsAngleOpen token a name FIX: Fix a bug where some TypeScript `<` tokens didn't appear in the syntax tree. Closes https://github.com/lezer-parser/javascript/issues/43 --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index b6c2b1f..93d774d 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -724,7 +724,7 @@ intersectionOp[@name=LogicOp] { "&" } JSXText { ![<{]+ } - tsAngleOpen[@dialect=ts] { "<" } + tsAngleOpen[@dialect=ts,@name="<"] { "<" } } @external tokens insertSemicolon from "./tokens" { insertSemi } From 2f52d819542d5705c6033ab78f4e5b3a1d1bd979 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 3 Dec 2024 14:19:38 +0100 Subject: [PATCH 43/59] Mark version 1.4.21 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a5b3a2..bd425a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 1.4.21 (2024-12-03) + +### Bug fixes + +Add support for `const` modifiers on TypeScript type parameters. + +Allow TypeScript syntax, where the condition is just a variable. + +Fix a bug where some TypeScript `<` tokens didn't appear in the syntax tree. + ## 1.4.20 (2024-12-02) ### Bug fixes diff --git a/package.json b/package.json index 6288549..e416b36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.20", + "version": "1.4.21", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 52f0592f3ef77bb9bcadc8af9c45865c3cf1039a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 6 Feb 2025 11:48:07 +0100 Subject: [PATCH 44/59] Fix ambiguity between type predicates and type annotations --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 93d774d..26659c2 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -248,7 +248,7 @@ TypeAnnotation { ":" type } TypePredicate { ":" ( - tskw<"asserts">? (VariableName | kw<"this">) !predicate (tskw<"is"> type)? | + tskw<"asserts"> (VariableName | kw<"this">) !predicate (tskw<"is"> type)? | (VariableName | kw<"this">) !predicate tskw<"is"> type ) } From 17e896d07b300576447ccf91e9f7e261a9f90a14 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 6 Feb 2025 11:48:36 +0100 Subject: [PATCH 45/59] Add support for in/out type parameter annotations FIX: Support `in`/`out` modifiers on TypeScript type parameters. --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 26659c2..2be263b 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -404,7 +404,7 @@ TypeParamList { "<" commaSep ">" } -typeParam { kw<"const">? TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? } +typeParam { (kw<"in"> | tskw<"out"> | kw<"const">)? TypeDefinition ~tsAngle (kw<"extends"> type)? ("=" type)? } typeofExpression { MemberExpression { typeofExpression !member (("." | questionDot) PropertyName | "[" expression "]") } | From 3f819cd39048a053190871fcfd71a49466a83d9a Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 17 Apr 2025 08:08:17 +0200 Subject: [PATCH 46/59] Add support for TS satisfies operator FEATURE: Support the TypeScript `satisfies` operator. Closes https://github.com/lezer-parser/javascript/issues/45 --- src/javascript.grammar | 1 + test/typescript.txt | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/javascript.grammar b/src/javascript.grammar index 2be263b..f33ebba 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -370,6 +370,7 @@ BinaryExpression { expressionNoComma !satisfies tskw<"satisfies"> type | (expressionNoComma | PrivatePropertyName) !rel ~tsIn kw<"in"> expressionNoComma | expressionNoComma !rel ckw<"as"> (kw<"const"> | type) | + expressionNoComma !rel tskw<"satisfies"> type | expressionNoComma !equal CompareOp<"==" "="? | "!=" "="?> expressionNoComma | expressionNoComma !bitOr BitOp { "|" } expressionNoComma | expressionNoComma !bitXor BitOp<"^"> expressionNoComma | diff --git a/test/typescript.txt b/test/typescript.txt index 93c0d06..b5d772f 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -378,3 +378,13 @@ Script(InterfaceDeclaration(interface,TypeDefinition,ObjectType( MethodType(MemberExpression(VariableName,PropertyName),ParamList, TypeAnnotation(ParameterizedType(TypeName,TypeArgList(TypeName)))), PropertyType(Number,TypeAnnotation(TypeName))))) + +# Binary type operators {"dialect": "ts"} + +log(foo as number, {} satisfies AbstractObjectFactory) + +==> + +Script(ExpressionStatement(CallExpression(VariableName,ArgList( + BinaryExpression(VariableName,as,TypeName), + BinaryExpression(ObjectExpression,satisfies,ParameterizedType(TypeName,TypeArgList(TypeName))))))) From a25d6f9bb88b574dc1ef5870f1024bc7fc64796e Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 17 Apr 2025 08:08:48 +0200 Subject: [PATCH 47/59] Mark version 1.5.0 --- CHANGELOG.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd425a5..c35dda8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 1.5.0 (2025-04-17) + +### Bug fixes + +Support `in`/`out` modifiers on TypeScript type parameters. + +### New features + +Support the TypeScript `satisfies` operator. + ## 1.4.21 (2024-12-03) ### Bug fixes diff --git a/package.json b/package.json index e416b36..c57cd94 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.4.21", + "version": "1.5.0", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 005fd9e2d1534c5442ea20affc976010720210a0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 18 Apr 2025 17:46:38 +0200 Subject: [PATCH 48/59] Add highlighting for the satisfies op FIX: Properly highlight `satisfies` as a keyword. Issue https://github.com/lezer-parser/javascript/issues/45 --- src/highlight.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/highlight.js b/src/highlight.js index 71b03df..25c912b 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -3,10 +3,10 @@ import {styleTags, tags as t} from "@lezer/highlight" export const jsHighlight = styleTags({ "get set async static": t.modifier, "for while do if else switch try catch finally return throw break continue default case": t.controlKeyword, - "in of await yield void typeof delete instanceof": t.operatorKeyword, + "in of await yield void typeof delete instanceof as satisfies": t.operatorKeyword, "let var const using function class extends": t.definitionKeyword, "import export from": t.moduleKeyword, - "with debugger as new": t.keyword, + "with debugger new": t.keyword, TemplateString: t.special(t.string), super: t.atom, BooleanLiteral: t.bool, From d0770ec1bb8fd600c9d9cd118075524d446be7fd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 18 Apr 2025 17:48:24 +0200 Subject: [PATCH 49/59] Mark version 1.5.1 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c35dda8..f2c1e65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.5.1 (2025-04-18) + +### Bug fixes + +Properly highlight `satisfies` as a keyword. + ## 1.5.0 (2025-04-17) ### Bug fixes diff --git a/package.json b/package.json index c57cd94..2a50ace 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.5.0", + "version": "1.5.1", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 40b30e6fe4d6cd475201c0f10ecd853040245e24 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 12 May 2025 16:01:54 +0200 Subject: [PATCH 50/59] Bump @lezer/generator dependency to one that can handle local tokens --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2a50ace..d9b1981 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "author": "Marijn Haverbeke ", "license": "MIT", "devDependencies": { - "@lezer/generator": "^1.0.0", + "@lezer/generator": "^1.7.0", "mocha": "^10.2.0", "rollup": "^2.52.2", "@rollup/plugin-node-resolve": "^9.0.0" From f2fc878a1f03d8515613be3bfe0abe241a503f14 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 15 Jul 2025 14:46:11 +0200 Subject: [PATCH 51/59] Allow const types with angle-bracket prefix syntax FIX: Allow `const` casts with old angle-bracket cast syntax. Closes https://github.com/lezer-parser/javascript/issues/46 --- src/javascript.grammar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index f33ebba..2f6f79e 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -311,7 +311,7 @@ expressionNoComma { DynamicImport { kw<"import"> "(" expressionNoComma ")" } | ImportMeta { kw<"import"> "." PropertyName } | JSXElement | - PrefixCast { tsAngleOpen type ~tsAngle ">" expressionNoComma } | + PrefixCast { tsAngleOpen (type | kw<"const">) ~tsAngle ">" expressionNoComma } | ArrowFunction[@dynamicPrecedence=1] { TypeParamList { tsAngleOpen commaSep ">" } ParamList TypeAnnotation? "=>" (Block | expressionNoComma) } From 0b9b9b8226040cb5d21e3274a2f7969ed69650bd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 3 Sep 2025 11:41:08 +0200 Subject: [PATCH 52/59] Add support for import defer FIX: Add support for `import defer` syntax. Closes https://github.com/lezer-parser/javascript/issues/47 --- src/javascript.grammar | 4 ++-- test/statement.txt | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 2f6f79e..8997273 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -84,9 +84,9 @@ ExportGroup { } ImportDeclaration { - kw<"import"> tskw<"type">? (Star ckw<"as"> VariableDefinition | commaSep) + kw<"import"> ckw<"defer">? tskw<"type">? (Star ckw<"as"> VariableDefinition | commaSep) ckw<"from"> String semi | - kw<"import"> String semi + kw<"import"> ckw<"defer">? String semi } ImportGroup { diff --git a/test/statement.txt b/test/statement.txt index 9243488..4bf28d8 100644 --- a/test/statement.txt +++ b/test/statement.txt @@ -238,6 +238,8 @@ import { member } from "module-name"; import { member1, member2 as alias2 } from "module-name"; import defaultMember, { member1, member2 as alias2, } from "module-name"; import "module-name"; +import defer x from "y"; +import defer from "y"; ==> @@ -247,7 +249,9 @@ Script( ImportDeclaration(import,ImportGroup(VariableDefinition),from,String), ImportDeclaration(import,ImportGroup(VariableDefinition,VariableName,as,VariableDefinition),from,String), ImportDeclaration(import,VariableDefinition,ImportGroup(VariableDefinition,VariableName,as,VariableDefinition),from,String), - ImportDeclaration(import,String)) + ImportDeclaration(import,String), + ImportDeclaration(import,defer,VariableDefinition,from,String), + ImportDeclaration(import,VariableDefinition,from,String)) # Exports From 8fc1866393fd5795aeaebde42d06b6511dfc23d8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 4 Sep 2025 11:22:40 +0200 Subject: [PATCH 53/59] Mark version 1.5.2 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c1e65..09b4113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.5.2 (2025-09-04) + +### Bug fixes + +Allow `const` casts with old angle-bracket cast syntax. + +Add support for `import defer` syntax. + ## 1.5.1 (2025-04-18) ### Bug fixes diff --git a/package.json b/package.json index d9b1981..88942e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.5.1", + "version": "1.5.2", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From 349b4931825b1ce68d772c4ba8aa0888ccfb6375 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 9 Sep 2025 11:41:25 +0200 Subject: [PATCH 54/59] Add highlighting for defer keyword FIX: Fix missing highlight tag for `defer` contextual keyword. Issue https://github.com/lezer-parser/javascript/issues/47 --- src/highlight.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/highlight.js b/src/highlight.js index 25c912b..385f4c4 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -2,7 +2,7 @@ import {styleTags, tags as t} from "@lezer/highlight" export const jsHighlight = styleTags({ "get set async static": t.modifier, - "for while do if else switch try catch finally return throw break continue default case": t.controlKeyword, + "for while do if else switch try catch finally return throw break continue default case defer": t.controlKeyword, "in of await yield void typeof delete instanceof as satisfies": t.operatorKeyword, "let var const using function class extends": t.definitionKeyword, "import export from": t.moduleKeyword, From 9450f7efa94d6597c1cb4fc5fbdf3bc2bd3f755b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 9 Sep 2025 12:36:13 +0200 Subject: [PATCH 55/59] Mark version 1.5.3 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09b4113..ad387b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.5.3 (2025-09-09) + +### Bug fixes + +Fix missing highlight tag for `defer` contextual keyword. + ## 1.5.2 (2025-09-04) ### Bug fixes diff --git a/package.json b/package.json index 88942e8..b58dcfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.5.2", + "version": "1.5.3", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From a129dc39f360f04b0e5e8e14b130cef1ab0c3891 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 18 Sep 2025 13:50:24 +0200 Subject: [PATCH 56/59] Support this parameter types in TypeScript function types FIX: Support `this` parameters in function types. Issue https://github.com/lezer-parser/javascript/issues/48 --- src/javascript.grammar | 2 +- test/typescript.txt | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/javascript.grammar b/src/javascript.grammar index 8997273..c148f11 100644 --- a/src/javascript.grammar +++ b/src/javascript.grammar @@ -487,7 +487,7 @@ PropertyType { } ParamTypeList[@name=ParamList] { - "(" commaSep<"..."? pattern ~arrow Optional? ~arrow TypeAnnotation?> ")" + "(" commaSep<"..."? pattern ~arrow Optional? ~arrow TypeAnnotation? | kw<"this"> TypeAnnotation> ")" } @skip {} { diff --git a/test/typescript.txt b/test/typescript.txt index b5d772f..3a740a7 100644 --- a/test/typescript.txt +++ b/test/typescript.txt @@ -388,3 +388,14 @@ log(foo as number, {} satisfies AbstractObjectFactory) Script(ExpressionStatement(CallExpression(VariableName,ArgList( BinaryExpression(VariableName,as,TypeName), BinaryExpression(ObjectExpression,satisfies,ParameterizedType(TypeName,TypeArgList(TypeName))))))) + +# Allows this parameters in function types {"dialect": "ts"} + +let x: (this: X, expression: string) => Promise + +==> + +Script(VariableDeclaration(let,VariableDefinition,TypeAnnotation(FunctionSignature( + ParamList(this,TypeAnnotation(TypeName),VariableDefinition,TypeAnnotation(TypeName)), + Arrow, + ParameterizedType(TypeName,TypeArgList(ArrayType(TypeName))))))) From 371ae0e0659c18414a8e079c1eaa4586d400d9f0 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 18 Sep 2025 14:15:28 +0200 Subject: [PATCH 57/59] Mark version 1.5.4 --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad387b7..6c02a5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.5.4 (2025-09-18) + +### Bug fixes + +Support `this` parameters in function types. + ## 1.5.3 (2025-09-09) ### Bug fixes diff --git a/package.json b/package.json index b58dcfc..8c40f10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lezer/javascript", - "version": "1.5.3", + "version": "1.5.4", "description": "lezer-based JavaScript grammar", "main": "dist/index.cjs", "type": "module", From d28558ab1d686fcf54ca14dfa2d3cb20b41be7ae Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Tue, 14 Apr 2026 17:24:26 +0200 Subject: [PATCH 58/59] Update github links --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c40f10..1a12121 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/lezer-parser/javascript.git" + "url": "git+https://code.haverbeke.berlin/lezer/javascript.git" }, "scripts": { "build": "lezer-generator src/javascript.grammar -o src/parser && rollup -c", From 5575a6bf84ffc388c18b363e2ded91cf77c2c292 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 15 Apr 2026 08:43:36 +0200 Subject: [PATCH 59/59] Add forwarding link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f979492..6ebba94 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**This repository has moved to https://code.haverbeke.berlin/lezer/javascript** + # @lezer/javascript This is a JavaScript grammar for the