Skip to content

Commit

Permalink
Merge branch 'master' into annotate-standard-exceptions-indexec-colle…
Browse files Browse the repository at this point in the history
…ctions
  • Loading branch information
Demetri0 committed May 6, 2020
2 parents 30b9f29 + 96e3b7d commit d9af6d4
Show file tree
Hide file tree
Showing 20 changed files with 220 additions and 101 deletions.
18 changes: 13 additions & 5 deletions packages/core/src/inference/function-type.js
Expand Up @@ -388,7 +388,9 @@ function resolveOuterTypeVarsFromCall(
actualType = Type.getTypeRoot(actualType, true);
declaratedType = Type.getTypeRoot(declaratedType);
// $FlowIssue
const difference = declaratedType.getDifference(actualType, true);
let difference = declaratedType.parent.priority > actualType.parent.priority
? actualType.getDifference(declaratedType, true)
: declaratedType.getDifference(actualType, true);
for (let j = 0; j < difference.length; j++) {
let { root, variable } = difference[j];
if (TypeVar.isSelf(root)) {
Expand Down Expand Up @@ -513,7 +515,7 @@ export function implicitApplyGeneric(
resultType === t &&
resultType.defaultType !== undefined
) {
return resultType.defaultType;
return rootFinder(resultType.defaultType) || Type.getTypeRoot(resultType.defaultType);
}
return resultType;
});
Expand Down Expand Up @@ -580,7 +582,7 @@ export function getRawFunctionType(
fn.root = result;
return result;
}
const result =
let result =
genericArguments != null
? // $FlowIssue
fn.applyGeneric(genericArguments, loc, true, false, initializing)
Expand All @@ -592,8 +594,14 @@ export function getRawFunctionType(
withClean,
dropUnknown
);
if (result instanceof $BottomType) {
result = result.unpack();
}
if (result instanceof $BottomType) {
result = result.subordinateMagicType;
}
if (result instanceof GenericType) {
return result.subordinateType;
result = result.subordinateType;
}
return result;
}
Expand Down Expand Up @@ -707,7 +715,7 @@ export function inferenceFunctionTypeByScope(
continue;
}
const oldRoot = Type.getTypeRoot(returnType);
if (returnType.root === undefined) {
if (returnType.root === undefined || newOneRoot.isPrincipalTypeFor(oldRoot)) {
returnType.root = newOneRoot;
} else if (!oldRoot.isPrincipalTypeFor(newOneRoot)) {
const variants: any = (oldRoot instanceof UnionType
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/inference/refinement.js
Expand Up @@ -198,7 +198,7 @@ function intersectionOfTypes(
(a, b) => a.equalsTo(b)
)[0];
return UnionType.term(
UnionType.getName(intersectedVariants),
null,
{},
intersectedVariants
);
Expand All @@ -219,7 +219,7 @@ function unionOfTypes(type1: Type, type2: Type, typeScope: TypeScope): Type {
const unionVariants = union(type1.variants, type2.variants, (a, b) =>
a.equalsTo(b)
);
return UnionType.term(UnionType.getName(unionVariants), {}, unionVariants);
return UnionType.term(null, {}, unionVariants);
}
if (type1 instanceof UnionType || type2 instanceof UnionType) {
const [unionType, notUnion]: [Type, Type] =
Expand All @@ -230,7 +230,7 @@ function unionOfTypes(type1: Type, type2: Type, typeScope: TypeScope): Type {
[notUnion],
(a, b) => a.equalsTo(b)
);
return UnionType.term(UnionType.getName(newVariants), {}, newVariants);
return UnionType.term(null, {}, newVariants);
}
if (type1.isPrincipalTypeFor(type2)) {
return type1;
Expand All @@ -239,7 +239,7 @@ function unionOfTypes(type1: Type, type2: Type, typeScope: TypeScope): Type {
return type2;
}
const variants = [type1, type2];
return UnionType.term(UnionType.getName(variants), {}, variants);
return UnionType.term(null, {}, variants);
}

function getRefinementByBinaryExpression(
Expand Down
50 changes: 30 additions & 20 deletions packages/core/src/type-graph/call.js
Expand Up @@ -786,14 +786,40 @@ export function addCallToTypeGraph(
targetType =
/*::target.type !== undefined ?*/ target.type /*:: : targetType*/;
}
let fnType =
targetType instanceof GenericType
? targetType.subordinateType
: targetType;
genericArguments =
node.typeArguments &&
node.typeArguments.params.map(arg =>
getTypeFromTypeAnnotation(
{ typeAnnotation: arg },
typeScope,
currentScope,
false,
null,
parentNode,
moduleScope,
pre,
middle,
post
)
);
const localTypeScope =
targetType instanceof GenericType
? targetType.localTypeScope
: typeScope;
if (targetType instanceof GenericType && genericArguments != null) {
targetType = getRawFunctionType(
// $FlowIssue
targetType,
[],
genericArguments,
localTypeScope,
node.loc
);
}
let fnType =
targetType instanceof GenericType
? targetType.subordinateType
: targetType;
if (
fnType != undefined &&
!(fnType instanceof FunctionType) &&
Expand Down Expand Up @@ -826,22 +852,6 @@ export function addCallToTypeGraph(
{ ...meta, isImmutable: defaultArg instanceof $AppliedImmutable }
).result;
});
genericArguments =
node.typeArguments &&
node.typeArguments.params.map(arg =>
getTypeFromTypeAnnotation(
{ typeAnnotation: arg },
typeScope,
currentScope,
false,
null,
parentNode,
moduleScope,
pre,
middle,
post
)
);
targetType.asNotUserDefined();
args = node.arguments.map((n, i) => {
if (
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/type-graph/type-graph.js
Expand Up @@ -855,7 +855,7 @@ export async function createModuleScope(
throw e;
}
if (Array.isArray(e)) {
errors.push(...e.map(e => Object.assign(e, { path: file.path })));
errors.push(...e.map(e => Object.assign(e, { source: file.path })));
} else {
e.source = file.path;
errors.push(e);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/type-graph/type-scope.js
Expand Up @@ -7,7 +7,7 @@ import type { Node, TSInterfaceDeclaration } from "@babel/core";

export class TypeScope {
static GLOBAL_SCOPE_PRIORITY = 0;
static MODULE_SCOPE_PRIORITY = 0;
static MODULE_SCOPE_PRIORITY = 1;

priority: number;
parent: TypeScope | null;
Expand Down
26 changes: 17 additions & 9 deletions packages/core/src/type-graph/types/bottom-type.js
@@ -1,6 +1,7 @@
import { Type } from "./type";
import { TypeVar } from "./type-var";
import { UnionType } from "./union-type";
import { TypeScope } from "../type-scope";
import { FunctionType } from "./function-type";

export class $BottomType extends Type {
Expand Down Expand Up @@ -106,12 +107,10 @@ export class $BottomType extends Type {
}
if (argument instanceof UnionType) {
const newType = argument.changeAll(sourceTypes, targetTypes, typeScope);
const result = argument.variants
.map(mapper)
.filter(a => a !== undefined);
return result.length > 1 && newType.parent.priority <= 1
? newType
: result[0];
if (newType.parent.priority > TypeScope. MODULE_SCOPE_PRIORITY) {
includedTypeVar = true;
}
return newType;
}
return argument;
};
Expand Down Expand Up @@ -167,10 +166,19 @@ export class $BottomType extends Type {
? Type.getTypeRoot(this.subordinateMagicType)
: this.subordinateMagicType;
if ("subordinateType" in target) {
const parameters = this.genericArguments.map(
t => {
if (t instanceof $BottomType) {
t = t.unpack();
}
if (t instanceof TypeVar && t.root !== undefined) {
t = Type.getTypeRoot(t);
}
return t;
}
);
return target.applyGeneric(
this.genericArguments.map(
a => (a instanceof TypeVar && a.root != undefined ? a.root : a)
),
parameters,
this.loc,
true,
true,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/type-graph/types/collection-type.js
Expand Up @@ -67,7 +67,7 @@ export class CollectionType<K: Type, V: Type> extends Type {
this.valueType.variants.some(a => a.equalsTo(Type.Undefined))
? this.valueType
: UnionType.term(
UnionType.getName([this.valueType, Type.Undefined]),
null,
{},
[this.valueType, Type.Undefined]
);
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/type-graph/types/immutable-type.js
Expand Up @@ -80,6 +80,10 @@ export class $AppliedImmutable extends Type {
weakContains(type) {
return this.readonly.contains(type);
}

getDifference(type: Type, withReverseUnion?: boolean = false) {
return this.readonly.getDifference(type, withReverseUnion);
}

changeAll(...args) {
const changed = this.readonly.changeAll(...args);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/type-graph/types/keys-type.js
Expand Up @@ -69,6 +69,6 @@ export class $Keys extends GenericType {
variants.push(Type.term(`'${property}'`, { isSubtypeOf: Type.String }));
}
}
return UnionType.term(UnionType.getName(variants), {}, variants);
return UnionType.term(null, {}, variants);
}
}
2 changes: 1 addition & 1 deletion packages/core/src/type-graph/types/partial-type.js
Expand Up @@ -52,7 +52,7 @@ export class $Partial extends GenericType {
? property.type.variants
: [property.type])
];
const newType = UnionType.term(UnionType.getName(variants), {}, variants);
const newType = UnionType.term(null, {}, variants);
return [name, new VariableInfo(newType, property.parent, property.meta)];
});
return ObjectType.term(
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/type-graph/types/property-type.js
Expand Up @@ -158,7 +158,7 @@ export class $PropertyType extends GenericType {
isCalledAsBottom
)
);
return UnionType.term(UnionType.getName(variants), {}, variants);
return UnionType.term(null, {}, variants);
} catch {
throw new HegelError(
`Property "${propertyName}" does not exist in "${
Expand All @@ -178,7 +178,7 @@ export class $PropertyType extends GenericType {
isCalledAsBottom
)
);
return UnionType.term(UnionType.getName(variants), {}, variants);
return UnionType.term(null, {}, variants);
} catch {
throw new HegelError(
`Property "${propertyName}" does not exist in "${
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/type-graph/types/type.js
Expand Up @@ -192,6 +192,9 @@ export class Type {
if (this.referenceEqualsTo(type)) {
return [];
}
if ("readonly" in type) {
type = type.readonly;
}
if ("variants" in type) {
// $FlowIssue
const variants = [...type.variants].sort(
Expand Down
60 changes: 39 additions & 21 deletions packages/core/src/type-graph/types/union-type.js
@@ -1,9 +1,9 @@
// @flow
import { Type } from "./type";
import { unique } from "../../utils/common";
import { TypeVar } from "./type-var";
import type { TypeMeta } from "./type";
import type { TypeScope } from "../type-scope";
import type { $BottomType } from "./bottom-type";

// $FlowIssue
export class UnionType extends Type {
Expand All @@ -18,9 +18,9 @@ export class UnionType extends Type {
...args: Array<any>
) {
variants = UnionType.flatten(variants);
const principalTypeInside = UnionType.getPrincipalTypeInside(variants);
if (principalTypeInside !== undefined) {
return principalTypeInside;
variants = UnionType.rollup(variants);
if (variants.length === 1) {
return variants[0];
}
name = name == null ? UnionType.getName(variants) : name;
let parent: TypeScope | void = meta.parent;
Expand All @@ -38,18 +38,7 @@ export class UnionType extends Type {
return super.term(name, newMeta, variants, ...args);
}

static getPrincipalTypeInside(variants: any) {
return variants.length === 1
? variants[0]
: variants.find(
variant =>
!(variant instanceof TypeVar) &&
variants.every(subVariant => variant.equalsTo(subVariant))
);
}

static getName(params: Array<Type>) {
params = unique(params.map(a => Type.getTypeRoot(a)), a => String(a.name));
const isMultyLine = this.prettyMode && params.length >= 4;
return `${params
.sort((t1, t2) => String(t1.name).localeCompare(String(t2.name)))
Expand Down Expand Up @@ -82,21 +71,50 @@ export class UnionType extends Type {
variant =>
variant instanceof UnionType
? this.flatten(variant.variants)
: [variant]
: [Type.getTypeRoot(variant)]
);
}

static shouldBeSkipped(variant: $BottomType | Type) {
return "subordinateMagicType" in variant || variant instanceof TypeVar || variant === Type.Unknown;
}

static uniqueVariants(set: Array<Type>) {
const unique: Array<Type> = [];
for (let i = 0; i < set.length; i++) {
const currentType = set[i];
if (
this.shouldBeSkipped(currentType) ||
!unique.some(
existed =>
!this.shouldBeSkipped(existed) &&
existed.isPrincipalTypeFor(currentType)
)
) {
unique.push(currentType);
}
}
return unique;
}

static rollup(variants: any) {
return variants.length === 1
? [variants[0]]
: this.uniqueVariants(variants);
}


variants: Array<Type>;

constructor(name: ?string, meta?: TypeMeta = {}, variants: Array<Type>) {
variants = UnionType.flatten(variants);
variants = UnionType.rollup(variants);
if (variants.length === 1) {
return variants[0];
}
name = name == null ? UnionType.getName(variants) : name;
super(name, meta);
const principalTypeInside = UnionType.getPrincipalTypeInside(variants);
if (principalTypeInside) {
return principalTypeInside;
}
this.variants = unique(variants, a => String(a.name)).sort((t1, t2) =>
this.variants = variants.sort((t1, t2) =>
String(t1.name).localeCompare(String(t2.name))
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/type-graph/types/values-type.js
Expand Up @@ -54,6 +54,6 @@ export class $Values extends GenericType {
}
const values = [...realTarget.properties.values()];
const variants = values.map(value => value.type);
return UnionType.term(UnionType.getName(variants), {}, variants);
return UnionType.term(null, {}, variants);
}
}

0 comments on commit d9af6d4

Please sign in to comment.