Skip to content

Commit bb22945

Browse files
committed
Closes #1868.
1 parent 8925f8c commit bb22945

4 files changed

Lines changed: 47 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@typespec/versioning",
5+
"comment": "Added validation preventing version enums from having duplicate values.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@typespec/versioning"
10+
}

packages/versioning/src/lib.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ const libDef = {
3939
default: paramMessage`The provided version '${"version"}' from '${"enumName"}' is not declared as a version enum. Use '@versioned(${"enumName"})' on the containing namespace.`,
4040
},
4141
},
42+
"version-duplicate": {
43+
severity: "error",
44+
messages: {
45+
default: paramMessage`Multiple versions from '${"name"}' resolve to the same value. Version enums must resolve to unique values.`,
46+
},
47+
},
4248
"using-versioned-library": {
4349
severity: "error",
4450
messages: {

packages/versioning/src/validate.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ export function $onValidate(program: Program) {
9595
},
9696
namespace: (namespace) => {
9797
const [_, versionMap] = getVersions(program, namespace);
98+
const size = versionMap?.size;
99+
const values = new Set(versionMap?.getVersions().map((v) => v.value));
100+
if (size && values) {
101+
if (size !== values.size) {
102+
const enumName = versionMap.getVersions()[0].enumMember.enum.name;
103+
reportDiagnostic(program, {
104+
code: "version-duplicate",
105+
format: { name: enumName },
106+
target: namespace,
107+
});
108+
}
109+
}
98110
const serviceProps = getService(program, namespace);
99111
if (serviceProps?.version !== undefined && versionMap !== undefined) {
100112
reportDiagnostic(program, {

packages/versioning/test/incompatible-versioning.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ describe("versioning: incompatible use of decorators", () => {
4242
severity: "error",
4343
});
4444
});
45+
46+
it("emit diagnostic when version enum has duplicate values", async () => {
47+
const diagnostics = await runner.diagnose(`
48+
@versioned(Versions)
49+
namespace DemoService;
50+
51+
enum Versions {
52+
v1: "v1",
53+
v2: "v2",
54+
latest: "v2",
55+
}
56+
`);
57+
expectDiagnostics(diagnostics, {
58+
code: "@typespec/versioning/version-duplicate",
59+
message:
60+
"Multiple versions from 'Versions' resolve to the same value. Version enums must resolve to unique values.",
61+
severity: "error",
62+
});
63+
});
4564
});
4665

4766
describe("versioning: validate incompatible references", () => {

0 commit comments

Comments
 (0)