diff --git a/tools/apiview/emitters/cadl-apiview/src/apiview.ts b/tools/apiview/emitters/cadl-apiview/src/apiview.ts index 97d596d132ac..a103706b2bca 100644 --- a/tools/apiview/emitters/cadl-apiview/src/apiview.ts +++ b/tools/apiview/emitters/cadl-apiview/src/apiview.ts @@ -319,7 +319,6 @@ export class ApiView { if (name === this.packageName) { return true; } - // FIXME: This should actually ensure that it is a proper subnamespace if (!name.startsWith(this.packageName)) { return false; } @@ -343,7 +342,9 @@ export class ApiView { if (!this.shouldEmitNamespace(name)) { continue; } - const nsModel = new NamespaceModel(name, ns, program); + // use a fake name to make the global namespace clear + const namespaceName = name == "" ? "::GLOBAL::" : name; + const nsModel = new NamespaceModel(namespaceName, ns, program); if (nsModel.shouldEmit()) { this.tokenizeNamespaceModel(nsModel); this.buildNavigation(nsModel); diff --git a/tools/apiview/emitters/cadl-apiview/test/apiview-options.test.ts b/tools/apiview/emitters/cadl-apiview/test/apiview-options.test.ts index f5782f4de699..29ea0a74afb1 100644 --- a/tools/apiview/emitters/cadl-apiview/test/apiview-options.test.ts +++ b/tools/apiview/emitters/cadl-apiview/test/apiview-options.test.ts @@ -1,7 +1,7 @@ import { Diagnostic, logDiagnostics, resolvePath } from "@cadl-lang/compiler"; -import { expectDiagnosticEmpty } from "@cadl-lang/compiler/testing"; +import { expectDiagnosticEmpty, expectDiagnostics } from "@cadl-lang/compiler/testing"; import { strictEqual } from "assert"; -import { apiViewFor, apiViewText, compare } from "./test-host.js"; +import { apiViewFor, apiViewText, compare, createApiViewTestRunner, diagnosticsFor } from "./test-host.js"; describe("apiview-options: tests", () => { @@ -44,8 +44,16 @@ describe("apiview-options: tests", () => { } `; const expect = ` - model SomeGlobal {}; + namespace ::GLOBAL:: { + model SomeGlobal {} + } + @Cadl.service( + { + title: "Test"; + version: "1"; + } + ) namespace Azure.Test { model Foo {} } @@ -54,7 +62,53 @@ describe("apiview-options: tests", () => { "include-global-namespace": true }); const actual = apiViewText(apiview); - compare(expect, actual, 9); + compare(expect, actual, 1); }); + it("emits error if multi-service package tries to specify version", async () => { + const input = ` + @Cadl.service( { title: "Test", version: "1" } ) + namespace Azure.Test { + model Foo {}; + } + + @Cadl.service( { title: "OtherTest", version: "1" } ) + namespace Azure.OtherTest { + model Foo {}; + } + ` + const diagnostics = await diagnosticsFor(input, {"version": "1"}); + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/cadl-apiview/invalid-option", + message: `Option "--output-file" cannot be used with multi-service specs unless "--service" is also supplied.` + }, + { + code: "@azure-tools/cadl-apiview/invalid-option", + message: `Option "--version" cannot be used with multi-service specs unless "--service" is also supplied.` + } + ]); + }); + + it("allows options if multi-service package specifies --service", async () => { + const input = ` + @Cadl.service( { title: "Test", version: "1" } ) + namespace Azure.Test { + model Foo {}; + } + + @Cadl.service( { title: "OtherTest", version: "1" } ) + namespace Azure.OtherTest { + model Foo {}; + } + `; + const expect = ` + namespace Azure.OtherTest { + model Foo {} + } + `; + const apiview = await apiViewFor(input, {"version": "1", "service": "OtherTest"}); + const actual = apiViewText(apiview); + compare(expect, actual, 9); + }); }); diff --git a/tools/apiview/emitters/cadl-apiview/test/test-host.ts b/tools/apiview/emitters/cadl-apiview/test/test-host.ts index ac7e61312e98..6f030ba197b8 100644 --- a/tools/apiview/emitters/cadl-apiview/test/test-host.ts +++ b/tools/apiview/emitters/cadl-apiview/test/test-host.ts @@ -6,7 +6,7 @@ import { ApiViewTestLibrary } from "../src/testing/index.js"; import "@azure-tools/cadl-apiview"; import { ApiViewEmitterOptions } from "../src/lib.js"; import { ApiViewDocument, ApiViewTokenKind } from "../src/apiview.js"; -import { resolvePath } from "@cadl-lang/compiler"; +import { Diagnostic, resolvePath } from "@cadl-lang/compiler"; import { strictEqual } from "assert"; export async function createApiViewTestHost() { @@ -34,6 +34,17 @@ export async function createApiViewTestRunner({ }); } +export async function diagnosticsFor(code: string, options: ApiViewEmitterOptions): Promise { + const runner = await createApiViewTestRunner({withVersioning: true}); + const outPath = resolvePath("/apiview.json"); + const diagnostics = await runner.diagnose(code, { + noEmit: false, + emitters: { "@azure-tools/cadl-apiview": { ...options, "output-file": outPath } }, + miscOptions: { "disable-linter": true }, + }); + return diagnostics; +} + export async function apiViewFor(code: string, options: ApiViewEmitterOptions): Promise { const runner = await createApiViewTestRunner({withVersioning: true}); const outPath = resolvePath("/apiview.json");