Skip to content

Commit

Permalink
Update targets for Versioning decorators (#2580)
Browse files Browse the repository at this point in the history
Fix #2497.

Clarifies which TypeSpec types these decorators can _actually_ be used
on by-design.

**BREAKING CHANGE** This is a breaking change because if unsupported
elements were previously decorated with these (i.e. Namespaces) those
will now throw an error.
  • Loading branch information
tjprescott authored Oct 18, 2023
1 parent 7d10458 commit af5ad70
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/versioning",
"comment": "Update targets for `@added`, `@removed`, `@renamedFrom`, `@madeOptional` and `@typeChangedFrom` to more clearly communicate where they can be used.",
"type": "none"
}
],
"packageName": "@typespec/versioning"
}
10 changes: 5 additions & 5 deletions docs/standard-library/versioning/reference/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Identifies when the target was added.

#### Target

`(intrinsic) unknown`
`union Model | ModelProperty | Operation | Enum | EnumMember | Union | UnionVariant | Scalar | Interface`

#### Parameters

Expand Down Expand Up @@ -53,7 +53,7 @@ Identifies when a target was made optional.

#### Target

`(intrinsic) unknown`
`ModelProperty`

#### Parameters

Expand Down Expand Up @@ -82,7 +82,7 @@ Identifies when the target was removed.

#### Target

`(intrinsic) unknown`
`union Model | ModelProperty | Operation | Enum | EnumMember | Union | UnionVariant | Scalar | Interface`

#### Parameters

Expand Down Expand Up @@ -117,7 +117,7 @@ Identifies when the target has been renamed.

#### Target

`(intrinsic) unknown`
`union Model | ModelProperty | Operation | Enum | EnumMember | Union | UnionVariant | Scalar | Interface`

#### Parameters

Expand Down Expand Up @@ -162,7 +162,7 @@ Identifies when the target type changed.

#### Target

`(intrinsic) unknown`
`ModelProperty`

#### Parameters

Expand Down
10 changes: 5 additions & 5 deletions packages/versioning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Identifies when the target was added.

##### Target

`(intrinsic) unknown`
`union Model | ModelProperty | Operation | Enum | EnumMember | Union | UnionVariant | Scalar | Interface`

##### Parameters

Expand Down Expand Up @@ -102,7 +102,7 @@ Identifies when a target was made optional.

##### Target

`(intrinsic) unknown`
`ModelProperty`

##### Parameters

Expand Down Expand Up @@ -131,7 +131,7 @@ Identifies when the target was removed.

##### Target

`(intrinsic) unknown`
`union Model | ModelProperty | Operation | Enum | EnumMember | Union | UnionVariant | Scalar | Interface`

##### Parameters

Expand Down Expand Up @@ -166,7 +166,7 @@ Identifies when the target has been renamed.

##### Target

`(intrinsic) unknown`
`union Model | ModelProperty | Operation | Enum | EnumMember | Union | UnionVariant | Scalar | Interface`

##### Parameters

Expand Down Expand Up @@ -211,7 +211,7 @@ Identifies when the target type changed.

##### Target

`(intrinsic) unknown`
`ModelProperty`

##### Parameters

Expand Down
47 changes: 42 additions & 5 deletions packages/versioning/lib/decorators.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,19 @@ namespace TypeSpec {
* }
* ```
*/
extern dec added(target: unknown, version: EnumMember);
extern dec added(
target:
| Model
| ModelProperty
| Operation
| Enum
| EnumMember
| Union
| UnionVariant
| Scalar
| Interface,
version: EnumMember
);

/**
* Identifies when the target was removed.
Expand All @@ -93,7 +105,19 @@ namespace TypeSpec {
* }
* ```
*/
extern dec removed(target: unknown, version: EnumMember);
extern dec removed(
target:
| Model
| ModelProperty
| Operation
| Enum
| EnumMember
| Union
| UnionVariant
| Scalar
| Interface,
version: EnumMember
);

/**
* Identifies when the target has been renamed.
Expand All @@ -106,7 +130,20 @@ namespace TypeSpec {
* op newName(): void;
* ```
*/
extern dec renamedFrom(target: unknown, version: EnumMember, oldName: valueof string);
extern dec renamedFrom(
target:
| Model
| ModelProperty
| Operation
| Enum
| EnumMember
| Union
| UnionVariant
| Scalar
| Interface,
version: EnumMember,
oldName: valueof string
);

/**
* Identifies when a target was made optional.
Expand All @@ -122,14 +159,14 @@ namespace TypeSpec {
* }
* ```
*/
extern dec madeOptional(target: unknown, version: EnumMember);
extern dec madeOptional(target: ModelProperty, version: EnumMember);

