From b7a6e41032495d1e9fb46c2cfd8d1ac38a044e10 Mon Sep 17 00:00:00 2001 From: Allen Zhang Date: Tue, 7 Nov 2023 07:48:09 -0800 Subject: [PATCH] Adding docs on the correct base level namespace (#2643) #2642 --- ...hang_namespaceDevDoc_2023-11-07-04-52.json | 10 +++ packages/compiler/src/core/parser.ts | 16 ++-- .../test/decorators/decorators.test.ts | 73 ++++++++++++++++++- 3 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 common/changes/@typespec/compiler/azhang_namespaceDevDoc_2023-11-07-04-52.json diff --git a/common/changes/@typespec/compiler/azhang_namespaceDevDoc_2023-11-07-04-52.json b/common/changes/@typespec/compiler/azhang_namespaceDevDoc_2023-11-07-04-52.json new file mode 100644 index 0000000000..394d0e8de6 --- /dev/null +++ b/common/changes/@typespec/compiler/azhang_namespaceDevDoc_2023-11-07-04-52.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@typespec/compiler", + "comment": "Fixing @doc and /** */ disappears from multi-segment or nested namespaces. #2642", + "type": "none" + } + ], + "packageName": "@typespec/compiler" +} \ No newline at end of file diff --git a/packages/compiler/src/core/parser.ts b/packages/compiler/src/core/parser.ts index d3c66f9c4a..444dc42552 100644 --- a/packages/compiler/src/core/parser.ts +++ b/packages/compiler/src/core/parser.ts @@ -413,7 +413,7 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa item = parseScalarStatement(pos, decorators); break; case Token.NamespaceKeyword: - item = parseNamespaceStatement(pos, decorators); + item = parseNamespaceStatement(pos, decorators, docs); break; case Token.InterfaceKeyword: item = parseInterfaceStatement(pos, decorators); @@ -455,7 +455,9 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa } mutate(item).directives = directives; - mutate(item).docs = docs; + if (tok !== Token.NamespaceKeyword) { + mutate(item).docs = docs; + } if (isBlocklessNamespace(item)) { if (seenBlocklessNs) { @@ -506,7 +508,7 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa item = parseScalarStatement(pos, decorators); break; case Token.NamespaceKeyword: - const ns = parseNamespaceStatement(pos, decorators); + const ns = parseNamespaceStatement(pos, decorators, docs); if (!Array.isArray(ns.statements)) { error({ code: "blockless-namespace-first", messageId: "topLevel", target: ns }); @@ -554,7 +556,9 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa break; } mutate(item).directives = directives; - mutate(item).docs = docs; + if (tok !== Token.NamespaceKeyword) { + mutate(item).docs = docs; + } stmts.push(item); } @@ -583,7 +587,8 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa function parseNamespaceStatement( pos: number, - decorators: DecoratorExpressionNode[] + decorators: DecoratorExpressionNode[], + docs: DocNode[] ): NamespaceStatementNode { parseExpected(Token.NamespaceKeyword); let currentName = parseIdentifierOrMemberExpression(); @@ -605,6 +610,7 @@ function createParser(code: string | SourceFile, options: ParseOptions = {}): Pa let outerNs: NamespaceStatementNode = { kind: SyntaxKind.NamespaceStatement, decorators, + docs: docs, id: nsSegments[0], locals: undefined!, statements, diff --git a/packages/compiler/test/decorators/decorators.test.ts b/packages/compiler/test/decorators/decorators.test.ts index 6ab18c5ae3..1e5a77112c 100644 --- a/packages/compiler/test/decorators/decorators.test.ts +++ b/packages/compiler/test/decorators/decorators.test.ts @@ -1,5 +1,5 @@ import { deepStrictEqual, ok, strictEqual } from "assert"; -import { Model, Operation, Scalar, getVisibility, isSecret } from "../../src/index.js"; +import { Model, Namespace, Operation, Scalar, getVisibility, isSecret } from "../../src/index.js"; import { getDoc, getEncode, @@ -21,6 +21,75 @@ describe("compiler: built-in decorators", () => { runner = await createTestRunner(); }); + describe("dev comment /** */", () => { + it("applies /** */ on blockless namespace", async () => { + const { Foo } = await runner.compile( + ` + @test + /** doc for namespace Foo */ + namespace TestDoc.Foo; + + model A {} + ` + ); + + strictEqual(getDoc(runner.program, Foo), "doc for namespace Foo"); + }); + + it("applies /** */ on enclosed namespace", async () => { + const { Foo } = await runner.compile( + ` + @test + /** doc for namespace Foo */ + namespace TestDoc.Foo { + model A {} + } + ` + ); + + strictEqual(getDoc(runner.program, Foo), "doc for namespace Foo"); + }); + + it("applies /** */ on nested enclosed namespace", async () => { + const { Foo } = await runner.compile( + // const { Foo, Foo_Bar } = await runner.compile( + ` + @test + /** doc for namespace Foo */ + namespace TestDoc.Foo { + /** doc for namespace Bar */ + namespace Bar { + model A {}; + } + } + ` + ); + + const Bar = (Foo as Namespace).namespaces.get("Bar")!; + strictEqual(getDoc(runner.program, Foo), "doc for namespace Foo"); + strictEqual(getDoc(runner.program, Bar), "doc for namespace Bar"); + }); + + it("applies /** */ on nested blockless + enclosed namespace", async () => { + const { Foo } = await runner.compile( + ` + @test + /** doc for namespace Foo */ + namespace TestDoc.Foo; + + /** doc for namespace Bar */ + namespace Bar { + model A {} + } + ` + ); + + const Bar = (Foo as Namespace).namespaces.get("Bar")!; + strictEqual(getDoc(runner.program, Foo), "doc for namespace Foo"); + strictEqual(getDoc(runner.program, Bar), "doc for namespace Bar"); + }); + }); + describe("@doc", () => { it("applies @doc on model", async () => { const { A } = await runner.compile( @@ -59,7 +128,7 @@ describe("compiler: built-in decorators", () => { ` @test @doc("doc for namespace") - namespace TestDoc { + namespace Foo.TestDoc { } ` );