Converting Existing Specs with Multiple Previews
Converting a spec with multiple preview versions into a spec with a single, latest preview version is complex because the changes that occur in any preview version are carried over into the next version by default. This means that each versioning decorator referencing a preview version must be dealt with in order to end with the correct decoration.
For each type decorated with a versioning decorator that references a preview version, follow these steps. If the type is decorated with more than one instance of a versioning decorator referencing different preview versions, each of these must be processed in version order (earliest version first)
A conversion consists of the following steps, outlined in the sections below
- Normalizing version decoration (optional)
- Determining which versions should be removed: this should include all preview api-versions except the last version (if the last version is a preview, that version will not be removed.)
- Handling each versioning decorator application that references a deleted preview version (except the first version)
- Removing the first version (if it is a preview)
- Removing the deleted preview versions from the Versions enum
- If there is a remaining preview version, it should be the last version in the versions enum. Ensure it is decorated with the
@previewVersiondecorator. - Cleaning up (optional)
In this document we use the notation @<decorator>(T, u, [arg]) this indicates an instance of the decorator <decorator> decorating type T using version u in a set of monotonically increasing versions 1..n
Normalizing Version Decoration (optional)
Section titled “Normalizing Version Decoration (optional)”Normalizing version decoration consists of removing redundant decorators and follows a few rules, described below. For these rules, consider an ordered set of versions 1...n.
- Trim any sequence of
@removeddecorators without an@addedbetween them: A decorator@removed(T, c)with typeTandcin1..nmay be safely removed if there is another decorator@removed(T, a)withain1..nanda < cunless there is a decorator@added(T, b)withbin1..nanda < b < c. - Trim any sequence of
@addeddecorators without any@removedbetween them: A decorator@added(T, c)with typeTandcin1..nmay be safely removed if there is another decorator@added(T,a)withain1..nanda < cunless there is a decorator@removed(T,b)withbin1..nanda < b < c. - Any duplicated application of a versioning decorator to a type with the same parameters may be safely removed, that is:
@added(T, a)and@added(T, a)can be simplified to@added(T, a)@removed(T, a)and@removed(T, a)can be simplified to@removed(T, a)@madeOptional(T, a)and@madeOptional(T, a)can be simplified to@madeOptional(T, a)@renamedFrom(T, a, name)and@renamedFrom(T, a, name)can be simplified to@renamedFrom(T, a, name)@typeChangedFrom(T, a, U)and@typeChangedFrom(T, a, U)can be simplified to@typeChangedFrom(T, a, U)@returnTypeChangedFrom(T, a, U)and@returnTypeChangedFrom(T, a, U)can be simplified to@returnTypeChangedFrom(T, a, U)
- If
@added(T, a)and@removed(T,a)occur,@added(T, a)may be removed. - If any versioning decorator with 3 arguments
@dec(T, v, a)whereTis a type,vis a version andais a valid arg value occurs with another application of the same decorator@dec(T, v, b)andb != a, then the innermost of the two decorators can be removed. - If any of the following decorators reference the first version, they may be removed:
@added@renamedFrom@madeOptional@typeChangedFrom@returnTypeChangedFrom
- if
@removed(T, 1)occurs, whereTis the decorated type and1is the first version:- If
Toccurs in any subsequent version (i.e. if there is any), this decorator should remain - Otherwise, the decorated type can simply be removed.
- If
Handling Each Versioning Decorator That References a Preview Version
Section titled “Handling Each Versioning Decorator That References a Preview Version”@renamedFrom(T, u, name) decorator
Section titled “@renamedFrom(T, u, name) decorator”- Based on the version referenced in the decorator, determine the immediate successor version
u + 1 - If version
u + 1does not exist (the version argument is the last version) then this version will not be deleted - If there is one or more
@renamedFrom(T, u + 1, anotherName)decorators, remove them. - Change
@renamedFrom(T, u, name)to@renamedFrom(T, u + 1, name)
@typeChangedFrom(T, u, type) decorator
Section titled “@typeChangedFrom(T, u, type) decorator”- Based on the version referenced in the decorator, determine the immediate successor version
u + 1 - If version
u + 1does not exist (the version argument is the last version) then this version will not be deleted - If there is one or more
@typeChangedFromdecorators referencing the immediate successor version, remove them. - Change
@typeChangedFrom(T, u, type)to@typeChangedFrom(T, u + 1, type)
@returnTypeChangedFrom(T, u, returnType) decorator
Section titled “@returnTypeChangedFrom(T, u, returnType) decorator”- Based on the version referenced in the decorator, determine the immediate successor version
u + 1 - If version
u + 1does not exist (the version argument is the last version) then this version will not be deleted - If there is one or more
@returnTypeChangedFromdecorators referencing the immediate successor version, remove them. - Change
@returnTypeChangedFrom(T, u, returnType)to@returnTypeChangedFrom(T, u + 1, returnType)
@madeOptional(T, u) decorator
Section titled “@madeOptional(T, u) decorator”- Based on the version referenced in the decorator, determine the immediate successor version
u + 1 - If version
u + 1does not exist (the version argument is the last version) then this version will not be deleted - If there is one or more
@madeOptionaldecorators referencing the immediate successor version, remove them. - Change
@madeOption(T, u)to@madeOptional(T, u + 1)
@added(T, u) decorator
Section titled “@added(T, u) decorator”- Based on the version referenced in the decorator, determine the immediate successor version
u + 1 - If version
u + 1does not exist (the version argument is the last version) then this version will not be deleted - If there is one or more
@added(T, u + 1)decorators referencing the immediate successor version- Remove them.
- Change the version argument in the decorator to match the successor version [
@added(T, u) -> @added(T, u + 1)]
- If there is an
@removed(T, u + 1)decorator referencing the immediate successor version- If the type does not occur in any previous version
v < u, delete the type altogether - If the type does occur in a previous version, remove the
@added(T, u)decorator.
- If the type does not occur in any previous version
- If there are no
@added(T, u + 1)or@removed(T, u + 1)decorators referencing the immediate successor version, change the version in the decorator to the immediate successor version: [@added(T, u)->@added(T, u + 1)]
@removed(T, u) decorator
Section titled “@removed(T, u) decorator”- Based on the version referenced in the decorator, determine the immediate successor version
u + 1 - If version
u + 1does not exist (the version argument is the last version) then this version will not be deleted - If there is one or more
@removed(T, u + 1)decorators referencing the immediate successor version- Remove them.
- Change the version argument in the decorator to match the successor version [
@removed(T, u) -> @removed(T, u + 1)]
- if there is one or more
@added(T, u + 1)decorators in the immediate successor version- Remove the
@removed(T, u)decorator
- Remove the
- If there are no
@removed(T, u + 1)or@removed(T, u + 1)decorators referencing the immediate successor version, change the version in the decorator to the immediate successor version: [@removed(T, u)->@removed(T, u + 1)]
Removing the First version in the Specification
Section titled “Removing the First version in the Specification”TypeSpec specs require no versioning decoration for the first version of a spec, and all versioning decorators except @removed have no impact on the type graph for subsequent versions and can be safely removed. Any @removed decorator referencing the first version should be treated as follows:
- If the decorated type does not occur in any subsequent versions, it can be removed
- If the decorated type does occur in subsequent versions, the version referenced in the
@removeddecorator should be updated to its immediate successor
Note that the last version of a specification should never be removed in a conversion, as if the last version is a preview, it will become the active preview.
Cleaning Up (optional)
Section titled “Cleaning Up (optional)”After removing the preview versions, repeat the steps to normalize version decoration to remove redundant decoration.