Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2 from JSMonk/master
Browse files Browse the repository at this point in the history
Get latest commits
  • Loading branch information
Kapelianovych authored Apr 25, 2020
2 parents 7215b9f + ac96e60 commit 510c686
Show file tree
Hide file tree
Showing 34 changed files with 391 additions and 257 deletions.
8 changes: 4 additions & 4 deletions packages/core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
"description": "",
"main": "index.js",
"scripts": {
"build": " npm run build:clean && npm run build:start && npm run build:copy",
"build:start": "babel src -d build",
"prebuild": "npm run build:clean",
"build": "babel src -d build",
"postbuild": "npm run build:copy",

"build:dev": "npm run build -- -s",

"build:copy": "cp ./package.json ./build/package.json && cp ./src/index.d.ts ./build/index.d.ts",
"build:clean": "rm -rf build && mkdir build",

"pretest": "npm run build",
"test": "jest"
},
"license": "MIT",
Expand All @@ -26,7 +32,7 @@
"babel-jest": "^25.1.0",
"babel-plugin-syntax-flow": "^6.18.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"flow-bin": "^0.94.0",
"flow-bin": "^0.123.0",
"jest": "^25.1.0"
}
}
6 changes: 3 additions & 3 deletions packages/core/src/checking/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type { CallableType } from "../type-graph/meta/call-meta";
import type { SourceLocation } from "@babel/parser";

