Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint

This commit is contained in:
Alexander T
2019-08-20 11:07:18 +03:00
90 changed files with 1830 additions and 414 deletions

View File

@@ -227,7 +227,7 @@ namespace ts {
symbol.flags |= symbolFlags;
node.symbol = symbol;
symbol.declarations = append(symbol.declarations, node);
symbol.declarations = appendIfUnique(symbol.declarations, node);
if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) && !symbol.exports) {
symbol.exports = createSymbolTable();
@@ -737,6 +737,9 @@ namespace ts {
case SyntaxKind.JSDocEnumTag:
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
break;
case SyntaxKind.JSDocClassTag:
bindJSDocClassTag(node as JSDocClassTag);
break;
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
case SyntaxKind.SourceFile: {
bindEachFunctionsFirst((node as SourceFile).statements);
@@ -1446,6 +1449,14 @@ namespace ts {
}
}
function bindJSDocClassTag(node: JSDocClassTag) {
bindEachChild(node);
const host = getHostSignatureFromJSDoc(node);
if (host && host.kind !== SyntaxKind.MethodDeclaration) {
addDeclarationToSymbol(host.symbol, host, SymbolFlags.Class);
}
}
function bindCallExpressionFlow(node: CallExpression) {
// If the target of the call expression is a function expression or arrow function we have
// an immediately invoked function expression (IIFE). Initialize the flowNode property to
@@ -1813,7 +1824,8 @@ namespace ts {
// typedef anchored to an A.B.C assignment - we need to bind into B's namespace under name C
const isTopLevel = isTopLevelNamespaceAssignment(declName.parent);
if (isTopLevel) {
bindPotentiallyMissingNamespaces(file.symbol, declName.parent, isTopLevel, !!findAncestor(declName, d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype"));
bindPotentiallyMissingNamespaces(file.symbol, declName.parent, isTopLevel,
!!findAncestor(declName, d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype"), /*containerIsClass*/ false);
const oldContainer = container;
container = isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name : declName.parent.expression;
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
@@ -2510,6 +2522,7 @@ namespace ts {
constructorSymbol.members = constructorSymbol.members || createSymbolTable();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class);
}
break;
@@ -2558,7 +2571,7 @@ namespace ts {
node.left.parent = node;
node.right.parent = node;
const lhs = node.left as PropertyAccessEntityNameExpression;
bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false);
bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false, /*containerIsClass*/ true);
}
function bindObjectDefinePrototypeProperty(node: BindableObjectDefinePropertyCall) {
@@ -2581,13 +2594,13 @@ namespace ts {
constructorFunction.parent = classPrototype;
classPrototype.parent = lhs;
bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true);
bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true, /*containerIsClass*/ true);
}
function bindObjectDefinePropertyAssignment(node: BindableObjectDefinePropertyCall) {
let namespaceSymbol = lookupSymbolForPropertyAccess(node.arguments[0]);
const isToplevel = node.parent.parent.kind === SyntaxKind.SourceFile;
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, node.arguments[0], isToplevel, /*isPrototypeProperty*/ false);
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, node.arguments[0], isToplevel, /*isPrototypeProperty*/ false, /*containerIsClass*/ false);
bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ false);
}
@@ -2618,10 +2631,10 @@ namespace ts {
*/
function bindStaticPropertyAssignment(node: PropertyAccessEntityNameExpression) {
node.expression.parent = node;
bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false);
bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false, /*containerIsClass*/ false);
}
function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: EntityNameExpression, isToplevel: boolean, isPrototypeProperty: boolean) {
function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: EntityNameExpression, isToplevel: boolean, isPrototypeProperty: boolean, containerIsClass: boolean) {
if (isToplevel && !isPrototypeProperty) {
// make symbols or add declarations for intermediate containers
const flags = SymbolFlags.Module | SymbolFlags.Assignment;
@@ -2638,6 +2651,9 @@ namespace ts {
}
});
}
if (containerIsClass && namespaceSymbol) {
addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, SymbolFlags.Class);
}
return namespaceSymbol;
}
@@ -2663,10 +2679,10 @@ namespace ts {
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
}
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) {
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean, containerIsClass: boolean) {
let namespaceSymbol = lookupSymbolForPropertyAccess(name);
const isToplevel = isTopLevelNamespaceAssignment(propertyAccess);
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty);
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass);
bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty);
}

View File

