diff --git a/common/changes/@typespec/compiler/augment-statement-semicolon_2023-08-30-12-49.json b/common/changes/@typespec/compiler/augment-statement-semicolon_2023-08-30-12-49.json new file mode 100644 index 00000000000..6de1a078c15 --- /dev/null +++ b/common/changes/@typespec/compiler/augment-statement-semicolon_2023-08-30-12-49.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@typespec/compiler", + "comment": "**Breaking Change** A semicolon is now required after augment decorator statements.", + "type": "none" + } + ], + "packageName": "@typespec/compiler" +} \ No newline at end of file diff --git a/docs/language-basics/decorators.md b/docs/language-basics/decorators.md index 2cc5d79dd8e..929cbe5dc89 100644 --- a/docs/language-basics/decorators.md +++ b/docs/language-basics/decorators.md @@ -34,7 +34,7 @@ model Dog {} ## Augment decorators -Decorators can also be used from a different location by referring to the type being decorated. For this you can declare an augment decorator using the `@@` prefix. The first argument of an augment decorator is the type reference that should be decorated. +Decorators can also be used from a different location by referring to the type being decorated. For this you can declare an augment decorator using the `@@` prefix. The first argument of an augment decorator is the type reference that should be decorated. As the augment decorator is a statement, it must end with a semicolon (`;`). ```typespec model Dog {} diff --git a/docs/language-basics/overview.md b/docs/language-basics/overview.md index 68d5cf5f496..9d615fa0e2b 100644 --- a/docs/language-basics/overview.md +++ b/docs/language-basics/overview.md @@ -47,7 +47,7 @@ _Details: [Decorators](./decorators.md)_ | Use decorator with arguments | `@tag("abc")` | | Declare a decorator in JS | `export function $tag(context: DecoratorContext, target: Type, name: string) {...}` | | Save state in decorator | `context.program.stateMap(key).set(target, )` | -| Augment decorator | `@@tag(MyType, "abc")` | +| Augment decorator | `@@tag(MyType, "abc");` | ## Scalars diff --git a/packages/compiler/src/core/parser.ts b/packages/compiler/src/core/parser.ts index 5f58395a545..b3f03ab638b 100644 --- a/packages/compiler/src/core/parser.ts +++ b/packages/compiler/src/core/parser.ts @@ -1188,6 +1188,9 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa ...finishNode(pos), }; } + + parseExpected(Token.Semicolon); + return { kind: SyntaxKind.AugmentDecoratorStatement, target, diff --git a/packages/compiler/test/checker/augment-decorators.test.ts b/packages/compiler/test/checker/augment-decorators.test.ts index c011bced363..e6e79769a64 100644 --- a/packages/compiler/test/checker/augment-decorators.test.ts +++ b/packages/compiler/test/checker/augment-decorators.test.ts @@ -153,7 +153,7 @@ describe("compiler: checker: augment decorators", () => { it("namespace", () => expectTarget(`@test("target") namespace Foo {}`, "Foo")); - it("global namespace", () => expectTarget(`@@test(global, "target")`, "global")); + it("global namespace", () => expectTarget(`@@test(global, "target");`, "global")); it("model", () => expectTarget(`@test("target") model Foo {}`, "Foo")); it("model property", () => @@ -288,7 +288,7 @@ describe("compiler: checker: augment decorators", () => { } namespace MyService { - @@customName(Lib.Foo, "FooCustom") + @@customName(Lib.Foo, "FooCustom"); } `); }); @@ -298,12 +298,12 @@ describe("compiler: checker: augment decorators", () => { await expectAugmentTarget(` import "./lib.tsp"; - @@customName(Foo, "FooCustom") + @@customName(Foo, "FooCustom"); `); }); it("augment type in another file checked after", async () => { - testHost.addTypeSpecFile("lib.tsp", `@@customName(Foo, "FooCustom") `); + testHost.addTypeSpecFile("lib.tsp", `@@customName(Foo, "FooCustom"); `); await expectAugmentTarget(` import "./lib.tsp"; @@ -345,7 +345,7 @@ describe("compiler: checker: augment decorators", () => { @test("target") @customName("Foo") model Foo {} - @@customName(Foo, "FooCustom") + @@customName(Foo, "FooCustom"); `); }); @@ -354,8 +354,8 @@ describe("compiler: checker: augment decorators", () => { @test("target") @customName("Foo") model Foo {} - @@customName(Foo, "NonCustom") - @@customName(Foo, "FooCustom") + @@customName(Foo, "NonCustom"); + @@customName(Foo, "FooCustom"); `); }); }); diff --git a/packages/compiler/test/checker/enum.test.ts b/packages/compiler/test/checker/enum.test.ts index 595d1e184af..eed92499d08 100644 --- a/packages/compiler/test/checker/enum.test.ts +++ b/packages/compiler/test/checker/enum.test.ts @@ -164,7 +164,7 @@ describe("compiler: enums", () => { @test enum Base {@doc("base doc") one} @test enum Spread {...Base} - @@doc(Spread.one, "override for spread") + @@doc(Spread.one, "override for spread"); ` ); const { Base, Spread } = (await testHost.compile("main.tsp")) as { diff --git a/packages/compiler/test/checker/interface.test.ts b/packages/compiler/test/checker/interface.test.ts index fc1c4665a2f..cce6337dec1 100644 --- a/packages/compiler/test/checker/interface.test.ts +++ b/packages/compiler/test/checker/interface.test.ts @@ -446,7 +446,7 @@ describe("compiler: interfaces", () => { ` @test interface Base {@doc("base doc") one(): void} @test interface Extending extends Base {} - @@doc(Extending.one, "override for spread") + @@doc(Extending.one, "override for spread"); ` ); const { Base, Extending } = (await testHost.compile("main.tsp")) as { diff --git a/packages/compiler/test/checker/model.test.ts b/packages/compiler/test/checker/model.test.ts index 008e37f1b12..85d873e8132 100644 --- a/packages/compiler/test/checker/model.test.ts +++ b/packages/compiler/test/checker/model.test.ts @@ -404,7 +404,7 @@ describe("compiler: models", () => { @test model Base {@doc("base doc") one: string} @test model Spread {...Base} - @@doc(Spread.one, "override for spread") + @@doc(Spread.one, "override for spread"); ` ); const { Base, Spread } = (await testHost.compile("main.tsp")) as { diff --git a/packages/compiler/test/checker/operations.test.ts b/packages/compiler/test/checker/operations.test.ts index 68575b3822f..f2a79bb7331 100644 --- a/packages/compiler/test/checker/operations.test.ts +++ b/packages/compiler/test/checker/operations.test.ts @@ -64,7 +64,7 @@ describe("compiler: operations", () => { @test op a(@doc("base doc") one: string): void; @test op b is a; - @@doc(b::parameters.one, "override for b") + @@doc(b::parameters.one, "override for b"); ` ); const { a, b } = (await testHost.compile("main.tsp")) as { a: Operation; b: Operation }; @@ -80,7 +80,7 @@ describe("compiler: operations", () => { @test op b is a; @test op c is a; - @@doc(b::parameters.one, "override for b") + @@doc(b::parameters.one, "override for b"); ` ); const { b, c } = (await testHost.compile("main.tsp")) as { b: Operation; c: Operation }; diff --git a/packages/compiler/test/decorator-utils.test.ts b/packages/compiler/test/decorator-utils.test.ts index 8a2a15612ca..427e43c1c3d 100644 --- a/packages/compiler/test/decorator-utils.test.ts +++ b/packages/compiler/test/decorator-utils.test.ts @@ -196,7 +196,7 @@ describe("compiler: decorator utils", () => { @bar model Foo {} - @@bar(Foo) + @@bar(Foo); `); expectDiagnosticEmpty(diagnostics); @@ -293,7 +293,7 @@ describe("compiler: decorator utils", () => { @red model Foo {} - @@blue(Foo) + @@blue(Foo); `); expectDiagnostics(diagnostics, [