/**
* Identifies when the target type changed.
* @param version The version that the target type changed in.
* @param oldType The previous type of the target.
*/
extern dec typeChangedFrom(target: unknown, version: EnumMember, oldType: unknown);
extern dec typeChangedFrom(target: ModelProperty, version: EnumMember, oldType: unknown);

/**
* Identifies when the target type changed.
Expand Down
65 changes: 55 additions & 10 deletions packages/versioning/src/versioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import {
Enum,
EnumMember,
getNamespaceFullName,
Model,
ModelProperty,
Namespace,
ObjectType,
Operation,
Program,
ProjectionApplication,
Scalar,
Type,
Union,
UnionVariant,
} from "@typespec/compiler";
import { Interface } from "readline";
import { createStateSymbol, reportDiagnostic } from "./lib.js";
import { Version, VersionResolution } from "./types.js";
import { TimelineMoment, VersioningTimeline } from "./versioning-timeline.js";
Expand Down Expand Up @@ -46,7 +51,20 @@ function checkIsVersion(
return version;
}

export function $added(context: DecoratorContext, t: Type, v: EnumMember) {
export function $added(
context: DecoratorContext,
t:
| Model
| ModelProperty
| Operation
| Enum
| EnumMember
| Union
| UnionVariant
| Scalar
| Interface,
v: EnumMember
) {
const { program } = context;

const version = checkIsVersion(context.program, v, context.getArgumentTarget(0)!);
Expand All @@ -55,15 +73,28 @@ export function $added(context: DecoratorContext, t: Type, v: EnumMember) {
}

// retrieve statemap to update or create a new one
const record = program.stateMap(addedOnKey).get(t) ?? new Array<Version>();
const record = program.stateMap(addedOnKey).get(t as Type) ?? new Array<Version>();
record.push(version);
// ensure that records are stored in ascending order
(record as Version[]).sort((a, b) => a.index - b.index);

program.stateMap(addedOnKey).set(t, record);
program.stateMap(addedOnKey).set(t as Type, record);
}

export function $removed(context: DecoratorContext, t: Type, v: EnumMember) {
export function $removed(
context: DecoratorContext,
t:
| Model
| ModelProperty
| Operation
| Enum
| EnumMember
| Union
| UnionVariant
| Scalar
| Interface,
v: EnumMember
) {
const { program } = context;

const version = checkIsVersion(context.program, v, context.getArgumentTarget(0)!);
Expand All @@ -72,12 +103,12 @@ export function $removed(context: DecoratorContext, t: Type, v: EnumMember) {
}

// retrieve statemap to update or create a new one
const record = program.stateMap(removedOnKey).get(t) ?? new Array<Version>();
const record = program.stateMap(removedOnKey).get(t as Type) ?? new Array<Version>();
record.push(version);
// ensure that records are stored in ascending order
(record as Version[]).sort((a, b) => a.index - b.index);

program.stateMap(removedOnKey).set(t, record);
program.stateMap(removedOnKey).set(t as Type, record);
}

/**
Expand Down Expand Up @@ -147,7 +178,21 @@ interface RenamedFrom {
oldName: string;
}

export function $renamedFrom(context: DecoratorContext, t: Type, v: EnumMember, oldName: string) {
export function $renamedFrom(
context: DecoratorContext,
t:
| Model
| ModelProperty
| Operation
| Enum
| EnumMember
| Union
| UnionVariant
| Scalar
| Interface,
v: EnumMember,
oldName: string
) {
const { program } = context;
const version = checkIsVersion(context.program, v, context.getArgumentTarget(0)!);
if (!version) {
Expand All @@ -157,17 +202,17 @@ export function $renamedFrom(context: DecoratorContext, t: Type, v: EnumMember,
if (oldName === "") {
reportDiagnostic(program, {
code: "invalid-renamed-from-value",
target: t,
target: t as Type,
});
}

// retrieve statemap to update or create a new one
const record = getRenamedFrom(program, t) ?? [];
const record = getRenamedFrom(program, t as Type) ?? [];
record.push({ version: version, oldName: oldName });
// ensure that records are stored in ascending order
record.sort((a, b) => a.version.index - b.version.index);

program.stateMap(renamedFromKey).set(t, record);
program.stateMap(renamedFromKey).set(t as Type, record);
}

export function $madeOptional(context: DecoratorContext, t: ModelProperty, v: EnumMember) {
Expand Down

0 comments on commit af5ad70

Please sign in to comment.