From 3a1e52efb1aa1b497fbde4d86d44c9dc08036247 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Wed, 23 Oct 2024 09:24:51 -0700 Subject: [PATCH 1/3] Allow trailing delimited in most locations --- packages/compiler/src/core/parser.ts | 3 ++- packages/compiler/test/parser.test.ts | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/compiler/src/core/parser.ts b/packages/compiler/src/core/parser.ts index c12954ffce8..b38c56a5141 100644 --- a/packages/compiler/src/core/parser.ts +++ b/packages/compiler/src/core/parser.ts @@ -269,7 +269,7 @@ namespace ListKind { delimiter: Token.Comma, toleratedDelimiter: Token.Semicolon, toleratedDelimiterIsValid: false, - trailingDelimiterIsValid: false, + trailingDelimiterIsValid: true, invalidAnnotationTarget: "expression", allowedStatementKeyword: Token.None, } as const; @@ -296,6 +296,7 @@ namespace ListKind { export const Heritage = { ...ExpresionsBase, allowEmpty: false, + trailingDelimiterIsValid: false, open: Token.None, close: Token.None, } as const; diff --git a/packages/compiler/test/parser.test.ts b/packages/compiler/test/parser.test.ts index ff3169e504e..3dca1358889 100644 --- a/packages/compiler/test/parser.test.ts +++ b/packages/compiler/test/parser.test.ts @@ -168,11 +168,18 @@ describe("compiler: parser", () => { `scalar bar extends uuid { init fromOther(abc: string) }`, + `scalar bar extends uuid { + init trailingComma(abc: string, def: string,) + }`, ]); parseErrorEach([["scalar uuid is string;", [{ message: "'{' expected." }]]]); }); + describe("operation statements", () => { + parseEach(["op foo(): int32;", "op trailingCommas(a: string,b: other,): int32;"]); + }); + describe("interface statements", () => { parseEach([ "interface Foo { }", @@ -190,6 +197,7 @@ describe("compiler: parser", () => { ["interface X { foo(a: string", [/'\)' expected/]], ["interface X { foo(@myDec", [/Property expected/]], ["interface X { foo(#suppress x", [/Property expected/]], + ["interface TrailingComma extends A, B, {}", [{ code: "token-expected" }]], ]); }); @@ -202,6 +210,7 @@ describe("compiler: parser", () => { 'namespace A { op b(param: [number, string]): [1, "hi"]; }', "alias EmptyTuple = [];", "model Template { }", + "alias TrailingComma = [1, 2,];", ]); }); @@ -245,6 +254,7 @@ describe("compiler: parser", () => { `const a = int8(123);`, `const a = utcDateTime.fromISO("abc");`, `const a = utcDateTime.fromISO("abc", "def");`, + `const trailingComma = utcDateTime.fromISO("abc", "def",);`, ]); parseErrorEach([ [`const a = int8(123;`, [{ message: "')' expected." }]], @@ -266,6 +276,7 @@ describe("compiler: parser", () => { `const A = #["abc"];`, `const A = #["abc", 123];`, `const A = #["abc", 123, #{nested: true}];`, + `const Trailing = #["abc", 123,];`, ]); }); @@ -814,6 +825,7 @@ describe("compiler: parser", () => { "extern dec myDec(target: Type, optional?: StringLiteral);", "extern dec myDec(target: Type, ...rest: StringLiteral[]);", "extern dec myDec(target, arg1, ...rest);", + "extern dec trailingComma(target, arg1: other, arg2: string,);", ]); parseErrorEach([ @@ -861,6 +873,7 @@ describe("compiler: parser", () => { "extern fn myDec(optional?: StringLiteral): void;", "extern fn myDec(...rest: StringLiteral[]): void;", "extern fn myDec(arg1, ...rest): void;", + "extern fn trailingComma(arg1: other, arg2: string,);", ]); parseErrorEach([ @@ -1237,6 +1250,14 @@ describe("compiler: parser", () => { ); }); + describe("template parameters", () => { + parseEach(["model Foo {}", "model TrailingComma {}"]); + }); + + describe("template arguments", () => { + parseEach(["alias Test = Foo;", "alias TrailingComma = Foo;"]); + }); + describe("annotations order", () => { function expectHasDocComment(script: TypeSpecScriptNode, content: string, index: number = 0) { const docs = script.statements[0].docs; From f3ee0220d1364daba2e18e880e665e47fa1e5137 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Wed, 23 Oct 2024 09:42:48 -0700 Subject: [PATCH 2/3] follow issue --- packages/compiler/src/core/messages.ts | 6 ------ packages/compiler/src/core/parser.ts | 16 ---------------- packages/compiler/test/parser.test.ts | 1 - 3 files changed, 23 deletions(-) diff --git a/packages/compiler/src/core/messages.ts b/packages/compiler/src/core/messages.ts index d0033888ca1..3198159fcf3 100644 --- a/packages/compiler/src/core/messages.ts +++ b/packages/compiler/src/core/messages.ts @@ -150,12 +150,6 @@ const diagnostics = { typeofTarget: "Typeof expects a value literal or value reference.", }, }, - "trailing-token": { - severity: "error", - messages: { - default: paramMessage`Trailing ${"token"}`, - }, - }, "unknown-directive": { severity: "error", messages: { diff --git a/packages/compiler/src/core/parser.ts b/packages/compiler/src/core/parser.ts index b38c56a5141..1b7116a7a65 100644 --- a/packages/compiler/src/core/parser.ts +++ b/packages/compiler/src/core/parser.ts @@ -171,7 +171,6 @@ interface ListKind { readonly delimiter: DelimiterToken; readonly toleratedDelimiter: DelimiterToken; readonly toleratedDelimiterIsValid: boolean; - readonly trailingDelimiterIsValid: boolean; readonly invalidAnnotationTarget?: string; readonly allowedStatementKeyword: Token; } @@ -193,7 +192,6 @@ namespace ListKind { const PropertiesBase = { allowEmpty: true, toleratedDelimiterIsValid: true, - trailingDelimiterIsValid: true, allowedStatementKeyword: Token.None, } as const; @@ -269,7 +267,6 @@ namespace ListKind { delimiter: Token.Comma, toleratedDelimiter: Token.Semicolon, toleratedDelimiterIsValid: false, - trailingDelimiterIsValid: true, invalidAnnotationTarget: "expression", allowedStatementKeyword: Token.None, } as const; @@ -296,7 +293,6 @@ namespace ListKind { export const Heritage = { ...ExpresionsBase, allowEmpty: false, - trailingDelimiterIsValid: false, open: Token.None, close: Token.None, } as const; @@ -3231,23 +3227,11 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa } r.items.push(item); - const delimiter = token(); - const delimiterPos = tokenPos(); if (parseOptionalDelimiter(kind)) { // Delimiter found: check if it's trailing. if (parseOptional(kind.close)) { mutate(r.range).end = previousTokenEnd; - if (!kind.trailingDelimiterIsValid) { - error({ - code: "trailing-token", - format: { token: TokenDisplay[delimiter] }, - target: { - pos: delimiterPos, - end: delimiterPos + 1, - }, - }); - } // It was trailing and we've consumed the close token. break; } diff --git a/packages/compiler/test/parser.test.ts b/packages/compiler/test/parser.test.ts index 3dca1358889..749d1fe7065 100644 --- a/packages/compiler/test/parser.test.ts +++ b/packages/compiler/test/parser.test.ts @@ -197,7 +197,6 @@ describe("compiler: parser", () => { ["interface X { foo(a: string", [/'\)' expected/]], ["interface X { foo(@myDec", [/Property expected/]], ["interface X { foo(#suppress x", [/Property expected/]], - ["interface TrailingComma extends A, B, {}", [{ code: "token-expected" }]], ]); }); From 6723df150bea141742f52c99856d65ae910f5152 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Wed, 23 Oct 2024 09:45:49 -0700 Subject: [PATCH 3/3] Create trailing-delimited-most-locations-2024-9-23-16-28-11.md --- ...railing-delimited-most-locations-2024-9-23-16-28-11.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .chronus/changes/trailing-delimited-most-locations-2024-9-23-16-28-11.md diff --git a/.chronus/changes/trailing-delimited-most-locations-2024-9-23-16-28-11.md b/.chronus/changes/trailing-delimited-most-locations-2024-9-23-16-28-11.md new file mode 100644 index 00000000000..c305222010b --- /dev/null +++ b/.chronus/changes/trailing-delimited-most-locations-2024-9-23-16-28-11.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: feature +packages: + - "@typespec/compiler" +--- + +Allow trailing delimiter in array values, tuple, decorator declaration, scalar initializer, etc.