WIP: Each type has an optional attached transformation
This commit is contained in:
Родитель
fb2375ba17
Коммит
48b63c5893
|
@ -115,7 +115,7 @@ export function findSimilarityCliques(
|
|||
): ClassType[][] {
|
||||
let unprocessedClasses = graph
|
||||
.allNamedTypesSeparated()
|
||||
.objects.filter(o => o instanceof ClassType && (includeFixedClasses || !o.isFixed))
|
||||
.objects.filter(o => o instanceof ClassType && o.transformation === undefined && (includeFixedClasses || !o.isFixed))
|
||||
.toArray() as ClassType[];
|
||||
const cliques: ClassType[][] = [];
|
||||
|
||||
|
|
|
@ -448,7 +448,7 @@ export abstract class ConvenienceRenderer extends Renderer {
|
|||
.sortBy((_, n) => defined(names.get(defined(propertyNameds.get(n)))));
|
||||
return sortedMap.toOrderedSet();
|
||||
}
|
||||
return t.children.toOrderedSet();
|
||||
return t.getChildren();
|
||||
};
|
||||
|
||||
protected get namedUnions(): OrderedSet<UnionType> {
|
||||
|
@ -524,7 +524,6 @@ export abstract class ConvenienceRenderer extends Renderer {
|
|||
},
|
||||
_enumType => "enum",
|
||||
_unionType => "union",
|
||||
transformedType => typeNameForUnionMember(transformedType.targetType),
|
||||
_dateType => "date",
|
||||
_timeType => "time",
|
||||
_dateTimeType => "date_time"
|
||||
|
@ -898,7 +897,7 @@ export abstract class ConvenienceRenderer extends Renderer {
|
|||
|
||||
function visit(t: Type) {
|
||||
if (visitedTypes.has(t)) return;
|
||||
queue.push(...t.children.toArray());
|
||||
queue.push(...t.getChildren().toArray());
|
||||
visitedTypes = visitedTypes.add(t);
|
||||
processed = processed.add(process(t));
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ export function cycleBreakerTypesForGraph(
|
|||
if (visitedTypes.has(t)) return;
|
||||
|
||||
if (isImplicitCycleBreaker(t)) {
|
||||
queue.push(...t.children.toArray());
|
||||
queue.push(...t.getChildren().toArray());
|
||||
} else {
|
||||
const maybeBreaker = findBreaker(t, path, canBreakCycles);
|
||||
if (maybeBreaker !== undefined) {
|
||||
|
@ -63,7 +63,7 @@ export function cycleBreakerTypesForGraph(
|
|||
}
|
||||
|
||||
const pathForChildren = path.unshift(t);
|
||||
t.children.forEach(c => visit(c, pathForChildren));
|
||||
t.getChildren().forEach(c => visit(c, pathForChildren));
|
||||
}
|
||||
|
||||
visitedTypes = visitedTypes.add(t);
|
||||
|
|
|
@ -130,11 +130,11 @@ export function gatherNames(graph: TypeGraph, debugPrint: boolean): void {
|
|||
members.forEach(memberType => {
|
||||
addNames(memberType, names);
|
||||
});
|
||||
},
|
||||
transformedType => {
|
||||
addNames(transformedType.targetType, names);
|
||||
}
|
||||
);
|
||||
if (t.transformation !== undefined) {
|
||||
addNames(t.transformation.targetType, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,11 +245,11 @@ export function gatherNames(graph: TypeGraph, debugPrint: boolean): void {
|
|||
const unionIsAncestor = unionHasGivenName || nullableFromUnion(unionType) === null;
|
||||
const ancestorForMembers = unionIsAncestor ? unionType : ancestor;
|
||||
members.forEach(memberType => processType(ancestorForMembers, memberType, undefined));
|
||||
},
|
||||
transformedType => {
|
||||
processType(ancestor, transformedType.targetType, alternativeSuffix);
|
||||
}
|
||||
);
|
||||
if (t.transformation !== undefined) {
|
||||
processType(ancestor, t.transformation.targetType, alternativeSuffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { Map, OrderedMap, OrderedSet, Set, Collection, isCollection } from "immutable";
|
||||
|
||||
import { PrimitiveTypeKind, Type, ClassProperty, Transformer } from "./Type";
|
||||
import { PrimitiveTypeKind, Type, ClassProperty, Transformation } from "./Type";
|
||||
import { combineTypeAttributesOfTypes } from "./TypeUtils";
|
||||
import { TypeGraph } from "./TypeGraph";
|
||||
import { TypeAttributes } from "./TypeAttributes";
|
||||
|
@ -78,44 +78,57 @@ export class TypeReconstituter<TBuilder extends BaseGraphRewriteBuilder> {
|
|||
return this._typeBuilder.reconstituteTypeRef(trefs);
|
||||
}
|
||||
|
||||
getPrimitiveType(kind: PrimitiveTypeKind): void {
|
||||
this.registerAndAddAttributes(this.builderForNewType().getPrimitiveType(kind, this._forwardingRef));
|
||||
getPrimitiveType(kind: PrimitiveTypeKind, transformation: Transformation | undefined): void {
|
||||
this.registerAndAddAttributes(
|
||||
this.builderForNewType().getPrimitiveType(kind, transformation, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
getStringType(enumCases: OrderedMap<string, number> | undefined): void {
|
||||
this.register(this.builderForNewType().getStringType(this._typeAttributes, enumCases, this._forwardingRef));
|
||||
getStringType(enumCases: OrderedMap<string, number> | undefined, transformation: Transformation | undefined): void {
|
||||
this.register(
|
||||
this.builderForNewType().getStringType(this._typeAttributes, enumCases, transformation, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
getEnumType(cases: OrderedSet<string>): void {
|
||||
this.register(this.builderForNewType().getEnumType(this._typeAttributes, cases, this._forwardingRef));
|
||||
getEnumType(cases: OrderedSet<string>, transformation: Transformation | undefined): void {
|
||||
this.register(
|
||||
this.builderForNewType().getEnumType(this._typeAttributes, cases, transformation, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
getUniqueMapType(): void {
|
||||
this.registerAndAddAttributes(this.builderForNewType().getUniqueMapType(this._forwardingRef));
|
||||
}
|
||||
|
||||
getMapType(values: TypeRef): void {
|
||||
this.registerAndAddAttributes(this.builderForNewType().getMapType(values, this._forwardingRef));
|
||||
getMapType(values: TypeRef, transformation: Transformation | undefined): void {
|
||||
this.registerAndAddAttributes(this.builderForNewType().getMapType(values, transformation, this._forwardingRef));
|
||||
}
|
||||
|
||||
getUniqueArrayType(): void {
|
||||
this.registerAndAddAttributes(this.builderForNewType().getUniqueArrayType(this._forwardingRef));
|
||||
}
|
||||
|
||||
getArrayType(items: TypeRef): void {
|
||||
this.registerAndAddAttributes(this.builderForNewType().getArrayType(items, this._forwardingRef));
|
||||
getArrayType(items: TypeRef, transformation: Transformation | undefined): void {
|
||||
this.registerAndAddAttributes(
|
||||
this.builderForNewType().getArrayType(items, transformation, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
setArrayItems(items: TypeRef): void {
|
||||
this.builderForSetting().setArrayItems(this.getResult(), items);
|
||||
setArrayItems(items: TypeRef, transformation: Transformation | undefined): void {
|
||||
this.builderForSetting().setArrayItems(this.getResult(), items, transformation);
|
||||
}
|
||||
|
||||
getObjectType(properties: OrderedMap<string, ClassProperty>, additionalProperties: TypeRef | undefined): void {
|
||||
getObjectType(
|
||||
properties: OrderedMap<string, ClassProperty>,
|
||||
additionalProperties: TypeRef | undefined,
|
||||
transformation: Transformation | undefined
|
||||
): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueObjectType(
|
||||
this._typeAttributes,
|
||||
properties,
|
||||
additionalProperties,
|
||||
transformation,
|
||||
this._forwardingRef
|
||||
)
|
||||
);
|
||||
|
@ -123,83 +136,98 @@ export class TypeReconstituter<TBuilder extends BaseGraphRewriteBuilder> {
|
|||
|
||||
getUniqueObjectType(
|
||||
properties: OrderedMap<string, ClassProperty> | undefined,
|
||||
additionalProperties: TypeRef | undefined
|
||||
additionalProperties: TypeRef | undefined,
|
||||
transformation: Transformation | undefined
|
||||
): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueObjectType(
|
||||
this._typeAttributes,
|
||||
properties,
|
||||
additionalProperties,
|
||||
transformation,
|
||||
this._forwardingRef
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getClassType(properties: OrderedMap<string, ClassProperty>): void {
|
||||
getClassType(properties: OrderedMap<string, ClassProperty>, transformation: Transformation | undefined): void {
|
||||
if (this._makeClassUnique) {
|
||||
this.getUniqueClassType(false, properties);
|
||||
this.getUniqueClassType(false, properties, transformation);
|
||||
return;
|
||||
}
|
||||
this.register(this.builderForNewType().getClassType(this._typeAttributes, properties, this._forwardingRef));
|
||||
this.register(this.builderForNewType().getClassType(this._typeAttributes, properties, transformation, this._forwardingRef));
|
||||
}
|
||||
|
||||
getUniqueClassType(isFixed: boolean, properties: OrderedMap<string, ClassProperty> | undefined): void {
|
||||
getUniqueClassType(
|
||||
isFixed: boolean,
|
||||
properties: OrderedMap<string, ClassProperty> | undefined,
|
||||
transformation: Transformation | undefined
|
||||
): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueClassType(this._typeAttributes, isFixed, properties, this._forwardingRef)
|
||||
this.builderForNewType().getUniqueClassType(
|
||||
this._typeAttributes,
|
||||
isFixed,
|
||||
properties,
|
||||
transformation,
|
||||
this._forwardingRef
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setObjectProperties(
|
||||
properties: OrderedMap<string, ClassProperty>,
|
||||
additionalProperties: TypeRef | undefined
|
||||
additionalProperties: TypeRef | undefined,
|
||||
transformation: Transformation | undefined
|
||||
): void {
|
||||
this.builderForSetting().setObjectProperties(this.getResult(), properties, additionalProperties);
|
||||
this.builderForSetting().setObjectProperties(
|
||||
this.getResult(),
|
||||
properties,
|
||||
additionalProperties,
|
||||
transformation
|
||||
);
|
||||
}
|
||||
|
||||
getUnionType(members: OrderedSet<TypeRef>): void {
|
||||
this.register(this.builderForNewType().getUnionType(this._typeAttributes, members, this._forwardingRef));
|
||||
getUnionType(members: OrderedSet<TypeRef>, transformation: Transformation | undefined): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUnionType(this._typeAttributes, members, transformation, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
getUniqueUnionType(): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueUnionType(this._typeAttributes, undefined, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
getIntersectionType(members: OrderedSet<TypeRef>): void {
|
||||
this.register(this.builderForNewType().getIntersectionType(this._typeAttributes, members, this._forwardingRef));
|
||||
}
|
||||
|
||||
getUniqueIntersectionType(members?: OrderedSet<TypeRef>): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueIntersectionType(this._typeAttributes, members, this._forwardingRef)
|
||||
);
|
||||
}
|
||||
|
||||
setSetOperationMembers(members: OrderedSet<TypeRef>): void {
|
||||
this.builderForSetting().setSetOperationMembers(this.getResult(), members);
|
||||
}
|
||||
|
||||
getTransformedType(transformer: Transformer, sourceRef: TypeRef, targetRef: TypeRef): void {
|
||||
this.register(
|
||||
this.builderForNewType().getTransformedType(
|
||||
this.builderForNewType().getUniqueUnionType(
|
||||
this._typeAttributes,
|
||||
transformer,
|
||||
sourceRef,
|
||||
targetRef,
|
||||
undefined,
|
||||
undefined,
|
||||
this._forwardingRef
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getUniqueTransformedType(transformer: Transformer): void {
|
||||
getIntersectionType(members: OrderedSet<TypeRef>, transformation: Transformation | undefined): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueTransformedType(this._typeAttributes, transformer, this._forwardingRef)
|
||||
this.builderForNewType().getIntersectionType(
|
||||
this._typeAttributes,
|
||||
members,
|
||||
transformation,
|
||||
this._forwardingRef
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setTransformedTypeTypes(sourceRef: TypeRef, targetRef: TypeRef): void {
|
||||
this.builderForSetting().setTransformedTypeTypes(this.getResult(), sourceRef, targetRef);
|
||||
getUniqueIntersectionType(): void {
|
||||
this.register(
|
||||
this.builderForNewType().getUniqueIntersectionType(
|
||||
this._typeAttributes,
|
||||
undefined,
|
||||
undefined,
|
||||
this._forwardingRef
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setSetOperationMembers(members: OrderedSet<TypeRef>, transformation: Transformation | undefined): void {
|
||||
this.builderForSetting().setSetOperationMembers(this.getResult(), members, transformation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,15 +34,15 @@ function replaceString(
|
|||
const attributes = t.getAttributes();
|
||||
const maybeEnumCases = shouldBeEnum(t);
|
||||
if (maybeEnumCases !== undefined) {
|
||||
return builder.getEnumType(attributes, maybeEnumCases.keySeq().toOrderedSet(), forwardingRef);
|
||||
return builder.getEnumType(attributes, maybeEnumCases.keySeq().toOrderedSet(), undefined, forwardingRef);
|
||||
}
|
||||
return builder.getStringType(attributes, undefined, forwardingRef);
|
||||
return builder.getStringType(attributes, undefined, undefined, forwardingRef);
|
||||
}
|
||||
|
||||
// A union needs replacing if it contains more than one string type, one of them being
|
||||
// a basic string type.
|
||||
function unionNeedsReplacing(u: UnionType): OrderedSet<Type> | undefined {
|
||||
const stringMembers = u.stringTypeMembers;
|
||||
const stringMembers = u.stringTypeMembers.filter(t => t.transformation === undefined);
|
||||
if (stringMembers.size <= 1) return undefined;
|
||||
if (u.findMember("string") === undefined) return undefined;
|
||||
return stringMembers;
|
||||
|
@ -63,11 +63,12 @@ function replaceUnion(group: Set<UnionType>, builder: GraphRewriteBuilder<UnionT
|
|||
return builder.getStringType(
|
||||
combineTypeAttributes(stringAttributes, u.getAttributes()),
|
||||
undefined,
|
||||
undefined,
|
||||
forwardingRef
|
||||
);
|
||||
}
|
||||
types.push(builder.getStringType(stringAttributes, undefined));
|
||||
return builder.getUnionType(u.getAttributes(), OrderedSet(types), forwardingRef);
|
||||
return builder.getUnionType(u.getAttributes(), OrderedSet(types), undefined, forwardingRef);
|
||||
}
|
||||
|
||||
export function inferEnums(
|
||||
|
@ -77,7 +78,7 @@ export function inferEnums(
|
|||
): TypeGraph {
|
||||
const allStrings = graph
|
||||
.allTypesUnordered()
|
||||
.filter(t => t instanceof StringType)
|
||||
.filter(t => t instanceof StringType && t.transformation === undefined)
|
||||
.map(t => [t])
|
||||
.toArray() as StringType[][];
|
||||
return graph.rewrite("infer enums", stringTypeMapping, false, allStrings, debugPrintReconstitution, replaceString);
|
||||
|
|
|
@ -121,6 +121,7 @@ export function inferMaps(
|
|||
unionBuilderForUnification(builder, false, false, false, conflateNumbers),
|
||||
conflateNumbers
|
||||
),
|
||||
undefined,
|
||||
forwardingRef
|
||||
);
|
||||
builder.addAttributes(tref, c.getAttributes());
|
||||
|
@ -131,7 +132,7 @@ export function inferMaps(
|
|||
ClassType
|
||||
>;
|
||||
const classesToReplace = allClasses
|
||||
.filter(c => !c.isFixed && shouldBeMap(c.getProperties()) !== undefined)
|
||||
.filter(c => c.transformation === undefined && !c.isFixed && shouldBeMap(c.getProperties()) !== undefined)
|
||||
.toArray();
|
||||
return graph.rewrite(
|
||||
"infer maps",
|
||||
|
|
|
@ -49,7 +49,7 @@ class InferenceUnionBuilder extends UnionBuilder<TypeBuilder, NestedValueArray,
|
|||
forwardingRef: TypeRef | undefined
|
||||
): TypeRef {
|
||||
const caseMap = OrderedMap(cases.map((c: string): [string, number] => [c, counts[c]]));
|
||||
return this.typeBuilder.getStringType(typeAttributes, caseMap, forwardingRef);
|
||||
return this.typeBuilder.getStringType(typeAttributes, caseMap, undefined, forwardingRef);
|
||||
}
|
||||
|
||||
protected makeObject(
|
||||
|
@ -179,9 +179,9 @@ export class TypeInference {
|
|||
|
||||
const propertyMap = OrderedMap(properties);
|
||||
if (fixed) {
|
||||
return this._typeBuilder.getUniqueClassType(typeAttributes, true, propertyMap, forwardingRef);
|
||||
return this._typeBuilder.getUniqueClassType(typeAttributes, true, propertyMap, undefined, forwardingRef);
|
||||
} else {
|
||||
return this._typeBuilder.getClassType(typeAttributes, propertyMap, forwardingRef);
|
||||
return this._typeBuilder.getClassType(typeAttributes, propertyMap, undefined, forwardingRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,6 @@ export class JSONSchemaRenderer extends ConvenienceRenderer {
|
|||
return this.definitionForUnion(unionType);
|
||||
}
|
||||
},
|
||||
transformedType => this.schemaForType(transformedType.sourceType),
|
||||
_dateType => ({ type: "string", format: "date" }),
|
||||
_timeType => ({ type: "string", format: "time" }),
|
||||
_dateTimeType => ({ type: "string", format: "date-time" })
|
||||
|
|
|
@ -163,7 +163,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer {
|
|||
mapType => ["m(", this.typeMapTypeFor(mapType.values), ")"],
|
||||
_enumType => panic("We handled this above"),
|
||||
unionType => {
|
||||
const children = unionType.children.map(this.typeMapTypeFor);
|
||||
const children = unionType.getChildren().map(this.typeMapTypeFor);
|
||||
return ["u(", ...intercalate(", ", children).toArray(), ")"];
|
||||
}
|
||||
);
|
||||
|
|
|
@ -487,7 +487,7 @@ export class RubyRenderer extends ConvenienceRenderer {
|
|||
this.emitDescription(this.descriptionForType(u));
|
||||
this.emitBlock(["class ", unionName, " < Dry::Struct"], () => {
|
||||
const table: Sourcelike[][] = [];
|
||||
this.forEachUnionMember(u, u.children, "none", null, (name, t) => {
|
||||
this.forEachUnionMember(u, u.getChildren(), "none", null, (name, t) => {
|
||||
table.push([["attribute :", name, ", "], [this.dryType(t, true)]]);
|
||||
});
|
||||
this.emitTable(table);
|
||||
|
@ -499,8 +499,8 @@ export class RubyRenderer extends ConvenienceRenderer {
|
|||
this.ensureBlankLine();
|
||||
const [maybeNull, nonNulls] = removeNullFromUnion(u, false);
|
||||
this.emitBlock("def self.from_dynamic!(d)", () => {
|
||||
const memberNames = u.children.map((member: Type) => this.nameForUnionMember(u, member));
|
||||
this.forEachUnionMember(u, u.children, "none", null, (name, t) => {
|
||||
const memberNames = u.getChildren().map((member: Type) => this.nameForUnionMember(u, member));
|
||||
this.forEachUnionMember(u, u.getChildren(), "none", null, (name, t) => {
|
||||
const nilMembers = memberNames
|
||||
.remove(name)
|
||||
.toArray()
|
||||
|
|
|
@ -91,7 +91,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer {
|
|||
_enumType => panic("We handled this above"),
|
||||
unionType => {
|
||||
if (this._inlineUnions || nullableFromUnion(unionType) !== null) {
|
||||
const children = unionType.children.map(c => parenIfNeeded(this.sourceFor(c)));
|
||||
const children = unionType.getChildren().map(c => parenIfNeeded(this.sourceFor(c)));
|
||||
return multiWord(" | ", ...children.toArray());
|
||||
} else {
|
||||
return singleWord(this.nameForNamedType(unionType));
|
||||
|
@ -123,7 +123,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer {
|
|||
|
||||
this.emitDescription(this.descriptionForType(u));
|
||||
|
||||
const children = multiWord(" | ", ...u.children.map(c => parenIfNeeded(this.sourceFor(c))).toArray());
|
||||
const children = multiWord(" | ", ...u.getChildren().map(c => parenIfNeeded(this.sourceFor(c))).toArray());
|
||||
this.emitLine("export type ", unionName, " = ", children.source, ";");
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ export function replaceObjectType(
|
|||
}
|
||||
|
||||
function makeClass(): TypeRef {
|
||||
return builder.getUniqueClassType(attributes, true, reconstituteProperties(), forwardingRef);
|
||||
return builder.getUniqueClassType(attributes, true, reconstituteProperties(), undefined, forwardingRef);
|
||||
}
|
||||
|
||||
function reconstituteAdditionalProperties(): TypeRef {
|
||||
|
@ -43,7 +43,7 @@ export function replaceObjectType(
|
|||
}
|
||||
|
||||
if (properties.isEmpty()) {
|
||||
const tref = builder.getMapType(reconstituteAdditionalProperties(), forwardingRef);
|
||||
const tref = builder.getMapType(reconstituteAdditionalProperties(), undefined, forwardingRef);
|
||||
builder.addAttributes(tref, attributes);
|
||||
return tref;
|
||||
}
|
||||
|
@ -77,12 +77,12 @@ export function replaceObjectType(
|
|||
*/
|
||||
}
|
||||
|
||||
const mapType = builder.getMapType(union, forwardingRef);
|
||||
const mapType = builder.getMapType(union, undefined, forwardingRef);
|
||||
builder.addAttributes(mapType, attributes);
|
||||
return mapType;
|
||||
}
|
||||
|
||||
const allObjectTypes = graph.allTypesUnordered().filter(t => t.kind === "object") as Set<ObjectType>;
|
||||
const allObjectTypes = graph.allTypesUnordered().filter(t => t.kind === "object" && t.transformation === undefined) as Set<ObjectType>;
|
||||
const objectTypesToReplace = leaveFullObjects
|
||||
? allObjectTypes.filter(o => o.getProperties().isEmpty() || o.getAdditionalProperties() === undefined)
|
||||
: allObjectTypes;
|
||||
|
|
|
@ -222,6 +222,7 @@ class IntersectionAccumulator
|
|||
}
|
||||
|
||||
addType(t: Type): TypeAttributes {
|
||||
assert(t.transformation === undefined, "We don't support intersections of transformations yet");
|
||||
let attributes = t.getAttributes();
|
||||
matchTypeExhaustive<void>(
|
||||
t,
|
||||
|
@ -247,9 +248,6 @@ class IntersectionAccumulator
|
|||
);
|
||||
this.addUnionSet(unionType.members);
|
||||
},
|
||||
_transformedType => {
|
||||
return panic("We don't support intersections with transformed types yet");
|
||||
},
|
||||
dateType => this.addUnionSet(OrderedSet([dateType])),
|
||||
timeType => this.addUnionSet(OrderedSet([timeType])),
|
||||
dateTimeType => this.addUnionSet(OrderedSet([dateTimeType]))
|
||||
|
@ -367,7 +365,7 @@ class IntersectionUnionBuilder extends UnionBuilder<
|
|||
typeAttributes: TypeAttributes,
|
||||
forwardingRef: TypeRef | undefined
|
||||
): TypeRef {
|
||||
return this.typeBuilder.getEnumType(typeAttributes, OrderedSet(cases), forwardingRef);
|
||||
return this.typeBuilder.getEnumType(typeAttributes, OrderedSet(cases), undefined, forwardingRef);
|
||||
}
|
||||
|
||||
protected makeObject(
|
||||
|
@ -387,7 +385,7 @@ class IntersectionUnionBuilder extends UnionBuilder<
|
|||
maybeAdditionalProperties === undefined
|
||||
? undefined
|
||||
: this.makeIntersection(maybeAdditionalProperties, emptyTypeAttributes);
|
||||
return this.typeBuilder.getUniqueObjectType(typeAttributes, properties, additionalProperties, forwardingRef);
|
||||
return this.typeBuilder.getUniqueObjectType(typeAttributes, properties, additionalProperties, undefined, forwardingRef);
|
||||
}
|
||||
|
||||
protected makeArray(
|
||||
|
@ -397,7 +395,7 @@ class IntersectionUnionBuilder extends UnionBuilder<
|
|||
): TypeRef {
|
||||
// FIXME: attributes
|
||||
const itemsType = this.makeIntersection(arrays, Map());
|
||||
const tref = this.typeBuilder.getArrayType(itemsType, forwardingRef);
|
||||
const tref = this.typeBuilder.getArrayType(itemsType, undefined, forwardingRef);
|
||||
this.typeBuilder.addAttributes(tref, typeAttributes);
|
||||
return tref;
|
||||
}
|
||||
|
@ -414,7 +412,7 @@ export function resolveIntersections(
|
|||
const intersections = types.filter(t => t instanceof IntersectionType) as Set<IntersectionType>;
|
||||
const [members, intersectionAttributes] = setOperationMembersRecursively(intersections.toArray());
|
||||
if (members.isEmpty()) {
|
||||
const t = builder.getPrimitiveType("any", forwardingRef);
|
||||
const t = builder.getPrimitiveType("any", undefined, forwardingRef);
|
||||
builder.addAttributes(t, intersectionAttributes);
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,14 @@ export function mapOptional<T, U>(f: (x: T) => U, x: T | undefined): U | undefin
|
|||
return f(x);
|
||||
}
|
||||
|
||||
export function ifUndefined<T>(x: any, f: () => T): T | undefined {
|
||||
if (x === undefined) {
|
||||
return f();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function defined<T>(x: T | undefined): T {
|
||||
if (x !== undefined) return x;
|
||||
return panic("Defined value expected, but got undefined");
|
||||
|
|
170
src/Type.ts
170
src/Type.ts
|
@ -61,9 +61,13 @@ export class Transformation {
|
|||
}
|
||||
|
||||
export abstract class Type {
|
||||
constructor(readonly typeRef: TypeRef, readonly kind: TypeKind, private _transformation?: Transformation) {}
|
||||
constructor(
|
||||
readonly typeRef: TypeRef,
|
||||
readonly kind: TypeKind,
|
||||
private _transformation: Transformation | undefined
|
||||
) {}
|
||||
|
||||
setTransformation(transformation: Transformation): void {
|
||||
setTransformation(transformation: Transformation | undefined): void {
|
||||
assert(this._transformation === undefined, "Tried to set transformation twice");
|
||||
this._transformation = transformation;
|
||||
}
|
||||
|
@ -72,7 +76,7 @@ export abstract class Type {
|
|||
return this._transformation;
|
||||
}
|
||||
|
||||
get children(): OrderedSet<Type> {
|
||||
getChildren(): OrderedSet<Type> {
|
||||
if (this._transformation === undefined) {
|
||||
return OrderedSet();
|
||||
}
|
||||
|
@ -82,7 +86,7 @@ export abstract class Type {
|
|||
directlyReachableTypes<T>(setForType: (t: Type) => OrderedSet<T> | null): OrderedSet<T> {
|
||||
const set = setForType(this);
|
||||
if (set) return set;
|
||||
return orderedSetUnion(this.children.map((t: Type) => t.directlyReachableTypes(setForType)));
|
||||
return orderedSetUnion(this.getChildren().map((t: Type) => t.directlyReachableTypes(setForType)));
|
||||
}
|
||||
|
||||
getAttributes(): TypeAttributes {
|
||||
|
@ -103,15 +107,16 @@ export abstract class Type {
|
|||
|
||||
abstract get isNullable(): boolean;
|
||||
abstract isPrimitive(): this is PrimitiveType;
|
||||
abstract reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void;
|
||||
|
||||
reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void {
|
||||
protected reconstituteTransformation<T extends BaseGraphRewriteBuilder>(
|
||||
builder: TypeReconstituter<T>
|
||||
): Transformation | undefined {
|
||||
const tform = this._transformation;
|
||||
if (tform === undefined) {
|
||||
builder.setTransformationAndFinish();
|
||||
return undefined;
|
||||
}
|
||||
builder.setTransformationAndFinish(
|
||||
new Transformation(tform.transformer, builder.reconstitute(tform.targetType.typeRef))
|
||||
);
|
||||
return new Transformation(tform.transformer, builder.reconstitute(tform.targetType.typeRef));
|
||||
}
|
||||
|
||||
get debugPrintKind(): string {
|
||||
|
@ -226,15 +231,11 @@ export class PrimitiveType extends Type {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
readonly kind: PrimitiveTypeKind;
|
||||
|
||||
constructor(typeRef: TypeRef, kind: PrimitiveTypeKind, checkKind: boolean = true) {
|
||||
constructor(typeRef: TypeRef, kind: PrimitiveTypeKind, transformation: Transformation | undefined, checkKind: boolean = true) {
|
||||
if (checkKind) {
|
||||
assert(kind !== "string", "Cannot instantiate a PrimitiveType as string");
|
||||
}
|
||||
super(typeRef, kind);
|
||||
}
|
||||
|
||||
get children(): OrderedSet<Type> {
|
||||
return OrderedSet();
|
||||
super(typeRef, kind, transformation);
|
||||
}
|
||||
|
||||
get isNullable(): boolean {
|
||||
|
@ -246,25 +247,21 @@ export class PrimitiveType extends Type {
|
|||
}
|
||||
|
||||
reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void {
|
||||
builder.getPrimitiveType(this.kind);
|
||||
}
|
||||
|
||||
protected structuralEqualityStep(_other: Type, _queue: (a: Type, b: Type) => boolean): boolean {
|
||||
return true;
|
||||
builder.getPrimitiveType(this.kind, this.reconstituteTransformation(builder));
|
||||
}
|
||||
}
|
||||
|
||||
export class StringType extends PrimitiveType {
|
||||
constructor(typeRef: TypeRef, readonly enumCases: OrderedMap<string, number> | undefined) {
|
||||
super(typeRef, "string", false);
|
||||
constructor(
|
||||
typeRef: TypeRef,
|
||||
readonly enumCases: OrderedMap<string, number> | undefined,
|
||||
transformation: Transformation | undefined
|
||||
) {
|
||||
super(typeRef, "string", transformation, false);
|
||||
}
|
||||
|
||||
reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void {
|
||||
builder.getStringType(this.enumCases);
|
||||
}
|
||||
|
||||
protected structuralEqualityStep(_other: Type, _queue: (a: Type, b: Type) => boolean): boolean {
|
||||
return true;
|
||||
builder.getStringType(this.enumCases, this.reconstituteTransformation(builder));
|
||||
}
|
||||
|
||||
get debugPrintKind(): string {
|
||||
|
@ -279,15 +276,16 @@ export class ArrayType extends Type {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
readonly kind: "array";
|
||||
|
||||
constructor(typeRef: TypeRef, private _itemsRef?: TypeRef) {
|
||||
super(typeRef, "array");
|
||||
constructor(typeRef: TypeRef, private _itemsRef: TypeRef | undefined, transformation: Transformation | undefined) {
|
||||
super(typeRef, "array", transformation);
|
||||
}
|
||||
|
||||
setItems(itemsRef: TypeRef) {
|
||||
setItems(itemsRef: TypeRef, transformation: Transformation | undefined) {
|
||||
if (this._itemsRef !== undefined) {
|
||||
return panic("Can only set array items once");
|
||||
}
|
||||
this._itemsRef = itemsRef;
|
||||
super.setTransformation(transformation);
|
||||
}
|
||||
|
||||
private getItemsRef(): TypeRef {
|
||||
|
@ -301,8 +299,8 @@ export class ArrayType extends Type {
|
|||
return this.getItemsRef().deref()[0];
|
||||
}
|
||||
|
||||
get children(): OrderedSet<Type> {
|
||||
return OrderedSet([this.items]);
|
||||
getChildren(): OrderedSet<Type> {
|
||||
return super.getChildren().add(this.items);
|
||||
}
|
||||
|
||||
get isNullable(): boolean {
|
||||
|
@ -318,14 +316,14 @@ export class ArrayType extends Type {
|
|||
const maybeItems = builder.lookup(itemsRef);
|
||||
if (maybeItems === undefined) {
|
||||
builder.getUniqueArrayType();
|
||||
builder.setArrayItems(builder.reconstitute(itemsRef));
|
||||
builder.setArrayItems(builder.reconstitute(itemsRef), this.reconstituteTransformation(builder));
|
||||
} else {
|
||||
builder.getArrayType(maybeItems);
|
||||
builder.getArrayType(maybeItems, this.reconstituteTransformation(builder));
|
||||
}
|
||||
}
|
||||
|
||||
protected structuralEqualityStep(other: ArrayType, queue: (a: Type, b: Type) => boolean): boolean {
|
||||
return queue(this.items, other.items);
|
||||
return super.structuralEqualityStep(other, queue) && queue(this.items, other.items);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,9 +362,10 @@ export class ObjectType extends Type {
|
|||
kind: TypeKind,
|
||||
readonly isFixed: boolean,
|
||||
private _properties: OrderedMap<string, ClassProperty> | undefined,
|
||||
private _additionalPropertiesRef: TypeRef | undefined
|
||||
private _additionalPropertiesRef: TypeRef | undefined,
|
||||
transformation: Transformation | undefined
|
||||
) {
|
||||
super(typeRef, kind);
|
||||
super(typeRef, kind, transformation);
|
||||
|
||||
assert(kind === "object" || kind === "map" || kind === "class");
|
||||
if (kind === "map") {
|
||||
|
@ -381,7 +380,11 @@ export class ObjectType extends Type {
|
|||
}
|
||||
}
|
||||
|
||||
setProperties(properties: OrderedMap<string, ClassProperty>, additionalPropertiesRef: TypeRef | undefined) {
|
||||
setProperties(
|
||||
properties: OrderedMap<string, ClassProperty>,
|
||||
additionalPropertiesRef: TypeRef | undefined,
|
||||
transformation: Transformation | undefined
|
||||
) {
|
||||
if (this instanceof MapType) {
|
||||
assert(properties.isEmpty(), "Cannot set properties on map type");
|
||||
} else if (this._properties !== undefined) {
|
||||
|
@ -394,6 +397,8 @@ export class ObjectType extends Type {
|
|||
|
||||
this._properties = properties;
|
||||
this._additionalPropertiesRef = additionalPropertiesRef;
|
||||
|
||||
this.setTransformation(transformation);
|
||||
}
|
||||
|
||||
getProperties(): OrderedMap<string, ClassProperty> {
|
||||
|
@ -413,7 +418,7 @@ export class ObjectType extends Type {
|
|||
return this._additionalPropertiesRef.deref()[0];
|
||||
}
|
||||
|
||||
get children(): OrderedSet<Type> {
|
||||
getChildren(): OrderedSet<Type> {
|
||||
const children = this.getSortedProperties()
|
||||
.map(p => p.type)
|
||||
.toOrderedSet();
|
||||
|
@ -421,7 +426,7 @@ export class ObjectType extends Type {
|
|||
if (additionalProperties === undefined) {
|
||||
return children;
|
||||
}
|
||||
return children.add(additionalProperties);
|
||||
return super.getChildren().union(children.add(additionalProperties));
|
||||
}
|
||||
|
||||
get isNullable(): boolean {
|
||||
|
@ -443,20 +448,21 @@ export class ObjectType extends Type {
|
|||
const properties = this.getProperties().map(
|
||||
(cp, n) => new ClassProperty(defined(maybePropertyTypes.get(n)), cp.isOptional)
|
||||
);
|
||||
const tform = this.reconstituteTransformation(builder);
|
||||
|
||||
switch (this.kind) {
|
||||
case "object":
|
||||
assert(this.isFixed);
|
||||
builder.getObjectType(properties, maybeAdditionalProperties);
|
||||
builder.getObjectType(properties, maybeAdditionalProperties, tform);
|
||||
break;
|
||||
case "map":
|
||||
builder.getMapType(defined(maybeAdditionalProperties));
|
||||
builder.getMapType(defined(maybeAdditionalProperties), tform);
|
||||
break;
|
||||
case "class":
|
||||
if (this.isFixed) {
|
||||
builder.getUniqueClassType(true, properties);
|
||||
builder.getUniqueClassType(true, properties, tform);
|
||||
} else {
|
||||
builder.getClassType(properties);
|
||||
builder.getClassType(properties, tform);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -466,13 +472,13 @@ export class ObjectType extends Type {
|
|||
switch (this.kind) {
|
||||
case "object":
|
||||
assert(this.isFixed);
|
||||
builder.getUniqueObjectType(undefined, undefined);
|
||||
builder.getUniqueObjectType(undefined, undefined, undefined);
|
||||
break;
|
||||
case "map":
|
||||
builder.getUniqueMapType();
|
||||
break;
|
||||
case "class":
|
||||
builder.getUniqueClassType(this.isFixed, undefined);
|
||||
builder.getUniqueClassType(this.isFixed, undefined, undefined);
|
||||
break;
|
||||
default:
|
||||
return panic(`Invalid object type kind ${this.kind}`);
|
||||
|
@ -482,11 +488,13 @@ export class ObjectType extends Type {
|
|||
cp => new ClassProperty(builder.reconstitute(cp.typeRef), cp.isOptional)
|
||||
);
|
||||
const additionalProperties = mapOptional(r => builder.reconstitute(r), this._additionalPropertiesRef);
|
||||
builder.setObjectProperties(properties, additionalProperties);
|
||||
builder.setObjectProperties(properties, additionalProperties, this.reconstituteTransformation(builder));
|
||||
}
|
||||
}
|
||||
|
||||
protected structuralEqualityStep(other: ObjectType, queue: (a: Type, b: Type) => boolean): boolean {
|
||||
if (!super.structuralEqualityStep(other, queue)) return false;
|
||||
|
||||
const pa = this.getProperties();
|
||||
const pb = other.getProperties();
|
||||
if (pa.size !== pb.size) return false;
|
||||
|
@ -512,8 +520,13 @@ export class ClassType extends ObjectType {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
kind: "class";
|
||||
|
||||
constructor(typeRef: TypeRef, isFixed: boolean, properties: OrderedMap<string, ClassProperty> | undefined) {
|
||||
super(typeRef, "class", isFixed, properties, undefined);
|
||||
constructor(
|
||||
typeRef: TypeRef,
|
||||
isFixed: boolean,
|
||||
properties: OrderedMap<string, ClassProperty> | undefined,
|
||||
transformation: Transformation | undefined
|
||||
) {
|
||||
super(typeRef, "class", isFixed, properties, undefined, transformation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,8 +534,8 @@ export class MapType extends ObjectType {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
readonly kind: "map";
|
||||
|
||||
constructor(typeRef: TypeRef, valuesRef: TypeRef | undefined) {
|
||||
super(typeRef, "map", false, OrderedMap(), valuesRef);
|
||||
constructor(typeRef: TypeRef, valuesRef: TypeRef | undefined, transformation: Transformation | undefined) {
|
||||
super(typeRef, "map", false, OrderedMap(), valuesRef, transformation);
|
||||
}
|
||||
|
||||
// FIXME: Remove and use `getAdditionalProperties()` instead.
|
||||
|
@ -535,12 +548,8 @@ export class EnumType extends Type {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
kind: "enum";
|
||||
|
||||
constructor(typeRef: TypeRef, readonly cases: OrderedSet<string>) {
|
||||
super(typeRef, "enum");
|
||||
}
|
||||
|
||||
get children(): OrderedSet<Type> {
|
||||
return OrderedSet();
|
||||
constructor(typeRef: TypeRef, readonly cases: OrderedSet<string>, transformation: Transformation | undefined) {
|
||||
super(typeRef, "enum", transformation);
|
||||
}
|
||||
|
||||
get isNullable(): boolean {
|
||||
|
@ -552,11 +561,11 @@ export class EnumType extends Type {
|
|||
}
|
||||
|
||||
reconstitute<T extends BaseGraphRewriteBuilder>(builder: TypeReconstituter<T>): void {
|
||||
builder.getEnumType(this.cases);
|
||||
builder.getEnumType(this.cases, this.reconstituteTransformation(builder));
|
||||
}
|
||||
|
||||
protected structuralEqualityStep(other: EnumType, _queue: (a: Type, b: Type) => void): boolean {
|
||||
return this.cases.toSet().equals(other.cases.toSet());
|
||||
protected structuralEqualityStep(other: EnumType, queue: (a: Type, b: Type) => boolean): boolean {
|
||||
return super.structuralEqualityStep(other, queue) && this.cases.toSet().equals(other.cases.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -578,15 +587,24 @@ export function setOperationCasesEqual(
|
|||
}
|
||||
|
||||
export abstract class SetOperationType extends Type {
|
||||
constructor(typeRef: TypeRef, kind: TypeKind, private _memberRefs?: OrderedSet<TypeRef>) {
|
||||
super(typeRef, kind);
|
||||
constructor(
|
||||
typeRef: TypeRef,
|
||||
kind: TypeKind,
|
||||
private _memberRefs: OrderedSet<TypeRef> | undefined,
|
||||
transformation: Transformation | undefined
|
||||
) {
|
||||
super(typeRef, kind, transformation);
|
||||
assert(transformation === undefined, "We don't support set operations with transformations yet");
|
||||
}
|
||||
|
||||
setMembers(memberRefs: OrderedSet<TypeRef>): void {
|
||||
setMembers(memberRefs: OrderedSet<TypeRef>, transformation: Transformation | undefined): void {
|
||||
if (this._memberRefs !== undefined) {
|
||||
return panic("Can only set map members once");
|
||||
}
|
||||
this._memberRefs = memberRefs;
|
||||
|
||||
assert(transformation === undefined, "We don't support set operations with transformations yet");
|
||||
this.setTransformation(transformation);
|
||||
}
|
||||
|
||||
protected getMemberRefs(): OrderedSet<TypeRef> {
|
||||
|
@ -605,8 +623,8 @@ export abstract class SetOperationType extends Type {
|
|||
return this.members.sortBy(t => t.kind);
|
||||
}
|
||||
|
||||
get children(): OrderedSet<Type> {
|
||||
return this.sortedMembers;
|
||||
getChildren(): OrderedSet<Type> {
|
||||
return super.getChildren().union(this.sortedMembers);
|
||||
}
|
||||
|
||||
isPrimitive(): this is PrimitiveType {
|
||||
|
@ -614,7 +632,7 @@ export abstract class SetOperationType extends Type {
|
|||
}
|
||||
|
||||
protected structuralEqualityStep(other: SetOperationType, queue: (a: Type, b: Type) => boolean): boolean {
|
||||
return setOperationCasesEqual(this.members, other.members, queue);
|
||||
return super.structuralEqualityStep(other, queue) && setOperationCasesEqual(this.members, other.members, queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -622,8 +640,8 @@ export class IntersectionType extends SetOperationType {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
kind: "intersection";
|
||||
|
||||
constructor(typeRef: TypeRef, memberRefs?: OrderedSet<TypeRef>) {
|
||||
super(typeRef, "intersection", memberRefs);
|
||||
constructor(typeRef: TypeRef, memberRefs: OrderedSet<TypeRef> | undefined, transformation: Transformation | undefined) {
|
||||
super(typeRef, "intersection", memberRefs, transformation);
|
||||
}
|
||||
|
||||
get isNullable(): boolean {
|
||||
|
@ -635,9 +653,9 @@ export class IntersectionType extends SetOperationType {
|
|||
const maybeMembers = builder.lookup(memberRefs);
|
||||
if (maybeMembers === undefined) {
|
||||
builder.getUniqueIntersectionType();
|
||||
builder.setSetOperationMembers(builder.reconstitute(memberRefs));
|
||||
builder.setSetOperationMembers(builder.reconstitute(memberRefs), this.reconstituteTransformation(builder));
|
||||
} else {
|
||||
builder.getIntersectionType(maybeMembers);
|
||||
builder.getIntersectionType(maybeMembers, this.reconstituteTransformation(builder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -646,16 +664,16 @@ export class UnionType extends SetOperationType {
|
|||
// @ts-ignore: This is initialized in the Type constructor
|
||||
kind: "union";
|
||||
|
||||
constructor(typeRef: TypeRef, memberRefs?: OrderedSet<TypeRef>) {
|
||||
super(typeRef, "union", memberRefs);
|
||||
constructor(typeRef: TypeRef, memberRefs: OrderedSet<TypeRef> | undefined, transformation: Transformation | undefined) {
|
||||
super(typeRef, "union", memberRefs, transformation);
|
||||
if (memberRefs !== undefined) {
|
||||
messageAssert(!memberRefs.isEmpty(), ErrorMessage.IRNoEmptyUnions);
|
||||
}
|
||||
}
|
||||
|
||||
setMembers(memberRefs: OrderedSet<TypeRef>): void {
|
||||
setMembers(memberRefs: OrderedSet<TypeRef>, transformation: Transformation | undefined): void {
|
||||
messageAssert(!memberRefs.isEmpty(), ErrorMessage.IRNoEmptyUnions);
|
||||
super.setMembers(memberRefs);
|
||||
super.setMembers(memberRefs, transformation);
|
||||
}
|
||||
|
||||
get stringTypeMembers(): OrderedSet<Type> {
|
||||
|
@ -693,9 +711,9 @@ export class UnionType extends SetOperationType {
|
|||
const maybeMembers = builder.lookup(memberRefs);
|
||||
if (maybeMembers === undefined) {
|
||||
builder.getUniqueUnionType();
|
||||
builder.setSetOperationMembers(builder.reconstitute(memberRefs));
|
||||
builder.setSetOperationMembers(builder.reconstitute(memberRefs), this.reconstituteTransformation(builder));
|
||||
} else {
|
||||
builder.getUnionType(maybeMembers);
|
||||
builder.getUnionType(maybeMembers, this.reconstituteTransformation(builder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
import { Map, OrderedMap, OrderedSet, Set, List } from "immutable";
|
||||
import { Map, OrderedMap, OrderedSet, Set } from "immutable";
|
||||
|
||||
import {
|
||||
PrimitiveTypeKind,
|
||||
|
@ -16,13 +16,12 @@ import {
|
|||
ClassProperty,
|
||||
IntersectionType,
|
||||
ObjectType,
|
||||
Transformer,
|
||||
Transformation
|
||||
} from "./Type";
|
||||
import { removeNullFromUnion } from "./TypeUtils";
|
||||
import { TypeGraph } from "./TypeGraph";
|
||||
import { TypeAttributes, combineTypeAttributes, TypeAttributeKind } from "./TypeAttributes";
|
||||
import { defined, assert, panic, setUnion, mapOptional } from "./Support";
|
||||
import { defined, assert, panic, setUnion, mapOptional, ifUndefined } from "./Support";
|
||||
|
||||
export class TypeRef {
|
||||
constructor(readonly graph: TypeGraph, readonly index: number) {}
|
||||
|
@ -179,7 +178,7 @@ export class TypeBuilder {
|
|||
|
||||
protected addForwardingIntersection(forwardingRef: TypeRef, tref: TypeRef): TypeRef {
|
||||
this._addedForwardingIntersection = true;
|
||||
return this.addType(forwardingRef, tr => new IntersectionType(tr, OrderedSet([tref])), undefined);
|
||||
return this.addType(forwardingRef, tr => new IntersectionType(tr, OrderedSet([tref]), undefined), undefined);
|
||||
}
|
||||
|
||||
protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: undefined): undefined;
|
||||
|
@ -205,20 +204,21 @@ export class TypeBuilder {
|
|||
private _classTypes: Map<Map<string, ClassProperty>, TypeRef> = Map();
|
||||
private _unionTypes: Map<Set<TypeRef>, TypeRef> = Map();
|
||||
private _intersectionTypes: Map<Set<TypeRef>, TypeRef> = Map();
|
||||
private _transformedTypes: Map<List<any>, TypeRef> = Map();
|
||||
|
||||
getPrimitiveType(kind: PrimitiveTypeKind, forwardingRef?: TypeRef): TypeRef {
|
||||
getPrimitiveType(kind: PrimitiveTypeKind, transformation?: Transformation, forwardingRef?: TypeRef): TypeRef {
|
||||
assert(kind !== "string", "Use getStringType to create strings");
|
||||
if (kind === "date") kind = this._stringTypeMapping.date;
|
||||
if (kind === "time") kind = this._stringTypeMapping.time;
|
||||
if (kind === "date-time") kind = this._stringTypeMapping.dateTime;
|
||||
if (kind === "string") {
|
||||
return this.getStringType(undefined, undefined, forwardingRef);
|
||||
return this.getStringType(undefined, undefined, transformation, forwardingRef);
|
||||
}
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._primitiveTypes.get(kind));
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._primitiveTypes.get(kind)));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new PrimitiveType(tr, kind), undefined);
|
||||
this._primitiveTypes = this._primitiveTypes.set(kind, tref);
|
||||
tref = this.addType(forwardingRef, tr => new PrimitiveType(tr, kind, transformation), undefined);
|
||||
if (transformation === undefined) {
|
||||
this._primitiveTypes = this._primitiveTypes.set(kind, tref);
|
||||
}
|
||||
}
|
||||
return tref;
|
||||
}
|
||||
|
@ -226,6 +226,7 @@ export class TypeBuilder {
|
|||
getStringType(
|
||||
attributes: TypeAttributes | undefined,
|
||||
cases: OrderedMap<string, number> | undefined,
|
||||
transformation?: Transformation,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
if (cases === undefined) {
|
||||
|
@ -240,27 +241,32 @@ export class TypeBuilder {
|
|||
// out whether we do want string types to have names (we most
|
||||
// likely don't), and if not, still don't keep track of them.
|
||||
let result: TypeRef;
|
||||
if (this._noEnumStringType === undefined) {
|
||||
result = this._noEnumStringType = this.addType(
|
||||
if (this._noEnumStringType === undefined || transformation !== undefined) {
|
||||
result = this.addType(
|
||||
forwardingRef,
|
||||
tr => new StringType(tr, undefined),
|
||||
tr => new StringType(tr, undefined, transformation),
|
||||
undefined
|
||||
);
|
||||
if (transformation === undefined) {
|
||||
this._noEnumStringType = result;
|
||||
}
|
||||
} else {
|
||||
result = this.forwardIfNecessary(forwardingRef, this._noEnumStringType);
|
||||
}
|
||||
this.addAttributes(this._noEnumStringType, attributes);
|
||||
this.addAttributes(result, attributes);
|
||||
return result;
|
||||
}
|
||||
return this.addType(forwardingRef, tr => new StringType(tr, cases), attributes);
|
||||
return this.addType(forwardingRef, tr => new StringType(tr, cases, transformation), attributes);
|
||||
}
|
||||
|
||||
getEnumType(attributes: TypeAttributes, cases: OrderedSet<string>, forwardingRef?: TypeRef): TypeRef {
|
||||
getEnumType(attributes: TypeAttributes, cases: OrderedSet<string>, transformation?: Transformation, forwardingRef?: TypeRef): TypeRef {
|
||||
const unorderedCases = cases.toSet();
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._enumTypes.get(unorderedCases));
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._enumTypes.get(unorderedCases)));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new EnumType(tr, cases), attributes);
|
||||
this._enumTypes = this._enumTypes.set(unorderedCases, tref);
|
||||
tref = this.addType(forwardingRef, tr => new EnumType(tr, cases, transformation), attributes);
|
||||
if (transformation === undefined) {
|
||||
this._enumTypes = this._enumTypes.set(unorderedCases, tref);
|
||||
}
|
||||
} else {
|
||||
this.addAttributes(tref, attributes);
|
||||
}
|
||||
|
@ -271,18 +277,19 @@ export class TypeBuilder {
|
|||
attributes: TypeAttributes,
|
||||
properties: OrderedMap<string, ClassProperty> | undefined,
|
||||
additionalProperties: TypeRef | undefined,
|
||||
transformation?: Transformation,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
properties = mapOptional(p => this.modifyPropertiesIfNecessary(p), properties);
|
||||
return this.addType(
|
||||
forwardingRef,
|
||||
tref => new ObjectType(tref, "object", true, properties, additionalProperties),
|
||||
tref => new ObjectType(tref, "object", true, properties, additionalProperties, transformation),
|
||||
attributes
|
||||
);
|
||||
}
|
||||
|
||||
getUniqueMapType(forwardingRef?: TypeRef): TypeRef {
|
||||
return this.addType(forwardingRef, tr => new MapType(tr, undefined), undefined);
|
||||
return this.addType(forwardingRef, tr => new MapType(tr, undefined, undefined), undefined);
|
||||
}
|
||||
|
||||
private registerMapType(values: TypeRef, tref: TypeRef): void {
|
||||
|
@ -290,11 +297,13 @@ export class TypeBuilder {
|
|||
this._mapTypes = this._mapTypes.set(values, tref);
|
||||
}
|
||||
|
||||
getMapType(values: TypeRef, forwardingRef?: TypeRef): TypeRef {
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._mapTypes.get(values));
|
||||
getMapType(values: TypeRef, transformation?: Transformation, forwardingRef?: TypeRef): TypeRef {
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._mapTypes.get(values)));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new MapType(tr, values), undefined);
|
||||
this.registerMapType(values, tref);
|
||||
tref = this.addType(forwardingRef, tr => new MapType(tr, values, transformation), undefined);
|
||||
if (transformation === undefined) {
|
||||
this.registerMapType(values, tref);
|
||||
}
|
||||
}
|
||||
return tref;
|
||||
}
|
||||
|
@ -307,13 +316,16 @@ export class TypeBuilder {
|
|||
setObjectProperties(
|
||||
ref: TypeRef,
|
||||
properties: OrderedMap<string, ClassProperty>,
|
||||
additionalProperties: TypeRef | undefined
|
||||
additionalProperties: TypeRef | undefined,
|
||||
transformation?: Transformation
|
||||
): void {
|
||||
const type = ref.deref()[0];
|
||||
if (!(type instanceof ObjectType)) {
|
||||
return panic("Tried to set properties of non-object type");
|
||||
}
|
||||
type.setProperties(this.modifyPropertiesIfNecessary(properties), additionalProperties);
|
||||
type.setProperties(this.modifyPropertiesIfNecessary(properties), additionalProperties, transformation);
|
||||
|
||||
if (transformation !== undefined) return;
|
||||
if (type instanceof MapType) {
|
||||
this.registerMapType(defined(additionalProperties), ref);
|
||||
} else if (type instanceof ClassType) {
|
||||
|
@ -324,7 +336,7 @@ export class TypeBuilder {
|
|||
}
|
||||
|
||||
getUniqueArrayType(forwardingRef?: TypeRef): TypeRef {
|
||||
return this.addType(forwardingRef, tr => new ArrayType(tr, undefined), undefined);
|
||||
return this.addType(forwardingRef, tr => new ArrayType(tr, undefined, undefined), undefined);
|
||||
}
|
||||
|
||||
private registerArrayType(items: TypeRef, tref: TypeRef): void {
|
||||
|
@ -332,22 +344,26 @@ export class TypeBuilder {
|
|||
this._arrayTypes = this._arrayTypes.set(items, tref);
|
||||
}
|
||||
|
||||
getArrayType(items: TypeRef, forwardingRef?: TypeRef): TypeRef {
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._arrayTypes.get(items));
|
||||
getArrayType(items: TypeRef, transformation?: Transformation, forwardingRef?: TypeRef): TypeRef {
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._arrayTypes.get(items)));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new ArrayType(tr, items), undefined);
|
||||
this.registerArrayType(items, tref);
|
||||
tref = this.addType(forwardingRef, tr => new ArrayType(tr, items, transformation), undefined);
|
||||
if (transformation === undefined) {
|
||||
this.registerArrayType(items, tref);
|
||||
}
|
||||
}
|
||||
return tref;
|
||||
}
|
||||
|
||||
setArrayItems(ref: TypeRef, items: TypeRef): void {
|
||||
setArrayItems(ref: TypeRef, items: TypeRef, transformation?: Transformation): void {
|
||||
const type = ref.deref()[0];
|
||||
if (!(type instanceof ArrayType)) {
|
||||
return panic("Tried to set items of non-array type");
|
||||
}
|
||||
type.setItems(items);
|
||||
this.registerArrayType(items, ref);
|
||||
type.setItems(items, transformation);
|
||||
if (transformation === undefined) {
|
||||
this.registerArrayType(items, ref);
|
||||
}
|
||||
}
|
||||
|
||||
modifyPropertiesIfNecessary(properties: OrderedMap<string, ClassProperty>): OrderedMap<string, ClassProperty> {
|
||||
|
@ -363,13 +379,16 @@ export class TypeBuilder {
|
|||
getClassType(
|
||||
attributes: TypeAttributes,
|
||||
properties: OrderedMap<string, ClassProperty>,
|
||||
transformation?: Transformation,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
properties = this.modifyPropertiesIfNecessary(properties);
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._classTypes.get(properties.toMap()));
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._classTypes.get(properties.toMap())));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new ClassType(tr, false, properties), attributes);
|
||||
this.registerClassType(properties, tref);
|
||||
tref = this.addType(forwardingRef, tr => new ClassType(tr, false, properties, transformation), attributes);
|
||||
if (transformation === undefined) {
|
||||
this.registerClassType(properties, tref);
|
||||
}
|
||||
} else {
|
||||
this.addAttributes(tref, attributes);
|
||||
}
|
||||
|
@ -387,18 +406,21 @@ export class TypeBuilder {
|
|||
attributes: TypeAttributes,
|
||||
isFixed: boolean,
|
||||
properties: OrderedMap<string, ClassProperty> | undefined,
|
||||
transformation?: Transformation,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
properties = mapOptional(p => this.modifyPropertiesIfNecessary(p), properties);
|
||||
return this.addType(forwardingRef, tref => new ClassType(tref, isFixed, properties), attributes);
|
||||
return this.addType(forwardingRef, tref => new ClassType(tref, isFixed, properties, transformation), attributes);
|
||||
}
|
||||
|
||||
getUnionType(attributes: TypeAttributes, members: OrderedSet<TypeRef>, forwardingRef?: TypeRef): TypeRef {
|
||||
getUnionType(attributes: TypeAttributes, members: OrderedSet<TypeRef>, transformation?: Transformation, forwardingRef?: TypeRef): TypeRef {
|
||||
const unorderedMembers = members.toSet();
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._unionTypes.get(unorderedMembers));
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._unionTypes.get(unorderedMembers)));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new UnionType(tr, members), attributes);
|
||||
this.registerUnionType(unorderedMembers, tref);
|
||||
tref = this.addType(forwardingRef, tr => new UnionType(tr, members, transformation), attributes);
|
||||
if (transformation === undefined) {
|
||||
this.registerUnionType(unorderedMembers, tref);
|
||||
}
|
||||
} else {
|
||||
this.addAttributes(tref, attributes);
|
||||
}
|
||||
|
@ -408,9 +430,10 @@ export class TypeBuilder {
|
|||
getUniqueUnionType(
|
||||
attributes: TypeAttributes,
|
||||
members: OrderedSet<TypeRef> | undefined,
|
||||
transformation?: Transformation,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
return this.addType(forwardingRef, tref => new UnionType(tref, members), attributes);
|
||||
return this.addType(forwardingRef, tref => new UnionType(tref, members, transformation), attributes);
|
||||
}
|
||||
|
||||
private registerIntersectionType(members: Set<TypeRef>, tref: TypeRef): void {
|
||||
|
@ -418,12 +441,14 @@ export class TypeBuilder {
|
|||
this._intersectionTypes = this._intersectionTypes.set(members, tref);
|
||||
}
|
||||
|
||||
getIntersectionType(attributes: TypeAttributes, members: OrderedSet<TypeRef>, forwardingRef?: TypeRef): TypeRef {
|
||||
getIntersectionType(attributes: TypeAttributes, members: OrderedSet<TypeRef>, transformation?: Transformation, forwardingRef?: TypeRef): TypeRef {
|
||||
const unorderedMembers = members.toSet();
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._intersectionTypes.get(unorderedMembers));
|
||||
let tref = ifUndefined(transformation, () => this.forwardIfNecessary(forwardingRef, this._intersectionTypes.get(unorderedMembers)));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(forwardingRef, tr => new IntersectionType(tr, members), attributes);
|
||||
this.registerIntersectionType(unorderedMembers, tref);
|
||||
tref = this.addType(forwardingRef, tr => new IntersectionType(tr, members, transformation), attributes);
|
||||
if (transformation === undefined) {
|
||||
this.registerIntersectionType(unorderedMembers, tref);
|
||||
}
|
||||
} else {
|
||||
this.addAttributes(tref, attributes);
|
||||
}
|
||||
|
@ -433,17 +458,18 @@ export class TypeBuilder {
|
|||
getUniqueIntersectionType(
|
||||
attributes: TypeAttributes,
|
||||
members: OrderedSet<TypeRef> | undefined,
|
||||
transformation?: Transformation,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
return this.addType(forwardingRef, tref => new IntersectionType(tref, members), attributes);
|
||||
return this.addType(forwardingRef, tref => new IntersectionType(tref, members, transformation), attributes);
|
||||
}
|
||||
|
||||
setSetOperationMembers(ref: TypeRef, members: OrderedSet<TypeRef>): void {
|
||||
setSetOperationMembers(ref: TypeRef, members: OrderedSet<TypeRef>, transformation?: Transformation): void {
|
||||
const type = ref.deref()[0];
|
||||
if (!(type instanceof UnionType || type instanceof IntersectionType)) {
|
||||
return panic("Tried to set members of non-set-operation type");
|
||||
}
|
||||
type.setMembers(members);
|
||||
type.setMembers(members, transformation);
|
||||
const unorderedMembers = members.toSet();
|
||||
if (type instanceof UnionType) {
|
||||
this.registerUnionType(unorderedMembers, ref);
|
||||
|
@ -454,59 +480,7 @@ export class TypeBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
setTransformation(ref: TypeRef, transformation: Transformation): void {
|
||||
const type = ref.deref()[0];
|
||||
type.setTransformation(transformation);
|
||||
}
|
||||
|
||||
setLostTypeAttributes(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
private registerTransformedType(
|
||||
transformer: Transformer,
|
||||
sourceRef: TypeRef,
|
||||
targetRef: TypeRef,
|
||||
tref: TypeRef
|
||||
): void {
|
||||
const key = List([transformer, sourceRef, targetRef]);
|
||||
if (this._transformedTypes.has(key)) return;
|
||||
this._transformedTypes = this._transformedTypes.set(key, tref);
|
||||
}
|
||||
|
||||
getTransformedType(
|
||||
attributes: TypeAttributes,
|
||||
transformer: Transformer,
|
||||
sourceRef: TypeRef,
|
||||
targetRef: TypeRef,
|
||||
forwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
const key = List([transformer, sourceRef, targetRef]);
|
||||
let tref = this.forwardIfNecessary(forwardingRef, this._transformedTypes.get(key));
|
||||
if (tref === undefined) {
|
||||
tref = this.addType(
|
||||
forwardingRef,
|
||||
tr => new TransformedType(tr, transformer, sourceRef, targetRef),
|
||||
attributes
|
||||
);
|
||||
this.registerTransformedType(transformer, sourceRef, targetRef, tref);
|
||||
} else {
|
||||
this.addAttributes(tref, attributes);
|
||||
}
|
||||
return tref;
|
||||
}
|
||||
|
||||
getUniqueTransformedType(attributes: TypeAttributes, transformer: Transformer, forwardingRef?: TypeRef): TypeRef {
|
||||
return this.addType(forwardingRef, tref => new TransformedType(tref, transformer), attributes);
|
||||
}
|
||||
|
||||
setTransformedTypeTypes(ref: TypeRef, sourceRef: TypeRef, targetRef: TypeRef): void {
|
||||
const type = ref.deref()[0];
|
||||
if (!(type instanceof TransformedType)) {
|
||||
return panic("Tried to set types of non-transformed type");
|
||||
}
|
||||
|
||||
type.setTypes(sourceRef, targetRef);
|
||||
this.registerTransformedType(type.transformer, sourceRef, targetRef, ref);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ export class TypeGraph {
|
|||
types = types.push(t);
|
||||
}
|
||||
|
||||
const children = childrenOfType !== undefined ? childrenOfType(t) : t.children;
|
||||
const children = childrenOfType !== undefined ? childrenOfType(t) : t.getChildren();
|
||||
children.forEach(addFromType);
|
||||
|
||||
if (!topDown && required) {
|
||||
|
@ -345,7 +345,7 @@ export class TypeGraph {
|
|||
if (this._parents === undefined) {
|
||||
const parents = defined(this._types).map(_ => Set());
|
||||
this.allTypesUnordered().forEach(p => {
|
||||
p.children.forEach(c => {
|
||||
p.getChildren().forEach(c => {
|
||||
const index = c.typeRef.index;
|
||||
parents[index] = parents[index].add(p);
|
||||
});
|
||||
|
@ -361,7 +361,7 @@ export class TypeGraph {
|
|||
const t = types[i];
|
||||
const parts: string[] = [];
|
||||
parts.push(`${t.debugPrintKind}${t.hasNames ? ` ${t.getCombinedName()}` : ""}`);
|
||||
const children = t.children;
|
||||
const children = t.getChildren();
|
||||
if (!children.isEmpty()) {
|
||||
parts.push(`children ${children.map(c => c.typeRef.index).join(",")}`);
|
||||
}
|
||||
|
@ -385,6 +385,7 @@ export function noneToAny(
|
|||
if (noneTypes.size === 0) {
|
||||
return graph;
|
||||
}
|
||||
assert(noneTypes.every(t => t.transformation === undefined), "We don't support none types with transformations");
|
||||
assert(noneTypes.size === 1, "Cannot have more than one none type");
|
||||
return graph.rewrite(
|
||||
"none to any",
|
||||
|
@ -393,7 +394,7 @@ export function noneToAny(
|
|||
[noneTypes.toArray()],
|
||||
debugPrintReconstitution,
|
||||
(types, builder, forwardingRef) => {
|
||||
const tref = builder.getPrimitiveType("any", forwardingRef);
|
||||
const tref = builder.getPrimitiveType("any", undefined, forwardingRef);
|
||||
const attributes = combineTypeAttributesOfTypes(types);
|
||||
builder.addAttributes(tref, attributes);
|
||||
return tref;
|
||||
|
@ -428,15 +429,15 @@ export function optionalToNullable(
|
|||
return new ClassProperty(ref, false);
|
||||
});
|
||||
if (c.isFixed) {
|
||||
return builder.getUniqueClassType(c.getAttributes(), true, properties, forwardingRef);
|
||||
return builder.getUniqueClassType(c.getAttributes(), true, properties, undefined, forwardingRef);
|
||||
} else {
|
||||
return builder.getClassType(c.getAttributes(), properties, forwardingRef);
|
||||
return builder.getClassType(c.getAttributes(), properties, undefined, forwardingRef);
|
||||
}
|
||||
}
|
||||
|
||||
const classesWithOptional = graph
|
||||
.allTypesUnordered()
|
||||
.filter(t => t instanceof ClassType && t.getProperties().some(p => p.isOptional));
|
||||
.filter(t => t instanceof ClassType && t.transformation === undefined && t.getProperties().some(p => p.isOptional));
|
||||
const replacementGroups = classesWithOptional.map(c => [c as ClassType]).toArray();
|
||||
if (classesWithOptional.size === 0) {
|
||||
return graph;
|
||||
|
|
|
@ -15,8 +15,7 @@ import {
|
|||
ClassType,
|
||||
ClassProperty,
|
||||
SetOperationType,
|
||||
UnionType,
|
||||
TransformedType
|
||||
UnionType
|
||||
} from "./Type";
|
||||
|
||||
export function assertIsObject(t: Type): ObjectType {
|
||||
|
@ -213,7 +212,6 @@ export function matchTypeExhaustive<U>(
|
|||
objectType: (objectType: ObjectType) => U,
|
||||
enumType: (enumType: EnumType) => U,
|
||||
unionType: (unionType: UnionType) => U,
|
||||
transformedType: (transformedType: TransformedType) => U,
|
||||
dateType: (dateType: PrimitiveType) => U,
|
||||
timeType: (timeType: PrimitiveType) => U,
|
||||
dateTimeType: (dateTimeType: PrimitiveType) => U
|
||||
|
@ -239,7 +237,6 @@ export function matchTypeExhaustive<U>(
|
|||
else if (t instanceof ObjectType) return objectType(t);
|
||||
else if (t instanceof EnumType) return enumType(t);
|
||||
else if (t instanceof UnionType) return unionType(t);
|
||||
else if (t instanceof TransformedType) return transformedType(t);
|
||||
return panic(`Unknown type ${t.kind}`);
|
||||
}
|
||||
|
||||
|
@ -281,7 +278,6 @@ export function matchType<U>(
|
|||
typeNotSupported,
|
||||
enumType,
|
||||
unionType,
|
||||
typeNotSupported,
|
||||
stringTypeMatchers.dateType || typeNotSupported,
|
||||
stringTypeMatchers.timeType || typeNotSupported,
|
||||
stringTypeMatchers.dateTimeType || typeNotSupported
|
||||
|
@ -295,8 +291,7 @@ export function matchCompoundType(
|
|||
classType: (classType: ClassType) => void,
|
||||
mapType: (mapType: MapType) => void,
|
||||
objectType: (objectType: ObjectType) => void,
|
||||
unionType: (unionType: UnionType) => void,
|
||||
transformedType: (transformedType: TransformedType) => void
|
||||
unionType: (unionType: UnionType) => void
|
||||
): void {
|
||||
function ignore<T extends Type>(_: T): void {
|
||||
return;
|
||||
|
@ -317,7 +312,6 @@ export function matchCompoundType(
|
|||
objectType,
|
||||
ignore,
|
||||
unionType,
|
||||
transformedType,
|
||||
ignore,
|
||||
ignore,
|
||||
ignore
|
||||
|
|
|
@ -112,9 +112,9 @@ export class UnifyUnionBuilder extends UnionBuilder<TypeBuilder & TypeLookerUp,
|
|||
forwardingRef: TypeRef | undefined
|
||||
): TypeRef {
|
||||
if (this._makeEnums) {
|
||||
return this.typeBuilder.getEnumType(typeAttributes, OrderedSet(enumCases), forwardingRef);
|
||||
return this.typeBuilder.getEnumType(typeAttributes, OrderedSet(enumCases), undefined, forwardingRef);
|
||||
} else {
|
||||
return this.typeBuilder.getStringType(typeAttributes, OrderedMap(counts), forwardingRef);
|
||||
return this.typeBuilder.getStringType(typeAttributes, OrderedMap(counts), undefined, forwardingRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,6 +170,7 @@ export class UnifyUnionBuilder extends UnionBuilder<TypeBuilder & TypeLookerUp,
|
|||
typeAttributes,
|
||||
properties,
|
||||
additionalProperties,
|
||||
undefined,
|
||||
forwardingRef
|
||||
);
|
||||
} else {
|
||||
|
@ -178,6 +179,7 @@ export class UnifyUnionBuilder extends UnionBuilder<TypeBuilder & TypeLookerUp,
|
|||
typeAttributes,
|
||||
this._makeClassesFixed,
|
||||
properties,
|
||||
undefined,
|
||||
forwardingRef
|
||||
);
|
||||
}
|
||||
|
@ -189,7 +191,7 @@ export class UnifyUnionBuilder extends UnionBuilder<TypeBuilder & TypeLookerUp,
|
|||
typeAttributes: TypeAttributes,
|
||||
forwardingRef: TypeRef | undefined
|
||||
): TypeRef {
|
||||
const ref = this.typeBuilder.getArrayType(this._unifyTypes(arrays, Map()), forwardingRef);
|
||||
const ref = this.typeBuilder.getArrayType(this._unifyTypes(arrays, Map()), undefined, forwardingRef);
|
||||
this.typeBuilder.addAttributes(ref, typeAttributes);
|
||||
return ref;
|
||||
}
|
||||
|
@ -222,6 +224,7 @@ export function unifyTypes<T extends Type>(
|
|||
conflateNumbers: boolean,
|
||||
maybeForwardingRef?: TypeRef
|
||||
): TypeRef {
|
||||
assert(types.every(t => t.transformation === undefined), "We don't support unifying types with transformations yet");
|
||||
if (types.isEmpty()) {
|
||||
return panic("Cannot unify empty set of types");
|
||||
} else if (types.count() === 1) {
|
||||
|
|
|
@ -233,6 +233,7 @@ export class TypeRefUnionAccumulator extends UnionAccumulator<TypeRef, TypeRef>
|
|||
// There is a method analogous to this in the IntersectionAccumulator. It might
|
||||
// make sense to find a common interface.
|
||||
private addType(t: Type, attributes: TypeAttributes): void {
|
||||
assert(t.transformation === undefined, "We don't support transformations in unions yet");
|
||||
matchTypeExhaustive(
|
||||
t,
|
||||
_noneType => this.addNone(attributes),
|
||||
|
@ -260,9 +261,6 @@ export class TypeRefUnionAccumulator extends UnionAccumulator<TypeRef, TypeRef>
|
|||
_unionType => {
|
||||
return panic("The unions should have been eliminated in attributesForTypesInUnion");
|
||||
},
|
||||
_transformedType => {
|
||||
return panic("We don't support transformed types in unions yet");
|
||||
},
|
||||
_dateType => this.addStringType("date", attributes),
|
||||
_timeType => this.addStringType("time", attributes),
|
||||
_dateTimeType => this.addStringType("date-time", attributes)
|
||||
|
@ -312,11 +310,11 @@ export abstract class UnionBuilder<TBuilder extends TypeBuilder, TArrayData, TOb
|
|||
case "date":
|
||||
case "time":
|
||||
case "date-time":
|
||||
const t = this.typeBuilder.getPrimitiveType(kind, forwardingRef);
|
||||
const t = this.typeBuilder.getPrimitiveType(kind, undefined, forwardingRef);
|
||||
this.typeBuilder.addAttributes(t, typeAttributes);
|
||||
return t;
|
||||
case "string":
|
||||
return this.typeBuilder.getStringType(typeAttributes, undefined, forwardingRef);
|
||||
return this.typeBuilder.getStringType(typeAttributes, undefined, undefined, forwardingRef);
|
||||
case "enum":
|
||||
return this.makeEnum(typeProvider.enumCases, typeProvider.enumCaseMap, typeAttributes, forwardingRef);
|
||||
case "object":
|
||||
|
@ -357,7 +355,7 @@ export abstract class UnionBuilder<TBuilder extends TypeBuilder, TArrayData, TOb
|
|||
}
|
||||
|
||||
const union = unique
|
||||
? this.typeBuilder.getUniqueUnionType(typeAttributes, undefined, forwardingRef)
|
||||
? this.typeBuilder.getUniqueUnionType(typeAttributes, undefined, undefined, forwardingRef)
|
||||
: undefined;
|
||||
|
||||
const types: TypeRef[] = [];
|
||||
|
@ -369,7 +367,7 @@ export abstract class UnionBuilder<TBuilder extends TypeBuilder, TArrayData, TOb
|
|||
this.typeBuilder.setSetOperationMembers(union, typesSet);
|
||||
return union;
|
||||
} else {
|
||||
return this.typeBuilder.getUnionType(typeAttributes, typesSet, forwardingRef);
|
||||
return this.typeBuilder.getUnionType(typeAttributes, typesSet, undefined, forwardingRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче