Refactor
This commit is contained in:
Родитель
42787bbeb9
Коммит
fe9f931ad6
|
@ -8,6 +8,36 @@ import { assert, defined } from "./Support";
|
|||
import { TypeRef, GraphRewriteBuilder, StringTypeMapping } from "./TypeBuilder";
|
||||
import { unifyTypes, UnifyUnionBuilder } from "./UnifyClasses";
|
||||
|
||||
function makeGroupsToFlatten(
|
||||
unions: Set<UnionType>,
|
||||
include: ((members: OrderedSet<Type>) => boolean) | undefined
|
||||
): Type[][] {
|
||||
let singleTypeGroups = Map<Type, OrderedSet<Type>>();
|
||||
const groups: Type[][] = [];
|
||||
unions.forEach(u => {
|
||||
const members = setOperationMembersRecursively(u)[0];
|
||||
|
||||
if (include !== undefined) {
|
||||
if (!include(members)) return;
|
||||
}
|
||||
|
||||
if (members.size === 1) {
|
||||
const t = defined(members.first());
|
||||
let maybeSet = singleTypeGroups.get(t);
|
||||
if (maybeSet === undefined) {
|
||||
maybeSet = OrderedSet([t]);
|
||||
}
|
||||
maybeSet = maybeSet.add(u);
|
||||
singleTypeGroups = singleTypeGroups.set(t, maybeSet);
|
||||
} else {
|
||||
groups.push([u]);
|
||||
}
|
||||
});
|
||||
singleTypeGroups.forEach(ts => groups.push(ts.toArray()));
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
export function flattenUnions(
|
||||
graph: TypeGraph,
|
||||
stringTypeMapping: StringTypeMapping,
|
||||
|
@ -31,29 +61,21 @@ export function flattenUnions(
|
|||
|
||||
const allUnions = graph.allTypesUnordered().filter(t => t instanceof UnionType) as Set<UnionType>;
|
||||
const nonCanonicalUnions = allUnions.filter(u => !u.isCanonical);
|
||||
let singleTypeGroups = Map<Type, OrderedSet<Type>>();
|
||||
const groups: Type[][] = [];
|
||||
let foundIntersection: boolean = false;
|
||||
nonCanonicalUnions.forEach(u => {
|
||||
const members = setOperationMembersRecursively(u)[0];
|
||||
let foundIntersection = false;
|
||||
const groups = makeGroupsToFlatten(nonCanonicalUnions, members => {
|
||||
assert(!members.isEmpty(), "We can't have an empty union");
|
||||
if (members.some(m => m instanceof IntersectionType)) {
|
||||
foundIntersection = true;
|
||||
return;
|
||||
}
|
||||
if (members.size === 1) {
|
||||
const t = defined(members.first());
|
||||
let maybeSet = singleTypeGroups.get(t);
|
||||
if (maybeSet === undefined) {
|
||||
maybeSet = OrderedSet([t]);
|
||||
}
|
||||
maybeSet = maybeSet.add(u);
|
||||
singleTypeGroups = singleTypeGroups.set(t, maybeSet);
|
||||
} else {
|
||||
groups.push([u]);
|
||||
}
|
||||
if (!members.some(m => m instanceof IntersectionType)) return true;
|
||||
|
||||
// FIXME: This is stupid. `flattenUnions` returns true when no more union
|
||||
// flattening is necessary, but `resolveIntersections` can introduce new
|
||||
// unions that might require flattening, so now `flattenUnions` needs to take
|
||||
// that into account. Either change `resolveIntersections` such that it
|
||||
// doesn't introduce non-canonical unions (by using `unifyTypes`), or have
|
||||
// some other way to tell whether more work is needed that doesn't require
|
||||
// the two passes to know about each other.
|
||||
foundIntersection = true;
|
||||
return false;
|
||||
});
|
||||
singleTypeGroups.forEach(ts => groups.push(ts.toArray()));
|
||||
graph = graph.rewrite("flatten unions", stringTypeMapping, false, groups, replace);
|
||||
|
||||
// console.log(`flattened ${nonCanonicalUnions.size} of ${unions.size} unions`);
|
||||
|
|
Загрузка…
Ссылка в новой задаче