Skip to content

Commit

Permalink
Add validation to make sure operation params reference models availab…
Browse files Browse the repository at this point in the history
…le in the current version (#4179)

fix [#3920](#3920)
fix [#3134](#3134)
  • Loading branch information
timotheeguerin authored Aug 29, 2024
1 parent 302e0c7 commit 133321f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 3 deletions.
8 changes: 8 additions & 0 deletions .chronus/changes/fix-validate-op-params-2024-7-13-19-39-34.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@typespec/versioning"
---

Add validation to make sure operation params reference models available in the current version
8 changes: 8 additions & 0 deletions .chronus/changes/fix-validate-op-params-2024-7-13-19-39-35.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@typespec/versioning"
---

Add validation to make sure types referencing array in union types have compatible versioning.
21 changes: 18 additions & 3 deletions packages/versioning/src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ export function $onValidate(program: Program) {
for (const sourceModel of op.parameters.sourceModels) {
validateReference(program, op, sourceModel.model);
}

for (const prop of op.parameters.properties.values()) {
// Validate op -> property have correct versioning
validateTargetVersionCompatible(program, op, prop, {
isTargetADependent: true,
});

// Validate model property -> type have correct versioning
const typeChangedFrom = getTypeChangedFrom(program, prop);
if (typeChangedFrom !== undefined) {
validateMultiTypeReference(program, prop);
} else {
validateReference(program, prop, prop.type);
}
}
},
interface: (iface) => {
for (const source of iface.sourceInterfaces) {
Expand Down Expand Up @@ -511,20 +526,20 @@ function validateReference(program: Program, source: Type, target: Type) {
if ("templateMapper" in target) {
for (const param of target.templateMapper?.args ?? []) {
if (isType(param)) {
validateTargetVersionCompatible(program, source, param);
validateReference(program, source, param);
}
}
}

switch (target.kind) {
case "Union":
for (const variant of target.variants.values()) {
validateTargetVersionCompatible(program, source, variant.type);
validateReference(program, source, variant.type);
}
break;
case "Tuple":
for (const value of target.values) {
validateTargetVersionCompatible(program, source, value);
validateReference(program, source, value);
}
break;
}
Expand Down
25 changes: 25 additions & 0 deletions packages/versioning/test/incompatible-versioning.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,20 @@ describe("versioning: validate incompatible references", () => {
});
});

describe("operations", () => {
it("emit diagnostic when unversioned parameter type is a versioned model", async () => {
const diagnostics = await runner.diagnose(`
@added(Versions.v2)
model Foo {}
op test(param: Foo): void;
`);
expectDiagnostics(diagnostics, {
code: "@typespec/versioning/incompatible-versioned-reference",
});
});
});

describe("complex type references", () => {
it("emit diagnostic when using versioned model as template argument in non versioned property", async () => {
const diagnostics = await runner.diagnose(`
Expand Down Expand Up @@ -584,6 +598,17 @@ describe("versioning: validate incompatible references", () => {
});
});

it("emit diagnostic when using versioned union variant of array in non versioned source", async () => {
const diagnostics = await runner.diagnose(`
@added(Versions.v2)
model Versioned {}
op test(): Versioned[] | string;
`);
expectDiagnostics(diagnostics, {
code: "@typespec/versioning/incompatible-versioned-reference",
});
});

it("emit diagnostic when using versioned tuple element in nin versioned operation return type", async () => {
const diagnostics = await runner.diagnose(`
@added(Versions.v2)
Expand Down

0 comments on commit 133321f

Please sign in to comment.