This commit is contained in:
Travis Prescott 2023-01-19 11:03:29 -08:00 коммит произвёл GitHub
Родитель 078a871588
Коммит e5957bf74f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 80 добавлений и 85 удалений

Просмотреть файл

@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@cadl-lang/versioning",
"comment": "",
"type": "none"
}
],
"packageName": "@cadl-lang/versioning"
}

Просмотреть файл

@ -21,20 +21,17 @@ import {
} from "./versioning.js";
export function $onValidate(program: Program) {
const namespaceDependencies = new Map();
const namespaceDependencies = new Map<Namespace | undefined, Set<Namespace>>();
function addDependency(source: Namespace | undefined, target: Type | undefined) {
if (target === undefined || !("namespace" in target) || target.namespace === undefined) {
if (!target || !("namespace" in target) || !target.namespace) {
return;
}
let set = namespaceDependencies.get(source);
if (set === undefined) {
set = new Set();
namespaceDependencies.set(source, set);
}
const set = namespaceDependencies.get(source) ?? new Set<Namespace>();
if (target.namespace !== source) {
set.add(target.namespace);
}
namespaceDependencies.set(source, set);
}
navigateProgram(
@ -119,7 +116,15 @@ export function $onValidate(program: Program) {
return;
}
for (const [depNs, deps] of useDependencies) {
namespaceDependencies.set(depNs, deps);
const set = new Set<Namespace>();
if (deps instanceof Map) {
for (const val of deps.values()) {
set.add(val.namespace);
}
} else {
set.add(deps.namespace);
}
namespaceDependencies.set(depNs, set);
}
},
},

Просмотреть файл

@ -394,14 +394,15 @@ export function $useDependency(
const targetEnum = target.enum;
let state = context.program.stateMap(useDependencyEnumKey).get(targetEnum) as Map<
EnumMember,
Version
Version[]
>;
if (!state) {
state = new Map<EnumMember, Version>();
}
for (const v of versions) {
state.set(target, v);
state = new Map<EnumMember, Version[]>();
}
// get any existing versions and combine them
const currentVersions = state.get(target) ?? [];
currentVersions.push(...versions);
state.set(target, currentVersions);
context.program.stateMap(useDependencyEnumKey).set(targetEnum, state);
}
}
@ -437,29 +438,31 @@ export function getUseDependencies(
}
return undefined;
} else if (target.kind === "Enum") {
const data = program.stateMap(useDependencyEnumKey).get(target) as Map<EnumMember, Version>;
const data = program.stateMap(useDependencyEnumKey).get(target) as Map<EnumMember, Version[]>;
if (!data) {
return undefined;
}
const resolved = resolveVersionDependency(program, data);
if (resolved instanceof Map) {
for (const [enumVer, value] of resolved) {
const targetNamespace = value.enumMember.enum.namespace;
if (!targetNamespace) {
reportDiagnostic(program, {
code: "version-not-found",
target: value.enumMember.enum,
format: { version: value.enumMember.name, enumName: value.enumMember.enum.name },
});
return undefined;
for (const val of value) {
const targetNamespace = val.enumMember.enum.namespace;
if (!targetNamespace) {
reportDiagnostic(program, {
code: "version-not-found",
target: val.enumMember.enum,
format: { version: val.enumMember.name, enumName: val.enumMember.enum.name },
});
return undefined;
}
let subMap = result.get(targetNamespace) as Map<Version, Version>;
if (subMap) {
subMap.set(enumVer, val);
} else {
subMap = new Map([[enumVer, val]]);
}
result.set(targetNamespace, subMap);
}
let subMap = result.get(targetNamespace) as Map<Version, Version>;
if (subMap) {
subMap.set(enumVer, value);
} else {
subMap = new Map([[enumVer, value]]);
}
result.set(targetNamespace, subMap);
}
}
}
@ -580,12 +583,12 @@ export function getVersionDependencies(
function resolveVersionDependency(
program: Program,
data: Map<EnumMember, Version> | Version
): Map<Version, Version> | Version {
data: Map<EnumMember, Version[]> | Version[]
): Map<Version, Version[]> | Version[] {
if (!(data instanceof Map)) {
return data;
}
const mapping = new Map<Version, Version>();
const mapping = new Map<Version, Version[]>();
for (const [key, value] of data) {
const sourceVersion = getVersionForEnumMember(program, key);
if (sourceVersion !== undefined) {

Просмотреть файл

@ -1,4 +1,4 @@
import { Model, Namespace, Program, projectProgram } from "@cadl-lang/compiler";
import { Model, Namespace, Operation, Program, projectProgram } from "@cadl-lang/compiler";
import {
BasicTestRunner,
createTestWrapper,
@ -18,9 +18,7 @@ describe("versioning: reference versioned library", () => {
runner = createTestWrapper(host, {
wrapper: (code) => `
import "@cadl-lang/versioning";
using Cadl.Versioning;
@versioned(Versions)
namespace VersionedLib {
enum Versions {l1, l2}
@ -62,6 +60,35 @@ describe("versioning: reference versioned library", () => {
assertFooV1(Foo);
});
it("use multiple versioned libraries given version", async () => {
const { MyService, Test, getBar } = (await runner.compile(`
@versioned(Versions)
namespace OtherVersionedLib {
enum Versions {
m1,
}
model Bar {};
}
@useDependency(VersionedLib.Versions.l1, OtherVersionedLib.Versions.m1)
@test namespace MyService {
@test model Test extends VersionedLib.Foo {}
@test op getBar(): OtherVersionedLib.Bar;
}
`)) as { MyService: Namespace; Test: Model; getBar: Operation };
const versions = buildVersionProjections(runner.program, MyService);
strictEqual(versions.length, 1);
strictEqual(versions[0].version, undefined);
strictEqual(versions[0].projections.length, 1);
const projector = projectProgram(runner.program, versions[0].projections, Test).projector;
const Foo = (projector.projectedTypes.get(Test) as any).baseModel;
assertFooV1(Foo);
ok((getBar.returnType as Model).name === "Bar");
ok((getBar.returnType as Model).namespace?.name === "OtherVersionedLib");
});
it("emit diagnostic if passing anything but an enum member", async () => {
const diagnostics = await runner.diagnose(`
@useDependency([[VersionedLib.Versions.l1, VersionedLib.Versions.l1]])
@ -158,7 +185,6 @@ describe("versioning: reference versioned library", () => {
@useDependency(VersionedLib.Versions.l2)
v2,
}
@versioned(TestServiceVersions)
namespace TestService {
@added(TestServiceVersions.v2)
@ -220,7 +246,6 @@ describe("versioning: reference versioned library", () => {
foo: T;
}
}
@versioned(Versions)
namespace MyService {
enum Versions {v1, v2}
@ -228,7 +253,6 @@ describe("versioning: reference versioned library", () => {
model Bar {}
model Test extends NonVersioned.Foo<Bar> {}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -240,7 +264,6 @@ describe("versioning: reference versioned library", () => {
enum Versions {v1, v2}
model Foo {}
interface Test {
test(): Foo;
}
@ -256,10 +279,8 @@ describe("versioning: reference versioned library", () => {
enum Versions {v1, v2}
model Foo {}
interface Test extends NonVersioned.Foo<Foo> {}
}
namespace NonVersioned {
interface Foo<T> {
foo(): T | {};
@ -278,12 +299,10 @@ describe("versioning: reference versioned library", () => {
enum Versions {v1, v2}
model Foo {}
namespace SubNamespace {
op use(): Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -296,14 +315,12 @@ describe("versioning: reference versioned library", () => {
model Foo {}
}
@useDependency(Lib.Versions.v1)
namespace MyService {
namespace SubNamespace {
op use(): Lib.Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -316,7 +333,6 @@ describe("versioning: reference versioned library", () => {
model Foo {}
}
@versioned(Versions)
namespace MyService {
enum Versions {
@ -327,7 +343,6 @@ describe("versioning: reference versioned library", () => {
op use(): Lib.Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -337,13 +352,11 @@ describe("versioning: reference versioned library", () => {
@versioned(Versions)
namespace MyService {
enum Versions {m1}
op use(): SubNamespace.Foo;
namespace SubNamespace {
model Foo {}
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -353,12 +366,10 @@ describe("versioning: reference versioned library", () => {
@versioned(Versions)
namespace Lib {
enum Versions {v1, v2}
namespace LibSub {
model Foo {}
}
}
@versioned(Versions)
namespace MyService {
enum Versions {
@ -369,7 +380,6 @@ describe("versioning: reference versioned library", () => {
op use(): Lib.LibSub.Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -400,9 +410,7 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
runner = createTestWrapper(host, {
wrapper: (code) => `
import "@cadl-lang/versioning";
using Cadl.Versioning;
@versioned(Versions)
namespace VersionedLib {
enum Versions {l1, l2}
@ -538,12 +546,10 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
enum Versions {v1, v2}
model Foo {}
namespace SubNamespace {
op use(): Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -556,7 +562,6 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
model Foo {}
}
#suppress "deprecated"
@versionedDependency(Lib.Versions.v1)
namespace MyService {
@ -564,7 +569,6 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
op use(): Lib.Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -577,7 +581,6 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
model Foo {}
}
#suppress "deprecated"
@versioned(Versions)
@versionedDependency([[Versions.m1, Lib.Versions.v1]])
@ -587,7 +590,6 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
op use(): Lib.Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -597,13 +599,11 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
@versioned(Versions)
namespace MyService {
enum Versions {m1}
op use(): SubNamespace.Foo;
namespace SubNamespace {
model Foo {}
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -613,12 +613,10 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
@versioned(Versions)
namespace Lib {
enum Versions {v1, v2}
namespace LibSub {
model Foo {}
}
}
#suppress "deprecated"
@versioned(Versions)
@versionedDependency([[Versions.m1, Lib.Versions.v1]])
@ -628,7 +626,6 @@ describe("versioning (deprecated): reference versioned library (@versionedDepend
op use(): Lib.LibSub.Foo;
}
}
`);
expectDiagnosticEmpty(diagnostics);
});
@ -668,13 +665,11 @@ describe("versioning (deprecated): dependencies (@versionedDependency)", () => {
...T;
}
}
#suppress "deprecated"
@versioned(Versions)
@versionedDependency([[Versions.v1, VersionedLib.Versions.l1], [Versions.v2, VersionedLib.Versions.l2]])
@test namespace MyService {
enum Versions {v1, v2}
model Spreadable {
a: int32;
@added(Versions.v2) b: int32;
@ -701,13 +696,11 @@ describe("versioning (deprecated): dependencies (@versionedDependency)", () => {
...T;
}
}
#suppress "deprecated"
@versioned(Versions)
@versionedDependency([[Versions.v1, VersionedLib.Versions.v1], [Versions.v2, VersionedLib.Versions.v2]])
@test namespace MyService {
enum Versions {v1, v2}
model Spreadable {
a: int32;
@added(Versions.v2) b: int32;
@ -732,9 +725,7 @@ describe("versioning (deprecated): dependencies (@versionedDependency)", () => {
@versionedDependency(Lib.Versions.v1)
@test("MyService")
namespace MyOrg.MyService {
}
@versioned(Versions)
namespace Lib {
enum Versions {
@ -755,9 +746,7 @@ describe("versioning (deprecated): dependencies (@versionedDependency)", () => {
@versionedDependency(Lib.One.Versions.v1)
@test("MyService")
namespace MyOrg.MyService {
}
@versioned(Versions)
namespace Lib.One {
enum Versions { v1: "v1" }
@ -766,7 +755,6 @@ describe("versioning (deprecated): dependencies (@versionedDependency)", () => {
#suppress "deprecated"
@versionedDependency(Lib.One.Versions.v1)
namespace Lib.Two { }
`)) as { MyService: Namespace };
const [v1] = runProjections(runner.program, MyService);
@ -790,11 +778,9 @@ describe("versioning: dependencies", () => {
...T;
}
}
@versioned(Versions)
@test namespace MyService {
enum Versions {v1, v2}
model Spreadable {
a: int32;
@added(Versions.v2) b: int32;
@ -821,7 +807,6 @@ describe("versioning: dependencies", () => {
...T;
}
}
@versioned(Versions)
@test namespace MyService {
enum Versions {
@ -830,7 +815,6 @@ describe("versioning: dependencies", () => {
@useDependency(VersionedLib.Versions.l2)
v2
}
model Spreadable {
a: int32;
@added(Versions.v2) b: int32;
@ -857,7 +841,6 @@ describe("versioning: dependencies", () => {
...T;
}
}
@versioned(Versions)
@test namespace MyService {
enum Versions {
@ -866,7 +849,6 @@ describe("versioning: dependencies", () => {
@useDependency(VersionedLib.Versions.v2)
v2
}
model Spreadable {
a: int32;
@added(Versions.v2) b: int32;
@ -890,9 +872,7 @@ describe("versioning: dependencies", () => {
@useDependency(Lib.Versions.v1)
@test("MyService")
namespace MyOrg.MyService {
}
@versioned(Versions)
namespace Lib {
enum Versions {
@ -912,9 +892,7 @@ describe("versioning: dependencies", () => {
@useDependency(Lib.One.Versions.v1)
@test("MyService")
namespace MyOrg.MyService {
}
@versioned(Versions)
namespace Lib.One {
enum Versions { v1: "v1" }
@ -922,7 +900,6 @@ describe("versioning: dependencies", () => {
@useDependency(Lib.One.Versions.v1)
namespace Lib.Two { }
`)) as { MyService: Namespace };
const [v1] = runProjections(runner.program, MyService);