@@ -2038,12 +2038,16 @@ namespace ts {
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum));
if (result.flags & (SymbolFlags.Function | SymbolFlags.FunctionScopedVariable | SymbolFlags.Assignment) && result.flags & SymbolFlags.Class) {
// constructor functions aren't block scoped
return;
}
// Block-scoped variables cannot be used before their definition
const declaration = find(
result.declarations,
d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration));
if (declaration === undefined) return Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined");
if (declaration === undefined) return Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration");
if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) {
let diagnosticMessage;
@@ -3522,8 +3526,8 @@ namespace ts {
}
function getTypeNamesForErrorDisplay(left: Type, right: Type): [string, string] {
let leftStr = typeToString(left);
let rightStr = typeToString(right);
let leftStr = symbolValueDeclarationIsContextSensitive(left.symbol) ? typeToString(left, left.symbol.valueDeclaration) : typeToString(left);
let rightStr = symbolValueDeclarationIsContextSensitive(right.symbol) ? typeToString(right, right.symbol.valueDeclaration) : typeToString(right);
if (leftStr === rightStr) {
leftStr = typeToString(left, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
rightStr = typeToString(right, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
@@ -3531,6 +3535,10 @@ namespace ts {
return [leftStr, rightStr];
}
function symbolValueDeclarationIsContextSensitive(symbol: Symbol): boolean {
return symbol && symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !isContextSensitive(symbol.valueDeclaration);
}
function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags {
return flags & TypeFormatFlags.NodeBuilderFlagsMask;
}
@@ -3804,7 +3812,7 @@ namespace ts {
id = (isConstructorObject ? "+" : "") + getSymbolId(symbol);
if (isJSConstructor(symbol.valueDeclaration)) {
// Instance and static types share the same symbol; only add 'typeof' for the static side.
const isInstanceType = type === getInferredClassType(symbol) ? SymbolFlags.Type : SymbolFlags.Value;
const isInstanceType = type === getDeclaredTypeOfClassOrInterface(symbol) ? SymbolFlags.Type : SymbolFlags.Value;
return symbolToTypeNode(symbol, context, isInstanceType);
}
// Always use 'typeof T' for type of class, enum, and module objects
@@ -5969,19 +5977,10 @@ namespace ts {
if (!links.type) {
const jsDeclaration = getDeclarationOfExpando(symbol.valueDeclaration);
if (jsDeclaration) {
const jsSymbol = getSymbolOfNode(jsDeclaration);
if (jsSymbol && (hasEntries(jsSymbol.exports) || hasEntries(jsSymbol.members))) {
symbol = cloneSymbol(symbol);
const merged = mergeJSSymbols(symbol, getSymbolOfNode(jsDeclaration));
if (merged) {
// note:we overwrite links because we just cloned the symbol
links = symbol as TransientSymbol;
if (hasEntries(jsSymbol.exports)) {
symbol.exports = symbol.exports || createSymbolTable();
mergeSymbolTable(symbol.exports, jsSymbol.exports);
}
if (hasEntries(jsSymbol.members)) {
symbol.members = symbol.members || createSymbolTable();
mergeSymbolTable(symbol.members, jsSymbol.members);
}
symbol = links = merged;
}
}
originalLinks.type = links.type = getTypeOfFuncClassEnumModuleWorker(symbol);
@@ -6156,6 +6155,16 @@ namespace ts {
function getOuterTypeParameters(node: Node, includeThisTypes?: boolean): TypeParameter[] | undefined {
while (true) {
node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead
if (node && isBinaryExpression(node)) {
// prototype assignments get the outer type parameters of their constructor function
const assignmentKind = getAssignmentDeclarationKind(node);
if (assignmentKind === AssignmentDeclarationKind.Prototype || assignmentKind === AssignmentDeclarationKind.PrototypeProperty) {
const symbol = getSymbolOfNode(node.left);
if (symbol && symbol.parent && !findAncestor(symbol.parent.valueDeclaration, d => node === d)) {
node = symbol.parent.valueDeclaration;
}
}
}
if (!node) {
return undefined;
}
@@ -6189,7 +6198,7 @@ namespace ts {
}
const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>node));
const thisType = includeThisTypes &&
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration) &&
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType;
return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
}
@@ -6210,6 +6219,7 @@ namespace ts {
if (node.kind === SyntaxKind.InterfaceDeclaration ||
node.kind === SyntaxKind.ClassDeclaration ||
node.kind === SyntaxKind.ClassExpression ||
isJSConstructor(node) ||
isTypeAlias(node)) {
const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag>node;
result = appendTypeParameters(result, getEffectiveTypeParameterDeclarations(declaration));
@@ -6243,7 +6253,7 @@ namespace ts {
const constraint = getBaseConstraintOfType(type);
return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint);
}
return isJSConstructorType(type);
return false;
}
function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined {
@@ -6345,9 +6355,7 @@ namespace ts {
const baseTypeNode = getBaseTypeNodeOfClass(type)!;
const typeArgs = typeArgumentsFromTypeReferenceNode(baseTypeNode);
let baseType: Type;
const originalBaseType = isJSConstructorType(baseConstructorType) ? baseConstructorType :
baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) :
undefined;
const originalBaseType = baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined;
if (baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class &&
areAllOuterTypeParametersApplied(originalBaseType!)) {
// When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the
@@ -6358,9 +6366,6 @@ namespace ts {
else if (baseConstructorType.flags & TypeFlags.Any) {
baseType = baseConstructorType;
}
else if (isJSConstructorType(baseConstructorType)) {
baseType = !baseTypeNode.typeArguments && getJSClassType(baseConstructorType.symbol) || anyType;
}
else {
// The class derives from a "class-like" constructor function, check that we have at least one construct signature
// with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere
@@ -6473,10 +6478,17 @@ namespace ts {
}
function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType {
const links = getSymbolLinks(symbol);
let links = getSymbolLinks(symbol);
const originalLinks = links;
if (!links.declaredType) {
const kind = symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface;
const type = links.declaredType = <InterfaceType>createObjectType(kind, symbol);
const merged = mergeJSSymbols(symbol, getAssignedClassSymbol(symbol.valueDeclaration));
if (merged) {
// note:we overwrite links because we just cloned the symbol
symbol = links = merged;
}
const type = originalLinks.declaredType = links.declaredType = <InterfaceType>createObjectType(kind, symbol);
const outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol);
const localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
// A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type
@@ -7447,7 +7459,7 @@ namespace ts {
* Converts an AnonymousType to a ResolvedType.
*/
function resolveAnonymousTypeMembers(type: AnonymousType) {
const symbol = type.symbol;
const symbol = getMergedSymbol(type.symbol);
if (type.target) {
setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper!, /*mappingThisOnly*/ false);
@@ -7503,12 +7515,18 @@ namespace ts {
// will never be observed because a qualified name can't reference signatures.
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
type.callSignatures = getSignaturesOfSymbol(symbol);
type.constructSignatures = filter(type.callSignatures, sig => isJSConstructor(sig.declaration));
}
// And likewise for construct signatures for classes
if (symbol.flags & SymbolFlags.Class) {
const classType = getDeclaredTypeOfClassOrInterface(symbol);
let constructSignatures = getSignaturesOfSymbol(symbol.members!.get(InternalSymbolName.Constructor));
let constructSignatures = symbol.members ? getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)) : emptyArray;
if (symbol.flags & SymbolFlags.Function) {
constructSignatures = addRange(constructSignatures.slice(), mapDefined(
type.callSignatures,
sig => isJSConstructor(sig.declaration) ?
createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes) :
undefined));
}
if (!constructSignatures.length) {
constructSignatures = getDefaultConstructSignatures(classType);
}
@@ -8743,7 +8761,6 @@ namespace ts {
let type = signature.target ? instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper) :
signature.unionSignatures ? getUnionType(map(signature.unionSignatures, getReturnTypeOfSignature), UnionReduction.Subtype) :
getReturnTypeFromAnnotation(signature.declaration!) ||
isJSConstructor(signature.declaration) && getJSClassType(getSymbolOfNode(signature.declaration!)) ||
(nodeIsMissing((<FunctionLikeDeclaration>signature.declaration).body) ? anyType : getReturnTypeFromBody(<FunctionLikeDeclaration>signature.declaration));
if (!popTypeResolution()) {
if (signature.declaration) {
@@ -9165,12 +9182,12 @@ namespace ts {
return undefined;
}
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName | undefined, meaning: SymbolFlags) {
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName | undefined, meaning: SymbolFlags, ignoreErrors?: boolean) {
if (!typeReferenceName) {
return unknownSymbol;
}
return resolveEntityName(typeReferenceName, meaning) || unknownSymbol;
return resolveEntityName(typeReferenceName, meaning, ignoreErrors) || unknownSymbol;
}
function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol): Type {
@@ -9362,10 +9379,19 @@ namespace ts {
if (!links.resolvedType) {
let symbol: Symbol | undefined;
let type: Type | undefined;
let meaning = SymbolFlags.Type;
const meaning = SymbolFlags.Type;
if (isJSDocTypeReference(node)) {
type = getIntendedTypeFromJSDocTypeReference(node);
meaning |= SymbolFlags.Value;
if (!type) {
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning, /*ignoreErrors*/ true);
if (symbol === unknownSymbol) {
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning | SymbolFlags.Value);
}
else {
resolveTypeReferenceName(getTypeReferenceName(node), meaning); // Resolve again to mark errors, if any
}
type = getTypeReferenceType(node, symbol);
}
}
if (!type) {
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning);
@@ -11080,10 +11106,25 @@ namespace ts {
const parent = container && container.parent;
if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) {
if (!hasModifier(container, ModifierFlags.Static) &&
(container.kind !== SyntaxKind.Constructor || isNodeDescendantOf(node, (<ConstructorDeclaration>container).body!))) {
(!isConstructorDeclaration(container) || isNodeDescendantOf(node, container.body))) {
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!;
}
}
// inside x.prototype = { ... }
if (parent && isObjectLiteralExpression(parent) && isBinaryExpression(parent.parent) && getAssignmentDeclarationKind(parent.parent) === AssignmentDeclarationKind.Prototype) {
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent.parent.left)!.parent!).thisType!;
}
// /** @return {this} */
// x.prototype.m = function() { ... }
const host = node.flags & NodeFlags.JSDoc ? getHostSignatureFromJSDoc(node) : undefined;
if (host && isFunctionExpression(host) && isBinaryExpression(host.parent) && getAssignmentDeclarationKind(host.parent) === AssignmentDeclarationKind.PrototypeProperty) {
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(host.parent.left)!.parent!).thisType!;
}
// inside constructor function C() { ... }
if (isJSConstructor(container) && isNodeDescendantOf(node, container.body)) {
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(container)).thisType!;
}
error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface);
return errorType;
}
@@ -12375,15 +12416,17 @@ namespace ts {
}
if (!ignoreReturnTypes) {
// If a signature reolution is already in-flight, skip issuing a circularity error
// If a signature resolution is already in-flight, skip issuing a circularity error
// here and just use the `any` type directly
const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType : (target.declaration && isJSConstructor(target.declaration)) ?
getJSClassType(target.declaration.symbol)! : getReturnTypeOfSignature(target);
const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType
: target.declaration && isJSConstructor(target.declaration) ? getDeclaredTypeOfClassOrInterface(target.declaration.symbol)
: getReturnTypeOfSignature(target);
if (targetReturnType === voidType) {
return result;
}
const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType : (source.declaration && isJSConstructor(source.declaration)) ?
getJSClassType(source.declaration.symbol)! : getReturnTypeOfSignature(source);
const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType
: source.declaration && isJSConstructor(source.declaration) ? getDeclaredTypeOfClassOrInterface(source.declaration.symbol)
: getReturnTypeOfSignature(source);
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
const targetTypePredicate = getTypePredicateOfSignature(target);
@@ -12706,8 +12749,8 @@ namespace ts {
}
function tryElaborateErrorsForPrimitivesAndObjects(source: Type, target: Type) {
const sourceType = typeToString(source);
const targetType = typeToString(target);
const sourceType = symbolValueDeclarationIsContextSensitive(source.symbol) ? typeToString(source, source.symbol.valueDeclaration) : typeToString(source);
const targetType = symbolValueDeclarationIsContextSensitive(target.symbol) ? typeToString(target, target.symbol.valueDeclaration) : typeToString(target);
if ((globalStringType === source && stringType === target) ||
(globalNumberType === source && numberType === target) ||
@@ -13511,9 +13554,19 @@ namespace ts {
// Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if
// one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2,
// and Y1 is related to Y2.
if (isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
const sourceParams = (source as ConditionalType).root.inferTypeParameters;
let sourceExtends = (<ConditionalType>source).extendsType;
let mapper: TypeMapper | undefined;
if (sourceParams) {
// If the source has infer type parameters, we instantiate them in the context of the target
const ctx = createInferenceContext(sourceParams, /*signature*/ undefined, InferenceFlags.None, isRelatedTo);
inferTypes(ctx.inferences, (<ConditionalType>target).extendsType, sourceExtends, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
sourceExtends = instantiateType(sourceExtends, ctx.mapper);
mapper = ctx.mapper;
}
if (isTypeIdenticalTo(sourceExtends, (<ConditionalType>target).extendsType) &&
(isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) || isRelatedTo((<ConditionalType>target).checkType, (<ConditionalType>source).checkType))) {
if (result = isRelatedTo(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target), reportErrors)) {
if (result = isRelatedTo(instantiateType(getTrueTypeFromConditionalType(<ConditionalType>source), mapper), getTrueTypeFromConditionalType(<ConditionalType>target), reportErrors)) {
result &= isRelatedTo(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target), reportErrors);
}
if (result) {
@@ -18262,10 +18315,8 @@ namespace ts {
if (isInJS && className) {
const classSymbol = checkExpression(className).symbol;
if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
const classType = getJSClassType(classSymbol);
if (classType) {
return getFlowTypeOfReference(node, classType);
}
const classType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType!;
return getFlowTypeOfReference(node, classType);
}
}
// Check if it's a constructor definition, can be either a variable decl or function decl
@@ -18275,10 +18326,8 @@ namespace ts {
else if (isInJS &&
(container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) &&
getJSDocClassTag(container)) {
const classType = getJSClassType(getMergedSymbol(container.symbol));
if (classType) {
return getFlowTypeOfReference(node, classType);
}
const classType = (getDeclaredTypeOfSymbol(getMergedSymbol(container.symbol)) as InterfaceType).thisType!;
return getFlowTypeOfReference(node, classType);
}
const thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType(container);
@@ -18289,7 +18338,7 @@ namespace ts {
if (isClassLike(container.parent)) {
const symbol = getSymbolOfNode(container.parent);
const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType!;
const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!;
return getFlowTypeOfReference(node, type);
}
@@ -19874,7 +19923,7 @@ namespace ts {
return isValidSpreadType(constraint);
}
}
return !!(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ||
return !!(type.flags & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ||
getFalsyFlags(type) & TypeFlags.DefinitelyFalsy && isValidSpreadType(removeDefinitelyFalsyTypes(type)) ||
type.flags & TypeFlags.UnionOrIntersection && every((<UnionOrIntersectionType>type).types, isValidSpreadType));
}
@@ -22809,7 +22858,7 @@ namespace ts {
* Indicates whether a declaration can be treated as a constructor in a JavaScript
* file.
*/
function isJSConstructor(node: Declaration | undefined): boolean {
function isJSConstructor(node: Node | undefined): node is FunctionDeclaration | FunctionExpression {
if (!node || !isInJSFile(node)) {
return false;
}
@@ -22822,39 +22871,35 @@ namespace ts {
// If the symbol of the node has members, treat it like a constructor.
const symbol = getSymbolOfNode(func);
return !!symbol && (symbol.members !== undefined || symbol.exports !== undefined && symbol.exports.get("prototype" as __String) !== undefined);
return !!symbol && symbol.members !== undefined;
}
return false;
}
function isJSConstructorType(type: Type) {
if (type.flags & TypeFlags.Object) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
return resolved.callSignatures.length === 1 && isJSConstructor(resolved.callSignatures[0].declaration);
function mergeJSSymbols(target: Symbol, source: Symbol | undefined) {
if (source && (hasEntries(source.exports) || hasEntries(source.members))) {
target = cloneSymbol(target);
if (hasEntries(source.exports)) {
target.exports = target.exports || createSymbolTable();
mergeSymbolTable(target.exports, source.exports);
}
if (hasEntries(source.members)) {
target.members = target.members || createSymbolTable();
mergeSymbolTable(target.members, source.members);
}
target.flags |= source.flags & SymbolFlags.Class;
return target as TransientSymbol;
}
return false;
}
function getJSClassType(symbol: Symbol): Type | undefined {
let inferred: Type | undefined;
if (isJSConstructor(symbol.valueDeclaration)) {
inferred = getInferredClassType(symbol);
}
const assigned = getAssignedClassType(symbol);
return assigned && inferred ?
getIntersectionType([inferred, assigned]) :
assigned || inferred;
}
function getAssignedClassType(symbol: Symbol): Type | undefined {
const decl = symbol.valueDeclaration;
function getAssignedClassSymbol(decl: Declaration): Symbol | undefined {
const assignmentSymbol = decl && decl.parent &&
(isFunctionDeclaration(decl) && getSymbolOfNode(decl) ||
isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent));
const prototype = assignmentSymbol && assignmentSymbol.exports && assignmentSymbol.exports.get("prototype" as __String);
const init = prototype && prototype.valueDeclaration && getAssignedJSPrototype(prototype.valueDeclaration);
return init ? getWidenedType(checkExpressionCached(init)) : undefined;
return init ? getSymbolOfNode(init) : undefined;
}
function getAssignedJSPrototype(node: Node) {
@@ -22871,15 +22916,6 @@ namespace ts {
}
}
function getInferredClassType(symbol: Symbol) {
const links = getSymbolLinks(symbol);
if (!links.inferredClassType) {
links.inferredClassType = createAnonymousType(symbol, getMembersOfSymbol(symbol) || emptySymbols, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined);
}
return links.inferredClassType;
}
/**
* Syntactically and semantically checks a call or new expression.
* @param node The call/new expression to be checked.

View File

@@ -3800,7 +3800,6 @@ namespace ts {
resolvedJSDocType?: Type; // Resolved type of a JSDoc type reference
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
inferredClassType?: Type; // Type of an inferred ES5 class
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
mapper?: TypeMapper; // Type mapper for instantiation alias
referenced?: boolean; // True if alias symbol has been referenced as a value

View File

@@ -2509,7 +2509,7 @@ namespace ts {
return node && node.kind === SyntaxKind.DeleteExpression;
}
export function isNodeDescendantOf(node: Node, ancestor: Node): boolean {
export function isNodeDescendantOf(node: Node, ancestor: Node | undefined): boolean {
while (node) {
if (node === ancestor) return true;
node = node.parent;

4
src/lib/es5.d.ts vendored
View File

@@ -466,13 +466,13 @@ interface String {
toLowerCase(): string;
/** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */
toLocaleLowerCase(): string;
toLocaleLowerCase(locales?: string | string[]): string;
/** Converts all the alphabetic characters in a string to uppercase. */
toUpperCase(): string;
/** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale. */
toLocaleUpperCase(): string;
toLocaleUpperCase(locales?: string | string[]): string;
/** Removes the leading and trailing white space and line terminator characters from a string. */
trim(): string;

View File

@@ -66,7 +66,7 @@ namespace ts {
options.noResolve = true;
// if jsx is specified then treat file as .tsx
const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts");
const inputFileName = transpileOptions.fileName || (transpileOptions.compilerOptions && transpileOptions.compilerOptions.jsx ? "module.tsx" : "module.ts");
const sourceFile = createSourceFile(inputFileName, input, options.target!); // TODO: GH#18217
if (transpileOptions.moduleName) {
sourceFile.moduleName = transpileOptions.moduleName;

View File

@@ -3,6 +3,7 @@ namespace ts {
interface TranspileTestSettings {
options?: TranspileOptions;
noSetFileName?: boolean;
}
function transpilesCorrectly(name: string, input: string, testSettings: TranspileTestSettings) {
@@ -26,15 +27,19 @@ namespace ts {
transpileOptions.compilerOptions.sourceMap = true;
if (!transpileOptions.fileName) {
transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts";
let unitName = transpileOptions.fileName;
if (!unitName) {
unitName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts";
if (!testSettings.noSetFileName) {
transpileOptions.fileName = unitName;
}
}
transpileOptions.reportDiagnostics = true;
const justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? Extension.Tsx : Extension.Ts);
const toBeCompiled: Harness.Compiler.TestFile[] = [{
unitName: transpileOptions.fileName,
const toBeCompiled = [{
unitName,
content: input
}];
const canUseOldTranspile = !transpileOptions.renamedDependencies;
@@ -453,5 +458,9 @@ var x = 0;`, {
transpilesCorrectly("Supports 'as const' arrays", `([] as const).forEach(k => console.log(k));`, {
options: { compilerOptions: { module: ModuleKind.CommonJS } }
});
transpilesCorrectly("Infer correct file extension", `const fn = <T>(a: T) => a`, {
noSetFileName: true
});
});
}