This commit is contained in:
Mark Probst 2018-03-29 09:16:43 -07:00
Родитель 51737eb68b
Коммит 42787bbeb9
3 изменённых файлов: 35 добавлений и 44 удалений

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

@ -3,31 +3,11 @@
import { Set, Map, OrderedSet } from "immutable";
import { TypeGraph } from "./TypeGraph";
import { Type, UnionType, IntersectionType } from "./Type";
import { Type, UnionType, IntersectionType, setOperationMembersRecursively } from "./Type";
import { assert, defined } from "./Support";
import { TypeRef, GraphRewriteBuilder, StringTypeMapping } from "./TypeBuilder";
import { unifyTypes, UnifyUnionBuilder } from "./UnifyClasses";
function unionMembersRecursively(union: UnionType): OrderedSet<Type> {
let processedUnions = Set<UnionType>();
let members = OrderedSet<Type>();
function addMembers(u: UnionType): void {
if (processedUnions.has(u)) return;
processedUnions = processedUnions.add(u);
u.members.forEach(t => {
if (t instanceof UnionType) {
addMembers(t);
} else {
members = members.add(t);
}
});
}
addMembers(union);
return members;
}
export function flattenUnions(
graph: TypeGraph,
stringTypeMapping: StringTypeMapping,
@ -55,7 +35,7 @@ export function flattenUnions(
const groups: Type[][] = [];
let foundIntersection: boolean = false;
nonCanonicalUnions.forEach(u => {
const members = unionMembersRecursively(u);
const members = setOperationMembersRecursively(u)[0];
assert(!members.isEmpty(), "We can't have an empty union");
if (members.some(m => m instanceof IntersectionType)) {
foundIntersection = true;

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

@ -30,7 +30,8 @@ import {
GenericClassProperty,
TypeKind,
combineTypeAttributesOfTypes,
ObjectType
ObjectType,
setOperationMembersRecursively
} from "./Type";
import { assert, defined, panic } from "./Support";
import {
@ -40,25 +41,8 @@ import {
makeTypeAttributesInferred
} from "./TypeAttributes";
function intersectionMembersRecursively(intersection: IntersectionType): [OrderedSet<Type>, TypeAttributes] {
const types: Type[] = [];
let attributes = emptyTypeAttributes;
function process(t: Type): void {
if (t instanceof IntersectionType) {
attributes = combineTypeAttributes(attributes, t.getAttributes());
t.members.forEach(process);
} else if (t.kind !== "any") {
types.push(t);
} else {
attributes = combineTypeAttributes(attributes, t.getAttributes());
}
}
process(intersection);
return [OrderedSet(types), attributes];
}
function canResolve(t: IntersectionType): boolean {
const members = intersectionMembersRecursively(t)[0];
const members = setOperationMembersRecursively(t)[0];
if (members.size <= 1) return true;
return members.every(m => !(m instanceof UnionType) || m.isCanonical);
}
@ -236,7 +220,7 @@ class IntersectionAccumulator
return panic("There shouldn't be a none type");
},
_anyType => {
return panic("The any type should have been filtered out in intersectionMembersRecursively");
return panic("The any type should have been filtered out in setOperationMembersRecursively");
},
nullType => this.addUnionSet(OrderedSet([nullType])),
boolType => this.addUnionSet(OrderedSet([boolType])),
@ -416,7 +400,7 @@ export function resolveIntersections(graph: TypeGraph, stringTypeMapping: String
forwardingRef: TypeRef
): TypeRef {
assert(types.size === 1);
const [members, intersectionAttributes] = intersectionMembersRecursively(defined(types.first()));
const [members, intersectionAttributes] = setOperationMembersRecursively(defined(types.first()));
if (members.isEmpty()) {
const t = builder.getPrimitiveType("any", forwardingRef);
builder.addAttributes(t, intersectionAttributes);

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

@ -5,7 +5,7 @@ import { OrderedSet, OrderedMap, Collection, Set, is, hash } from "immutable";
import { defined, panic, assert, assertNever } from "./Support";
import { TypeRef, TypeReconstituter } from "./TypeBuilder";
import { TypeNames, namesTypeAttributeKind } from "./TypeNames";
import { TypeAttributes, combineTypeAttributes } from "./TypeAttributes";
import { TypeAttributes, combineTypeAttributes, emptyTypeAttributes } from "./TypeAttributes";
export type PrimitiveStringTypeKind = "string" | "date" | "time" | "date-time";
export type PrimitiveTypeKind = "none" | "any" | "null" | "bool" | "integer" | "double" | PrimitiveStringTypeKind;
@ -568,6 +568,33 @@ export class UnionType extends SetOperationType {
}
}
export function setOperationMembersRecursively<T extends SetOperationType>(
setOperation: T
): [OrderedSet<Type>, TypeAttributes] {
const kind = setOperation.kind;
const includeAny = kind !== "intersection";
let processedSetOperations = Set<T>();
let members = OrderedSet<Type>();
let attributes = emptyTypeAttributes;
function process(t: Type): void {
if (t.kind === kind) {
const so = t as T;
if (processedSetOperations.has(so)) return;
processedSetOperations = processedSetOperations.add(so);
attributes = combineTypeAttributes(attributes, t.getAttributes());
so.members.forEach(process);
} else if (includeAny || t.kind !== "any") {
members = members.add(t);
} else {
attributes = combineTypeAttributes(attributes, t.getAttributes());
}
}
process(setOperation);
return [members, attributes];
}
export function combineTypeAttributesOfTypes(types: Collection<any, Type>): TypeAttributes {
return combineTypeAttributes(
types