function getActualType(
actual: ?Type | VariableInfo | Array<Type | VariableInfo>,
actual: ?Type | VariableInfo<Type> | Array<Type | VariableInfo<Type>>,
typeScope: TypeScope
) {
if (actual === undefined || actual === null) {
Expand All @@ -44,7 +44,7 @@ function isAssign(call: CallMeta) {
function isValidTypes(
targetName: mixed,
declaratedType: Type | RestArgument,
actual: ?Type | VariableInfo | Array<VariableInfo | Type>,
actual: ?Type | VariableInfo<Type> | Array<VariableInfo<Type> | Type>,
typeScope: TypeScope
): boolean {
let declaratedRootType =
Expand All @@ -71,7 +71,7 @@ function isValidTypes(
}
if (
declaratedRootType.onlyLiteral &&
!declaratedRootType.isNominal &&
!(declaratedRootType instanceof ObjectType && declaratedRootType.isNominal) &&
declaratedRootType !== ObjectType.Object &&
declaratedRootType !== ObjectType.Object.root &&
declaratedRootType !== FunctionType.Function &&
Expand Down
26 changes: 11 additions & 15 deletions packages/core/src/inference/equals-refinement.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,14 +206,9 @@ export function refinePropertyWithConstraint(
variableType: Type,
typeScope: TypeScope
): [?Type, ?Type] {
const refinementedType: Type = chaining.reduceRight((res: Type, property) => {
const propertiesForObjectType = [[property, new VariableInfo(res)]];
return ObjectType.term(
ObjectType.getName(propertiesForObjectType),
{},
propertiesForObjectType
);
}, refinementType);
const refinementedType: Type = chaining.reduceRight((res: Type, property) =>
createObjectWith(property, res, typeScope)
, refinementType);
return [refinementedType, variableType];
}

Expand Down Expand Up @@ -434,26 +429,27 @@ function equalsProperty(
if (refinmentedAndAlternate == undefined) {
return;
}
const [refinemented, alternate] = refinmentedAndAlternate;
if (
refinmentedAndAlternate[0] !== undefined &&
refinmentedAndAlternate[1] === undefined &&
refinemented != undefined &&
alternate == undefined &&
isSwitch
) {
return [variableName, refinmentedAndAlternate[0], Type.Never];
return [variableName, refinemented, Type.Never];
}
if (
refinmentedAndAlternate[0] == undefined ||
(refinmentedAndAlternate[1] == undefined && !isSwitch)
refinemented == undefined ||
(alternate == undefined && !isSwitch)
) {
const typeName = String(refinementType.name);
throw new HegelError(
`Property ${
refinmentedAndAlternate[0] === undefined ? "can't be" : "is always"
refinemented === undefined ? "can't be" : "is always"
} "${typeName}"`,
refinementNode.loc
);
}
return [variableName, refinmentedAndAlternate[0], refinmentedAndAlternate[1]];
return [variableName, refinemented, alternate || Type.Never];
}
export function equalsRefinement(
currentRefinementNode: Node,
Expand Down
25 changes: 16 additions & 9 deletions packages/core/src/inference/function-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export function inferenceFunctionLiteralType(
const isWithoutAnnotation = typeNode == undefined;
functionScope.body.set(
name,
new VariableInfo(paramType, localTypeScope, new Meta(param.loc))
new VariableInfo(paramType, functionScope, new Meta(param.loc))
);
if (param.left !== undefined) {
if (
Expand Down Expand Up @@ -201,7 +201,7 @@ export function inferenceFunctionLiteralType(
paramType = !isWithoutAnnotation
? paramType
: getVariableType(
new VariableInfo(paramType),
new VariableInfo(paramType, functionScope),
newType,
typeScope,
callResultType.inferenced
Expand Down Expand Up @@ -420,7 +420,7 @@ function resolveOuterTypeVarsFromCall(

export function implicitApplyGeneric(
fn: GenericType<FunctionType>,
argumentsTypes: Array<Type | VariableInfo>,
argumentsTypes: Array<Type | VariableInfo<Type>>,
localTypeScope: TypeScope,
loc: SourceLocation,
withClean?: boolean = true,
Expand Down Expand Up @@ -506,7 +506,11 @@ export function implicitApplyGeneric(
) {
unreachableTypes.add(resultType);
}
if (resultType === t && resultType.defaultType !== undefined) {
if (
resultType instanceof TypeVar &&
resultType === t &&
resultType.defaultType !== undefined
) {
return resultType.defaultType;
}
return resultType;
Expand Down Expand Up @@ -538,7 +542,7 @@ let iterator = 0;

export function getRawFunctionType(
fn: FunctionType | GenericType<FunctionType> | TypeVar,
args: Array<Type | VariableInfo>,
args: Array<Type | VariableInfo<Type>>,
genericArguments?: Array<Type> | null,
localTypeScope: TypeScope,
loc: SourceLocation,
Expand Down Expand Up @@ -594,7 +598,7 @@ export function getRawFunctionType(

export function getInvocationType(
fn: FunctionType | GenericType<FunctionType> | TypeVar,
argumentsTypes: Array<Type | VariableInfo>,
argumentsTypes: Array<Type | VariableInfo<Type>>,
genericArguments?: Array<Type> | null,
localTypeScope: TypeScope,
loc: SourceLocation,
Expand Down Expand Up @@ -626,7 +630,7 @@ export function getInvocationType(
: returnType;
}

export function clearRoot(type: Type) {
export function clearRoot(type: TypeVar) {
type.root = undefined;
}

Expand Down Expand Up @@ -724,13 +728,16 @@ export function inferenceFunctionTypeByScope(
returnType instanceof TypeVar &&
!returnType.isUserDefined
) {
const variants = returnType.root !== undefined
? [Type.getTypeRoot(returnType)]
: [];
returnType.root = UnionType.term(
null,
{},
[
returnType.root,
...variants,
isAsync ? Type.Undefined.promisify() : Type.Undefined
].filter(a => a !== undefined)
]
);
}
const created: Map<TypeVar, TypeVar> = new Map();
Expand Down
21 changes: 11 additions & 10 deletions packages/core/src/inference/in-operator.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function inIdentifier(
targetNode.name,
ObjectType.term(null, { isSoft: true }, [
...type.properties,
[propertyName, new VariableInfo(Type.Unknown)]
[propertyName, new VariableInfo(Type.Unknown, currentScope)]
]),
type
];
Expand All @@ -91,36 +91,37 @@ function refinementProperty(
if (property === undefined) {
return;
}
const propertyType = property.type;
if (isLast) {
if (
!(property.type instanceof UnionType) &&
!(property.type instanceof ObjectType)
!(propertyType instanceof UnionType) &&
!(propertyType instanceof ObjectType)
) {
throw new HegelError(
`Property has not "${propertyName}" property`,
refinementNode.loc
);
}
if (property.type instanceof ObjectType) {
const existed = property.type.getPropertyType(propertyName);
if (!property.type.isStrict && !existed) {
if (propertyType instanceof ObjectType) {
const existed = propertyType.getPropertyType(propertyName);
if (!propertyType.isStrict && !existed) {
return [
mergeObjectsTypes(
property.type,
propertyType,
createObjectWith(propertyName, Type.Unknown, typeScope),
typeScope
),
property.type
];
}
return existed
? [property.type, undefined]
: [undefined, property.type];
? [propertyType, undefined]
: [undefined, propertyType];
}
const [
refinementedVariants,
alternateVariants
] = property.type.variants.reduce(
] = propertyType.variants.reduce(
([refinementedVariants, alternateVariants], variant) =>
variant instanceof ObjectType && variant.getPropertyType(propertyName)
? [refinementedVariants.concat([variant]), alternateVariants]
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/inference/refinement.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ function intersectionOfTypes(
if (type1 instanceof UnionType || type2 instanceof UnionType) {
// $FlowIssue
const [unionType, notUnion]: [UnionType, Type] =
// $FlowIssue
type1 instanceof UnionType ? [type1, type2] : [type2, type1];
// $FlowIssue
const isTypeExisting = unionType.variants.some(t => t.equalsTo(notUnion));
return isTypeExisting ? notUnion : Type.Never;
}
Expand Down Expand Up @@ -309,6 +309,9 @@ function refinementByCondition(
const previousCaseScope = moduleScope.scopes.get(
VariableScope.getName(previousCase.consequent)
);
if (previousCaseScope === undefined) {
throw new Error("Never!!!");
}
const previousPrimaryRefinement = previousCaseScope.body.get(name);
if (previousPrimaryRefinement === undefined) {
return;
Expand Down Expand Up @@ -492,15 +495,15 @@ export function refinement(
!primaryScope.body.has(varName) ||
condition.type === NODE.SWITCH_CASE
) {
primaryScope.body.set(varName, new VariableInfo(refinementedType));
primaryScope.body.set(varName, new VariableInfo(refinementedType, currentScope));
}
if (alternateType && alternateScopes) {
alternateScopes.forEach(alternateScope => {
if (
!alternateScope.body.has(varName) ||
condition.type === NODE.SWITCH_CASE
) {
alternateScope.body.set(varName, new VariableInfo(alternateType));
alternateScope.body.set(varName, new VariableInfo(alternateType, currentScope));
}
});
}
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/inference/switch-refinement.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import HegelError from "../utils/errors";
import { UnionType } from "../type-graph/types/union-type";
import { VariableInfo } from "../type-graph/variable-info";
import { addCallToTypeGraph } from "../type-graph/call";
import type { Handler } from "../utils/traverse";
import type { SwitchStatement } from "@babel/parser";
import type { VariableScope } from "../type-graph/variable-scope";
import type { ModuleScope, PositionedModuleScope } from "../type-graph/module-scope";

export function findUnhandledCases(
node: SwitchStatement,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/inference/typeof.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function isReturnTypeOfTypeof(node: Node) {
function getTypeofAndLiteral(
left: Node,
right: Node,
typeofOperator: VariableInfo
typeofOperator: VariableInfo<Type>
): ?{ typeofNode: Node, stringNode: Node } {
let typeofNode: ?Node = null;
if (isTypeofOperator(left)) {
Expand Down
Loading

0 comments on commit 510c686

Please sign in to comment.