From 61bb522a6424407602f4df65dda4be09c61d1b15 Mon Sep 17 00:00:00 2001 From: mshanemc Date: Mon, 8 Dec 2025 08:57:56 -0600 Subject: [PATCH 1/3] fix: W-8095488 (ternary without space gets treated as optional chaining) --- grammars/apex.tmLanguage | 2 +- grammars/apex.tmLanguage.cson | 2 +- grammars/soql.tmLanguage | 2 +- src/apex.tmLanguage.yml | 3 +- .../classes/TernaryWithDecimals_W8095488.cls | 88 +++++++++++++++++++ .../TernaryWithDecimals_W8095488.cls-meta.xml | 6 ++ 6 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 test/repros/force-app/main/default/classes/TernaryWithDecimals_W8095488.cls create mode 100644 test/repros/force-app/main/default/classes/TernaryWithDecimals_W8095488.cls-meta.xml diff --git a/grammars/apex.tmLanguage b/grammars/apex.tmLanguage index a9d52cc..62891de 100644 --- a/grammars/apex.tmLanguage +++ b/grammars/apex.tmLanguage @@ -3798,7 +3798,7 @@ conditional-operator begin - (?<!\?)\?(?!\?|\.|\[) + (?<!\?)\?(?!\?|\.(?!\d)|\[) beginCaptures 0 diff --git a/grammars/apex.tmLanguage.cson b/grammars/apex.tmLanguage.cson index 4accb9c..c32ff83 100644 --- a/grammars/apex.tmLanguage.cson +++ b/grammars/apex.tmLanguage.cson @@ -2242,7 +2242,7 @@ repository: } ] 'conditional-operator': - begin: '(?conditional-operator begin - (?<!\?)\?(?!\?|\.|\[) + (?<!\?)\?(?!\?|\.(?!\d)|\[) beginCaptures 0 diff --git a/src/apex.tmLanguage.yml b/src/apex.tmLanguage.yml index 5915856..3fe8b27 100644 --- a/src/apex.tmLanguage.yml +++ b/src/apex.tmLanguage.yml @@ -1342,7 +1342,8 @@ repository: # Only match ? if: # 1. There isn't a preceding or trailing ? (null-coalescing operator) # 2. There isn't a trailing . or [ (null-conditional operator) - begin: (? + + 58.0 + Active + + From bb0eea625800abaf25302afd2f8905457a408eb9 Mon Sep 17 00:00:00 2001 From: mshanemc Date: Mon, 8 Dec 2025 09:01:43 -0600 Subject: [PATCH 2/3] test: ternary space stuff --- test/expressions.tests.ts | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/expressions.tests.ts b/test/expressions.tests.ts index a63775e..ad05b52 100644 --- a/test/expressions.tests.ts +++ b/test/expressions.tests.ts @@ -235,6 +235,57 @@ Object newPoint = new Vector(point.x * z, 0);`); Token.Punctuation.Semicolon, ]); }); + + it('ternary with decimal literal without spaces (W-8095488)', async () => { + const input = Input.InMethod(`Decimal d = b?.34:0;`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.PrimitiveType.Decimal, + Token.Identifiers.LocalName('d'), + Token.Operators.Assignment, + Token.Variables.ReadWrite('b'), + Token.Operators.Conditional.QuestionMark, + Token.Literals.Numeric.Decimal('34'), + Token.Operators.Conditional.Colon, + Token.Literals.Numeric.Decimal('0'), + Token.Punctuation.Semicolon, + ]); + }); + + it('ternary with decimal literal with leading digits (W-8095488)', async () => { + const input = Input.InMethod(`Decimal i = b?.123:0;`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.PrimitiveType.Decimal, + Token.Identifiers.LocalName('i'), + Token.Operators.Assignment, + Token.Variables.ReadWrite('b'), + Token.Operators.Conditional.QuestionMark, + Token.Literals.Numeric.Decimal('123'), + Token.Operators.Conditional.Colon, + Token.Literals.Numeric.Decimal('0'), + Token.Punctuation.Semicolon, + ]); + }); + + it('ternary with decimal literal with spaces (W-8095488)', async () => { + const input = Input.InMethod(`Decimal d = b ? .34 : 0;`); + const tokens = await tokenize(input); + + tokens.should.deep.equal([ + Token.PrimitiveType.Decimal, + Token.Identifiers.LocalName('d'), + Token.Operators.Assignment, + Token.Variables.ReadWrite('b'), + Token.Operators.Conditional.QuestionMark, + Token.Literals.Numeric.Decimal('34'), + Token.Operators.Conditional.Colon, + Token.Literals.Numeric.Decimal('0'), + Token.Punctuation.Semicolon, + ]); + }); }); describe('Element Access', () => { From a1e44df9372a7f348e06f4fefee94c0393a77187 Mon Sep 17 00:00:00 2001 From: mshanemc Date: Mon, 8 Dec 2025 09:04:19 -0600 Subject: [PATCH 3/3] chore: test file naming --- package.json | 4 ++-- test/{annotation.tests.ts => annotation.test.ts} | 0 test/{class.tests.ts => class.test.ts} | 0 test/{comment.tests.ts => comment.test.ts} | 0 test/{constructor.tests.ts => constructor.test.ts} | 0 test/{enum.tests.ts => enum.test.ts} | 0 test/{expressions.tests.ts => expressions.test.ts} | 0 test/{field.tests.ts => field.test.ts} | 0 test/{for-statements.tests.ts => for-statements.test.ts} | 0 test/{incomplete-code.tests.ts => incomplete-code.test.ts} | 0 .../{initializer-block.tests.ts => initializer-block.test.ts} | 0 test/{interface.tests.ts => interface.test.ts} | 0 test/{javadoc.tests.ts => javadoc.test.ts} | 0 test/{literals.tests.ts => literals.test.ts} | 0 test/{local.tests.ts => local.test.ts} | 0 test/{method.tests.ts => method.test.ts} | 0 test/{operator.tests.ts => operator.test.ts} | 0 test/{property.tests.ts => property.test.ts} | 0 test/{queries.tests.ts => queries.test.ts} | 0 test/{statements.tests.ts => statements.test.ts} | 0 test/{switch.tests.ts => switch.test.ts} | 0 test/{system.tests.ts => system.test.ts} | 0 test/{trigger.tests.ts => trigger.test.ts} | 0 test/{type-name.tests.ts => type-name.test.ts} | 0 test/{xml-doc-comment.tests.ts => xml-doc-comment.test.ts} | 0 25 files changed, 2 insertions(+), 2 deletions(-) rename test/{annotation.tests.ts => annotation.test.ts} (100%) rename test/{class.tests.ts => class.test.ts} (100%) rename test/{comment.tests.ts => comment.test.ts} (100%) rename test/{constructor.tests.ts => constructor.test.ts} (100%) rename test/{enum.tests.ts => enum.test.ts} (100%) rename test/{expressions.tests.ts => expressions.test.ts} (100%) rename test/{field.tests.ts => field.test.ts} (100%) rename test/{for-statements.tests.ts => for-statements.test.ts} (100%) rename test/{incomplete-code.tests.ts => incomplete-code.test.ts} (100%) rename test/{initializer-block.tests.ts => initializer-block.test.ts} (100%) rename test/{interface.tests.ts => interface.test.ts} (100%) rename test/{javadoc.tests.ts => javadoc.test.ts} (100%) rename test/{literals.tests.ts => literals.test.ts} (100%) rename test/{local.tests.ts => local.test.ts} (100%) rename test/{method.tests.ts => method.test.ts} (100%) rename test/{operator.tests.ts => operator.test.ts} (100%) rename test/{property.tests.ts => property.test.ts} (100%) rename test/{queries.tests.ts => queries.test.ts} (100%) rename test/{statements.tests.ts => statements.test.ts} (100%) rename test/{switch.tests.ts => switch.test.ts} (100%) rename test/{system.tests.ts => system.test.ts} (100%) rename test/{trigger.tests.ts => trigger.test.ts} (100%) rename test/{type-name.tests.ts => type-name.test.ts} (100%) rename test/{xml-doc-comment.tests.ts => xml-doc-comment.test.ts} (100%) diff --git a/package.json b/package.json index 8535766..2920533 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "watch": "tsc -w -p .", "test:soql-tmgrammar": "vscode-tmgrammar-test -g \"./grammars/soql.tmLanguage\" \"./test/soql/*.soql\" ", "test:soql-tmgrammar-snapshots": "vscode-tmgrammar-snap -s source.soql -g \"./grammars/soql.tmLanguage\" \"./test/soql/snapshots/*.soql\" ", - "test": "npm run compile && mocha out/test/**/*.tests.js && npm run test:soql-tmgrammar && npm run test:soql-tmgrammar-snapshots", + "test": "npm run compile && mocha out/test/**/*.test.js && npm run test:soql-tmgrammar && npm run test:soql-tmgrammar-snapshots", "prepare": "npm run build", "format": "prettier --config .prettierrc.json --write './**/*.{ts,js,json,md}'" }, @@ -72,4 +72,4 @@ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } } -} +} \ No newline at end of file diff --git a/test/annotation.tests.ts b/test/annotation.test.ts similarity index 100% rename from test/annotation.tests.ts rename to test/annotation.test.ts diff --git a/test/class.tests.ts b/test/class.test.ts similarity index 100% rename from test/class.tests.ts rename to test/class.test.ts diff --git a/test/comment.tests.ts b/test/comment.test.ts similarity index 100% rename from test/comment.tests.ts rename to test/comment.test.ts diff --git a/test/constructor.tests.ts b/test/constructor.test.ts similarity index 100% rename from test/constructor.tests.ts rename to test/constructor.test.ts diff --git a/test/enum.tests.ts b/test/enum.test.ts similarity index 100% rename from test/enum.tests.ts rename to test/enum.test.ts diff --git a/test/expressions.tests.ts b/test/expressions.test.ts similarity index 100% rename from test/expressions.tests.ts rename to test/expressions.test.ts diff --git a/test/field.tests.ts b/test/field.test.ts similarity index 100% rename from test/field.tests.ts rename to test/field.test.ts diff --git a/test/for-statements.tests.ts b/test/for-statements.test.ts similarity index 100% rename from test/for-statements.tests.ts rename to test/for-statements.test.ts diff --git a/test/incomplete-code.tests.ts b/test/incomplete-code.test.ts similarity index 100% rename from test/incomplete-code.tests.ts rename to test/incomplete-code.test.ts diff --git a/test/initializer-block.tests.ts b/test/initializer-block.test.ts similarity index 100% rename from test/initializer-block.tests.ts rename to test/initializer-block.test.ts diff --git a/test/interface.tests.ts b/test/interface.test.ts similarity index 100% rename from test/interface.tests.ts rename to test/interface.test.ts diff --git a/test/javadoc.tests.ts b/test/javadoc.test.ts similarity index 100% rename from test/javadoc.tests.ts rename to test/javadoc.test.ts diff --git a/test/literals.tests.ts b/test/literals.test.ts similarity index 100% rename from test/literals.tests.ts rename to test/literals.test.ts diff --git a/test/local.tests.ts b/test/local.test.ts similarity index 100% rename from test/local.tests.ts rename to test/local.test.ts diff --git a/test/method.tests.ts b/test/method.test.ts similarity index 100% rename from test/method.tests.ts rename to test/method.test.ts diff --git a/test/operator.tests.ts b/test/operator.test.ts similarity index 100% rename from test/operator.tests.ts rename to test/operator.test.ts diff --git a/test/property.tests.ts b/test/property.test.ts similarity index 100% rename from test/property.tests.ts rename to test/property.test.ts diff --git a/test/queries.tests.ts b/test/queries.test.ts similarity index 100% rename from test/queries.tests.ts rename to test/queries.test.ts diff --git a/test/statements.tests.ts b/test/statements.test.ts similarity index 100% rename from test/statements.tests.ts rename to test/statements.test.ts diff --git a/test/switch.tests.ts b/test/switch.test.ts similarity index 100% rename from test/switch.tests.ts rename to test/switch.test.ts diff --git a/test/system.tests.ts b/test/system.test.ts similarity index 100% rename from test/system.tests.ts rename to test/system.test.ts diff --git a/test/trigger.tests.ts b/test/trigger.test.ts similarity index 100% rename from test/trigger.tests.ts rename to test/trigger.test.ts diff --git a/test/type-name.tests.ts b/test/type-name.test.ts similarity index 100% rename from test/type-name.tests.ts rename to test/type-name.test.ts diff --git a/test/xml-doc-comment.tests.ts b/test/xml-doc-comment.test.ts similarity index 100% rename from test/xml-doc-comment.tests.ts rename to test/xml-doc-comment.test.ts