mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-24 11:43:18 -05:00
merge with master
This commit is contained in:
@@ -1485,7 +1485,7 @@ module ts {
|
||||
return appendParentTypeArgumentsAndSymbolName(symbol);
|
||||
}
|
||||
|
||||
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
let globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike;
|
||||
return writeType(type, globalFlags);
|
||||
|
||||
@@ -1493,8 +1493,9 @@ module ts {
|
||||
// Write undefined/null type as any
|
||||
if (type.flags & TypeFlags.Intrinsic) {
|
||||
// Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
|
||||
writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) &&
|
||||
(type.flags & TypeFlags.Any) ? "any" : (<IntrinsicType>type).intrinsicName);
|
||||
writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type)
|
||||
? "any"
|
||||
: (<IntrinsicType>type).intrinsicName);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Reference) {
|
||||
writeTypeReference(<TypeReference>type, flags);
|
||||
@@ -1608,49 +1609,54 @@ module ts {
|
||||
}
|
||||
|
||||
function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) {
|
||||
// Always use 'typeof T' for type of class, enum, and module objects
|
||||
if (type.symbol && type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
// Use 'typeof T' for types of functions and methods that circularly reference themselves
|
||||
else if (shouldWriteTypeOfFunctionSymbol()) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
else if (typeStack && contains(typeStack, type)) {
|
||||
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||
let typeAlias = getTypeAliasForTypeLiteral(type);
|
||||
if (typeAlias) {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
|
||||
let symbol = type.symbol;
|
||||
if (symbol) {
|
||||
// Always use 'typeof T' for type of class, enum, and module objects
|
||||
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
else if (shouldWriteTypeOfFunctionSymbol()) {
|
||||
writeTypeofSymbol(type, flags);
|
||||
}
|
||||
else if (contains(symbolStack, symbol)) {
|
||||
// If type is an anonymous type literal in a type alias declaration, use type alias name
|
||||
let typeAlias = getTypeAliasForTypeLiteral(type);
|
||||
if (typeAlias) {
|
||||
// The specified symbol flags need to be reinterpreted as type flags
|
||||
buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags);
|
||||
}
|
||||
else {
|
||||
// Recursive usage, use any
|
||||
writeKeyword(writer, SyntaxKind.AnyKeyword);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Recursive usage, use any
|
||||
writeKeyword(writer, SyntaxKind.AnyKeyword);
|
||||
// Since instantiations of the same anonymous type have the same symbol, tracking symbols instead
|
||||
// of types allows us to catch circular references to instantiations of the same anonymous type
|
||||
if (!symbolStack) {
|
||||
symbolStack = [];
|
||||
}
|
||||
symbolStack.push(symbol);
|
||||
writeLiteralType(type, flags);
|
||||
symbolStack.pop();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!typeStack) {
|
||||
typeStack = [];
|
||||
}
|
||||
typeStack.push(type);
|
||||
// Anonymous types with no symbol are never circular
|
||||
writeLiteralType(type, flags);
|
||||
typeStack.pop();
|
||||
}
|
||||
|
||||
function shouldWriteTypeOfFunctionSymbol() {
|
||||
if (type.symbol) {
|
||||
let isStaticMethodSymbol = !!(type.symbol.flags & SymbolFlags.Method && // typeof static method
|
||||
ts.forEach(type.symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
|
||||
let isNonLocalFunctionSymbol = !!(type.symbol.flags & SymbolFlags.Function) &&
|
||||
(type.symbol.parent || // is exported function symbol
|
||||
ts.forEach(type.symbol.declarations, declaration =>
|
||||
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
||||
|
||||
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
||||
// typeof is allowed only for static/non local functions
|
||||
return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
|
||||
(typeStack && contains(typeStack, type)); // it is type of the symbol uses itself recursively
|
||||
}
|
||||
let isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
|
||||
forEach(symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
|
||||
let isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
|
||||
(symbol.parent || // is exported function symbol
|
||||
forEach(symbol.declarations, declaration =>
|
||||
declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock));
|
||||
if (isStaticMethodSymbol || isNonLocalFunctionSymbol) {
|
||||
// typeof is allowed only for static/non local functions
|
||||
return !!(flags & TypeFormatFlags.UseTypeOfFunction) || // use typeof if format flags specify it
|
||||
(contains(symbolStack, symbol)); // it is type of the symbol uses itself recursively
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1685,7 +1691,7 @@ module ts {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack);
|
||||
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
@@ -1697,7 +1703,7 @@ module ts {
|
||||
}
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, typeStack);
|
||||
buildSignatureDisplay(resolved.constructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, symbolStack);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
@@ -1709,7 +1715,7 @@ module ts {
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
for (let signature of resolved.callSignatures) {
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1717,7 +1723,7 @@ module ts {
|
||||
writeKeyword(writer, SyntaxKind.NewKeyword);
|
||||
writeSpace(writer);
|
||||
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1758,7 +1764,7 @@ module ts {
|
||||
if (p.flags & SymbolFlags.Optional) {
|
||||
writePunctuation(writer, SyntaxKind.QuestionToken);
|
||||
}
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, typeStack);
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
@@ -1787,18 +1793,18 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
appendSymbolNameOnly(tp.symbol, writer);
|
||||
let constraint = getConstraintOfTypeParameter(tp);
|
||||
if (constraint) {
|
||||
writeSpace(writer);
|
||||
writeKeyword(writer, SyntaxKind.ExtendsKeyword);
|
||||
writeSpace(writer);
|
||||
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeDisplay(constraint, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
}
|
||||
|
||||
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
let parameterNode = <ParameterDeclaration>p.valueDeclaration;
|
||||
if (isRestParameter(parameterNode)) {
|
||||
writePunctuation(writer, SyntaxKind.DotDotDotToken);
|
||||
@@ -1810,10 +1816,10 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
writeSpace(writer);
|
||||
|
||||
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (typeParameters && typeParameters.length) {
|
||||
writePunctuation(writer, SyntaxKind.LessThanToken);
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
@@ -1821,13 +1827,13 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.CommaToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeParameterDisplay(typeParameters[i], writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
writePunctuation(writer, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
}
|
||||
|
||||
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (typeParameters && typeParameters.length) {
|
||||
writePunctuation(writer, SyntaxKind.LessThanToken);
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
@@ -1841,19 +1847,19 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
if (i > 0) {
|
||||
writePunctuation(writer, SyntaxKind.CommaToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
|
||||
buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
|
||||
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
|
||||
writeSpace(writer);
|
||||
writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken);
|
||||
@@ -1862,21 +1868,21 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||
}
|
||||
writeSpace(writer);
|
||||
buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
|
||||
buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
|
||||
// Instantiated signature, write type arguments instead
|
||||
// This is achieved by passing in the mapper separately
|
||||
buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
|
||||
}
|
||||
else {
|
||||
buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
|
||||
buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, symbolStack);
|
||||
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
return _displayBuilder || (_displayBuilder = {
|
||||
@@ -2131,6 +2137,10 @@ module ts {
|
||||
return prop ? getTypeOfSymbol(prop) : undefined;
|
||||
}
|
||||
|
||||
function isTypeAny(type: Type) {
|
||||
return type && (type.flags & TypeFlags.Any) !== 0;
|
||||
}
|
||||
|
||||
// Return the inferred type for a binding element
|
||||
function getTypeForBindingElement(declaration: BindingElement): Type {
|
||||
let pattern = <BindingPattern>declaration.parent;
|
||||
@@ -2142,7 +2152,7 @@ module ts {
|
||||
// If no type was specified or inferred for parent, or if the specified or inferred type is any,
|
||||
// infer from the initializer of the binding element if one is present. Otherwise, go with the
|
||||
// undefined or any type of the parent.
|
||||
if (!parentType || parentType === anyType) {
|
||||
if (!parentType || isTypeAny(parentType)) {
|
||||
if (declaration.initializer) {
|
||||
return checkExpressionCached(declaration.initializer);
|
||||
}
|
||||
@@ -2169,7 +2179,7 @@ module ts {
|
||||
// fact an iterable or array (depending on target language).
|
||||
let elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false);
|
||||
if (!declaration.dotDotDotToken) {
|
||||
if (elementType.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(elementType)) {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
@@ -3716,9 +3726,9 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function containsAnyType(types: Type[]) {
|
||||
function containsTypeAny(types: Type[]) {
|
||||
for (let type of types) {
|
||||
if (type.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3746,7 +3756,7 @@ module ts {
|
||||
let sortedTypes: Type[] = [];
|
||||
addTypesToSortedSet(sortedTypes, types);
|
||||
if (noSubtypeReduction) {
|
||||
if (containsAnyType(sortedTypes)) {
|
||||
if (containsTypeAny(sortedTypes)) {
|
||||
return anyType;
|
||||
}
|
||||
removeAllButLast(sortedTypes, undefinedType);
|
||||
@@ -3996,19 +4006,8 @@ module ts {
|
||||
}
|
||||
|
||||
function instantiateAnonymousType(type: ObjectType, mapper: TypeMapper): ObjectType {
|
||||
// If this type has already been instantiated using this mapper, returned the cached result. This guards against
|
||||
// infinite instantiations of cyclic types, e.g. "var x: { a: T, b: typeof x };"
|
||||
if (mapper.mappings) {
|
||||
let cached = <ObjectType>mapper.mappings[type.id];
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mapper.mappings = {};
|
||||
}
|
||||
// Instantiate the given type using the given mapper and cache the result
|
||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
|
||||
// Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it
|
||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol);
|
||||
result.properties = instantiateList(getPropertiesOfObjectType(type), mapper, instantiateSymbol);
|
||||
result.members = createSymbolTable(result.properties);
|
||||
result.callSignatures = instantiateList(getSignaturesOfType(type, SignatureKind.Call), mapper, instantiateSignature);
|
||||
@@ -4017,7 +4016,6 @@ module ts {
|
||||
let numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
|
||||
if (stringIndexType) result.stringIndexType = instantiateType(stringIndexType, mapper);
|
||||
if (numberIndexType) result.numberIndexType = instantiateType(numberIndexType, mapper);
|
||||
mapper.mappings[type.id] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4182,13 +4180,13 @@ module ts {
|
||||
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
|
||||
if (source === target) return Ternary.True;
|
||||
if (relation !== identityRelation) {
|
||||
if (target.flags & TypeFlags.Any) return Ternary.True;
|
||||
if (isTypeAny(target)) return Ternary.True;
|
||||
if (source === undefinedType) return Ternary.True;
|
||||
if (source === nullType && target !== undefinedType) return Ternary.True;
|
||||
if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True;
|
||||
if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True;
|
||||
if (relation === assignableRelation) {
|
||||
if (source.flags & TypeFlags.Any) return Ternary.True;
|
||||
if (isTypeAny(source)) return Ternary.True;
|
||||
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
|
||||
}
|
||||
}
|
||||
@@ -4432,12 +4430,13 @@ module ts {
|
||||
// Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at
|
||||
// some level beyond that.
|
||||
function isDeeplyNestedGeneric(type: ObjectType, stack: ObjectType[]): boolean {
|
||||
if (type.flags & TypeFlags.Reference && depth >= 10) {
|
||||
let target = (<TypeReference>type).target;
|
||||
// We track type references (created by createTypeReference) and instantiated types (created by instantiateType)
|
||||
if (type.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && depth >= 10) {
|
||||
let symbol = type.symbol;
|
||||
let count = 0;
|
||||
for (let i = 0; i < depth; i++) {
|
||||
let t = stack[i];
|
||||
if (t.flags & TypeFlags.Reference && (<TypeReference>t).target === target) {
|
||||
if (t.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && t.symbol === symbol) {
|
||||
count++;
|
||||
if (count >= 10) return true;
|
||||
}
|
||||
@@ -5412,55 +5411,58 @@ module ts {
|
||||
function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) {
|
||||
let type = getTypeOfSymbol(symbol);
|
||||
// Only narrow when symbol is variable of type any or an object, union, or type parameter type
|
||||
if (node && symbol.flags & SymbolFlags.Variable && type.flags & (TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) {
|
||||
loop: while (node.parent) {
|
||||
let child = node;
|
||||
node = node.parent;
|
||||
let narrowedType = type;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.IfStatement:
|
||||
// In a branch of an if statement, narrow based on controlling expression
|
||||
if (child !== (<IfStatement>node).expression) {
|
||||
narrowedType = narrowType(type, (<IfStatement>node).expression, /*assumeTrue*/ child === (<IfStatement>node).thenStatement);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
// In a branch of a conditional expression, narrow based on controlling condition
|
||||
if (child !== (<ConditionalExpression>node).condition) {
|
||||
narrowedType = narrowType(type, (<ConditionalExpression>node).condition, /*assumeTrue*/ child === (<ConditionalExpression>node).whenTrue);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
// In the right operand of an && or ||, narrow based on left operand
|
||||
if (child === (<BinaryExpression>node).right) {
|
||||
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
|
||||
narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ true);
|
||||
if (node && symbol.flags & SymbolFlags.Variable) {
|
||||
if (isTypeAny(type) || type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) {
|
||||
loop: while (node.parent) {
|
||||
let child = node;
|
||||
node = node.parent;
|
||||
let narrowedType = type;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.IfStatement:
|
||||
// In a branch of an if statement, narrow based on controlling expression
|
||||
if (child !== (<IfStatement>node).expression) {
|
||||
narrowedType = narrowType(type, (<IfStatement>node).expression, /*assumeTrue*/ child === (<IfStatement>node).thenStatement);
|
||||
}
|
||||
else if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
|
||||
narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ false);
|
||||
break;
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
// In a branch of a conditional expression, narrow based on controlling condition
|
||||
if (child !== (<ConditionalExpression>node).condition) {
|
||||
narrowedType = narrowType(type, (<ConditionalExpression>node).condition, /*assumeTrue*/ child === (<ConditionalExpression>node).whenTrue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.Constructor:
|
||||
// Stop at the first containing function or module declaration
|
||||
break loop;
|
||||
}
|
||||
// Use narrowed type if construct contains no assignments to variable
|
||||
if (narrowedType !== type) {
|
||||
if (isVariableAssignedWithin(symbol, node)) {
|
||||
break;
|
||||
break;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
// In the right operand of an && or ||, narrow based on left operand
|
||||
if (child === (<BinaryExpression>node).right) {
|
||||
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
|
||||
narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ true);
|
||||
}
|
||||
else if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
|
||||
narrowedType = narrowType(type, (<BinaryExpression>node).left, /*assumeTrue*/ false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.Constructor:
|
||||
// Stop at the first containing function or module declaration
|
||||
break loop;
|
||||
}
|
||||
// Use narrowed type if construct contains no assignments to variable
|
||||
if (narrowedType !== type) {
|
||||
if (isVariableAssignedWithin(symbol, node)) {
|
||||
break;
|
||||
}
|
||||
type = narrowedType;
|
||||
}
|
||||
type = narrowedType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
|
||||
function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
@@ -5533,7 +5535,7 @@ module ts {
|
||||
|
||||
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
// Check that type is not any, assumed result is true, and we have variable symbol on the left
|
||||
if (type.flags & TypeFlags.Any || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
|
||||
if (isTypeAny(type) || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(<Identifier>expr.left) !== symbol) {
|
||||
return type;
|
||||
}
|
||||
// Check that right operand is a function type with a prototype property
|
||||
@@ -5547,7 +5549,7 @@ module ts {
|
||||
if (prototypeProperty) {
|
||||
// Target type is type of the protoype property
|
||||
let prototypePropertyType = getTypeOfSymbol(prototypeProperty);
|
||||
if (prototypePropertyType !== anyType) {
|
||||
if (!isTypeAny(prototypePropertyType)) {
|
||||
targetType = prototypePropertyType;
|
||||
}
|
||||
}
|
||||
@@ -6308,7 +6310,11 @@ module ts {
|
||||
function isNumericComputedName(name: ComputedPropertyName): boolean {
|
||||
// It seems odd to consider an expression of type Any to result in a numeric name,
|
||||
// but this behavior is consistent with checkIndexedAccess
|
||||
return allConstituentTypesHaveKind(checkComputedPropertyName(name), TypeFlags.Any | TypeFlags.NumberLike);
|
||||
return isTypeAnyOrAllConstituentTypesHaveKind(checkComputedPropertyName(name), TypeFlags.NumberLike);
|
||||
}
|
||||
|
||||
function isTypeAnyOrAllConstituentTypesHaveKind(type: Type, kind: TypeFlags): boolean {
|
||||
return isTypeAny(type) || allConstituentTypesHaveKind(type, kind);
|
||||
}
|
||||
|
||||
function isNumericLiteralName(name: string) {
|
||||
@@ -6343,7 +6349,7 @@ module ts {
|
||||
|
||||
// This will allow types number, string, symbol or any. It will also allow enums, the unknown
|
||||
// type, and any union of these types (like string | number).
|
||||
if (!allConstituentTypesHaveKind(links.resolvedType, TypeFlags.Any | TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) {
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(links.resolvedType, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) {
|
||||
error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
|
||||
}
|
||||
else {
|
||||
@@ -6495,39 +6501,39 @@ module ts {
|
||||
|
||||
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
|
||||
let type = checkExpressionOrQualifiedName(left);
|
||||
if (type === unknownType) return type;
|
||||
if (type !== anyType) {
|
||||
let apparentType = getApparentType(getWidenedType(type));
|
||||
if (apparentType === unknownType) {
|
||||
// handle cases when type is Type parameter with invalid constraint
|
||||
return unknownType;
|
||||
}
|
||||
let prop = getPropertyOfType(apparentType, right.text);
|
||||
if (!prop) {
|
||||
if (right.text) {
|
||||
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type));
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
getNodeLinks(node).resolvedSymbol = prop;
|
||||
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
|
||||
// TS 1.0 spec (April 2014): 4.8.2
|
||||
// - In a constructor, instance member function, instance member accessor, or
|
||||
// instance member variable initializer where this references a derived class instance,
|
||||
// a super property access is permitted and must specify a public instance member function of the base class.
|
||||
// - In a static member function or static member accessor
|
||||
// where this references the constructor function object of a derived class,
|
||||
// a super property access is permitted and must specify a public static member function of the base class.
|
||||
if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
|
||||
error(right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
|
||||
}
|
||||
else {
|
||||
checkClassPropertyAccess(node, left, type, prop);
|
||||
}
|
||||
}
|
||||
return getTypeOfSymbol(prop);
|
||||
if (isTypeAny(type)) {
|
||||
return type;
|
||||
}
|
||||
return anyType;
|
||||
|
||||
let apparentType = getApparentType(getWidenedType(type));
|
||||
if (apparentType === unknownType) {
|
||||
// handle cases when type is Type parameter with invalid constraint
|
||||
return unknownType;
|
||||
}
|
||||
let prop = getPropertyOfType(apparentType, right.text);
|
||||
if (!prop) {
|
||||
if (right.text) {
|
||||
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type));
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
getNodeLinks(node).resolvedSymbol = prop;
|
||||
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
|
||||
// TS 1.0 spec (April 2014): 4.8.2
|
||||
// - In a constructor, instance member function, instance member accessor, or
|
||||
// instance member variable initializer where this references a derived class instance,
|
||||
// a super property access is permitted and must specify a public instance member function of the base class.
|
||||
// - In a static member function or static member accessor
|
||||
// where this references the constructor function object of a derived class,
|
||||
// a super property access is permitted and must specify a public static member function of the base class.
|
||||
if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
|
||||
error(right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
|
||||
}
|
||||
else {
|
||||
checkClassPropertyAccess(node, left, type, prop);
|
||||
}
|
||||
}
|
||||
return getTypeOfSymbol(prop);
|
||||
}
|
||||
|
||||
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
|
||||
@@ -6536,7 +6542,7 @@ module ts {
|
||||
: (<QualifiedName>node).left;
|
||||
|
||||
let type = checkExpressionOrQualifiedName(left);
|
||||
if (type !== unknownType && type !== anyType) {
|
||||
if (type !== unknownType && !isTypeAny(type)) {
|
||||
let prop = getPropertyOfType(getWidenedType(type), propertyName);
|
||||
if (prop && prop.parent && prop.parent.flags & SymbolFlags.Class) {
|
||||
if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
|
||||
@@ -6609,10 +6615,10 @@ module ts {
|
||||
}
|
||||
|
||||
// Check for compatible indexer types.
|
||||
if (allConstituentTypesHaveKind(indexType, TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
|
||||
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
|
||||
|
||||
// Try to use a number indexer.
|
||||
if (allConstituentTypesHaveKind(indexType, TypeFlags.Any | TypeFlags.NumberLike)) {
|
||||
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike)) {
|
||||
let numberIndexType = getIndexTypeOfType(objectType, IndexKind.Number);
|
||||
if (numberIndexType) {
|
||||
return numberIndexType;
|
||||
@@ -6626,7 +6632,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Fall back to any.
|
||||
if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && objectType !== anyType) {
|
||||
if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !isTypeAny(objectType)) {
|
||||
error(node, Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type);
|
||||
}
|
||||
|
||||
@@ -7276,8 +7282,10 @@ module ts {
|
||||
// types are provided for the argument expressions, and the result is always of type Any.
|
||||
// We exclude union types because we may have a union of function types that happen to have
|
||||
// no common signatures.
|
||||
if (funcType === anyType || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
|
||||
if (node.typeArguments) {
|
||||
if (isTypeAny(funcType) || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
|
||||
// The unknownType indicates that an error already occured (and was reported). No
|
||||
// need to report another error in this case.
|
||||
if (funcType !== unknownType && node.typeArguments) {
|
||||
error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
|
||||
}
|
||||
return resolveUntypedCall(node);
|
||||
@@ -7306,15 +7314,6 @@ module ts {
|
||||
}
|
||||
|
||||
let expressionType = checkExpression(node.expression);
|
||||
// TS 1.0 spec: 4.11
|
||||
// If ConstructExpr is of type Any, Args can be any argument
|
||||
// list and the result of the operation is of type Any.
|
||||
if (expressionType === anyType) {
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
|
||||
}
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
// If ConstructExpr's apparent type(section 3.8.1) is an object type with one or
|
||||
// more construct signatures, the expression is processed in the same manner as a
|
||||
@@ -7327,6 +7326,16 @@ module ts {
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
// TS 1.0 spec: 4.11
|
||||
// If ConstructExpr is of type Any, Args can be any argument
|
||||
// list and the result of the operation is of type Any.
|
||||
if (isTypeAny(expressionType)) {
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
|
||||
}
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
// Technically, this signatures list may be incomplete. We are taking the apparent type,
|
||||
// but we are not including construct signatures that may have been added to the Object or
|
||||
// Function interface, since they have none by default. This is a bit of a leap of faith
|
||||
@@ -7364,7 +7373,7 @@ module ts {
|
||||
|
||||
let callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
|
||||
|
||||
if (tagType === anyType || (!callSignatures.length && !(tagType.flags & TypeFlags.Union) && isTypeAssignableTo(tagType, globalFunctionType))) {
|
||||
if (isTypeAny(tagType) || (!callSignatures.length && !(tagType.flags & TypeFlags.Union) && isTypeAssignableTo(tagType, globalFunctionType))) {
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
@@ -7576,7 +7585,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Functions that return 'void' or 'any' don't need any return expressions.
|
||||
if (returnType === voidType || returnType === anyType) {
|
||||
if (returnType === voidType || isTypeAny(returnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7680,7 +7689,7 @@ module ts {
|
||||
}
|
||||
|
||||
function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean {
|
||||
if (!allConstituentTypesHaveKind(type, TypeFlags.Any | TypeFlags.NumberLike)) {
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(type, TypeFlags.NumberLike)) {
|
||||
error(operand, diagnostic);
|
||||
return false;
|
||||
}
|
||||
@@ -7892,7 +7901,7 @@ module ts {
|
||||
error(node.left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
|
||||
}
|
||||
// NOTE: do not raise error if right is unknown as related error was already reported
|
||||
if (!(rightType.flags & TypeFlags.Any || isTypeSubtypeOf(rightType, globalFunctionType))) {
|
||||
if (!(isTypeAny(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) {
|
||||
error(node.right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type);
|
||||
}
|
||||
return booleanType;
|
||||
@@ -7903,10 +7912,10 @@ module ts {
|
||||
// The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
|
||||
// and the right operand to be of type Any, an object type, or a type parameter type.
|
||||
// The result is always of the Boolean primitive type.
|
||||
if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
|
||||
error(node.left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
|
||||
}
|
||||
if (!allConstituentTypesHaveKind(rightType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
error(node.right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
|
||||
}
|
||||
return booleanType;
|
||||
@@ -7918,10 +7927,11 @@ module ts {
|
||||
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
||||
// TODO(andersh): Computed property support
|
||||
let name = <Identifier>(<PropertyAssignment>p).name;
|
||||
let type = sourceType.flags & TypeFlags.Any ? sourceType :
|
||||
getTypeOfPropertyOfType(sourceType, name.text) ||
|
||||
isNumericLiteralName(name.text) && getIndexTypeOfType(sourceType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(sourceType, IndexKind.String);
|
||||
let type = isTypeAny(sourceType)
|
||||
? sourceType
|
||||
: getTypeOfPropertyOfType(sourceType, name.text) ||
|
||||
isNumericLiteralName(name.text) && getIndexTypeOfType(sourceType, IndexKind.Number) ||
|
||||
getIndexTypeOfType(sourceType, IndexKind.String);
|
||||
if (type) {
|
||||
checkDestructuringAssignment((<PropertyAssignment>p).initializer || name, type);
|
||||
}
|
||||
@@ -7947,8 +7957,9 @@ module ts {
|
||||
if (e.kind !== SyntaxKind.OmittedExpression) {
|
||||
if (e.kind !== SyntaxKind.SpreadElementExpression) {
|
||||
let propName = "" + i;
|
||||
let type = sourceType.flags & TypeFlags.Any ? sourceType :
|
||||
isTupleLikeType(sourceType)
|
||||
let type = isTypeAny(sourceType)
|
||||
? sourceType
|
||||
: isTupleLikeType(sourceType)
|
||||
? getTypeOfPropertyOfType(sourceType, propName)
|
||||
: elementType;
|
||||
if (type) {
|
||||
@@ -8087,10 +8098,10 @@ module ts {
|
||||
// If one or both operands are of the String primitive type, the result is of the String primitive type.
|
||||
resultType = stringType;
|
||||
}
|
||||
else if (leftType.flags & TypeFlags.Any || rightType.flags & TypeFlags.Any) {
|
||||
else if (isTypeAny(leftType) || isTypeAny(rightType)) {
|
||||
// Otherwise, the result is of type Any.
|
||||
// NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
|
||||
resultType = anyType;
|
||||
resultType = leftType === unknownType || rightType === unknownType ? unknownType : anyType;
|
||||
}
|
||||
|
||||
// Symbols are not allowed at all in arithmetic expressions
|
||||
@@ -9786,7 +9797,7 @@ module ts {
|
||||
if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
|
||||
}
|
||||
else if (!allConstituentTypesHaveKind(leftType, TypeFlags.Any | TypeFlags.StringLike)) {
|
||||
else if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike)) {
|
||||
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
|
||||
}
|
||||
else {
|
||||
@@ -9798,7 +9809,7 @@ module ts {
|
||||
let rightType = checkExpression(node.expression);
|
||||
// unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
|
||||
// in this case error about missing name is already reported - do not report extra one
|
||||
if (!allConstituentTypesHaveKind(rightType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
|
||||
}
|
||||
|
||||
@@ -9820,7 +9831,7 @@ module ts {
|
||||
}
|
||||
|
||||
function checkIteratedTypeOrElementType(inputType: Type, errorNode: Node, allowStringInput: boolean): Type {
|
||||
if (inputType.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(inputType)) {
|
||||
return inputType;
|
||||
}
|
||||
|
||||
@@ -9879,7 +9890,7 @@ module ts {
|
||||
* whole pattern and that T (above) is 'any'.
|
||||
*/
|
||||
function getElementTypeOfIterable(type: Type, errorNode: Node): Type {
|
||||
if (type.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(type)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -9892,7 +9903,7 @@ module ts {
|
||||
}
|
||||
else {
|
||||
let iteratorFunction = getTypeOfPropertyOfType(type, getPropertyNameForKnownSymbolName("iterator"));
|
||||
if (iteratorFunction && iteratorFunction.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(iteratorFunction)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -9925,7 +9936,7 @@ module ts {
|
||||
*
|
||||
*/
|
||||
function getElementTypeOfIterator(type: Type, errorNode: Node): Type {
|
||||
if (type.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(type)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -9938,7 +9949,7 @@ module ts {
|
||||
}
|
||||
else {
|
||||
let iteratorNextFunction = getTypeOfPropertyOfType(type, "next");
|
||||
if (iteratorNextFunction && iteratorNextFunction.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(iteratorNextFunction)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -9951,7 +9962,7 @@ module ts {
|
||||
}
|
||||
|
||||
let iteratorNextResult = getUnionType(map(iteratorNextFunctionSignatures, getReturnTypeOfSignature));
|
||||
if (iteratorNextResult.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(iteratorNextResult)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -9971,7 +9982,7 @@ module ts {
|
||||
}
|
||||
|
||||
function getElementTypeOfIterableIterator(type: Type): Type {
|
||||
if (type.flags & TypeFlags.Any) {
|
||||
if (isTypeAny(type)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -349,7 +349,7 @@ module ts {
|
||||
|
||||
return {
|
||||
options: getCompilerOptions(),
|
||||
fileNames: getFiles(),
|
||||
fileNames: getFileNames(),
|
||||
errors
|
||||
};
|
||||
|
||||
@@ -395,23 +395,24 @@ module ts {
|
||||
return options;
|
||||
}
|
||||
|
||||
function getFiles(): string[] {
|
||||
var files: string[] = [];
|
||||
function getFileNames(): string[] {
|
||||
var fileNames: string[] = [];
|
||||
if (hasProperty(json, "files")) {
|
||||
if (json["files"] instanceof Array) {
|
||||
var files = map(<string[]>json["files"], s => combinePaths(basePath, s));
|
||||
fileNames = map(<string[]>json["files"], s => combinePaths(basePath, s));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var sysFiles = host.readDirectory(basePath, ".ts");
|
||||
var exclude = json["exclude"] instanceof Array ? map(<string[]>json["exclude"], normalizeSlashes) : undefined;
|
||||
var sysFiles = host.readDirectory(basePath, ".ts", exclude);
|
||||
for (var i = 0; i < sysFiles.length; i++) {
|
||||
var name = sysFiles[i];
|
||||
if (!fileExtensionIs(name, ".d.ts") || !contains(sysFiles, name.substr(0, name.length - 5) + ".ts")) {
|
||||
files.push(name);
|
||||
fileNames.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return files;
|
||||
return fileNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,42 @@ module ts {
|
||||
True = -1
|
||||
}
|
||||
|
||||
export function createFileMap<T>(getCanonicalFileName: (fileName: string) => string): FileMap<T> {
|
||||
let files: Map<T> = {};
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
contains,
|
||||
delete: deleteItem,
|
||||
forEachValue: forEachValueInMap
|
||||
}
|
||||
|
||||
function set(fileName: string, value: T) {
|
||||
files[normalizeKey(fileName)] = value;
|
||||
}
|
||||
|
||||
function get(fileName: string) {
|
||||
return files[normalizeKey(fileName)];
|
||||
}
|
||||
|
||||
function contains(fileName: string) {
|
||||
return hasProperty(files, normalizeKey(fileName));
|
||||
}
|
||||
|
||||
function deleteItem (fileName: string) {
|
||||
let key = normalizeKey(fileName);
|
||||
delete files[key];
|
||||
}
|
||||
|
||||
function forEachValueInMap(f: (value: T) => void) {
|
||||
forEachValue(files, f);
|
||||
}
|
||||
|
||||
function normalizeKey(key: string) {
|
||||
return getCanonicalFileName(normalizeSlashes(key));
|
||||
}
|
||||
}
|
||||
|
||||
export const enum Comparison {
|
||||
LessThan = -1,
|
||||
EqualTo = 0,
|
||||
|
||||
@@ -1646,6 +1646,12 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
}
|
||||
|
||||
function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
while (expr.kind === SyntaxKind.TypeAssertionExpression) {
|
||||
expr = (<TypeAssertion>expr).expression;
|
||||
}
|
||||
|
||||
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
|
||||
// to parenthesize the expression before a dot. The known exceptions are:
|
||||
//
|
||||
@@ -1654,7 +1660,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
// NumberLiteral
|
||||
// 1.x -> not the same as (1).x
|
||||
//
|
||||
if (isLeftHandSideExpression(expr) && expr.kind !== SyntaxKind.NewExpression && expr.kind !== SyntaxKind.NumericLiteral) {
|
||||
if (isLeftHandSideExpression(expr) &&
|
||||
expr.kind !== SyntaxKind.NewExpression &&
|
||||
expr.kind !== SyntaxKind.NumericLiteral) {
|
||||
|
||||
return <LeftHandSideExpression>expr;
|
||||
}
|
||||
let node = <ParenthesizedExpression>createSynthesizedNode(SyntaxKind.ParenthesizedExpression);
|
||||
@@ -1941,7 +1950,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
}
|
||||
|
||||
function emitParenExpression(node: ParenthesizedExpression) {
|
||||
if (!node.parent || node.parent.kind !== SyntaxKind.ArrowFunction) {
|
||||
// If the node is synthesized, it means the emitter put the parentheses there,
|
||||
// not the user. If we didn't want them, the emitter would not have put them
|
||||
// there.
|
||||
if (!nodeIsSynthesized(node) && node.parent.kind !== SyntaxKind.ArrowFunction) {
|
||||
if (node.expression.kind === SyntaxKind.TypeAssertionExpression) {
|
||||
let operand = (<TypeAssertion>node.expression).expression;
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@ module ts {
|
||||
/** The version of the TypeScript compiler release */
|
||||
export const version = "1.5.3";
|
||||
|
||||
const carriageReturnLineFeed = "\r\n";
|
||||
const lineFeed = "\n";
|
||||
|
||||
export function findConfigFile(searchPath: string): string {
|
||||
var fileName = "tsconfig.json";
|
||||
while (true) {
|
||||
@@ -94,10 +91,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
let newLine =
|
||||
options.newLine === NewLineKind.CarriageReturnLineFeed ? carriageReturnLineFeed :
|
||||
options.newLine === NewLineKind.LineFeed ? lineFeed :
|
||||
sys.newLine;
|
||||
const newLine = getNewLineCharacter(options);
|
||||
|
||||
return {
|
||||
getSourceFile,
|
||||
@@ -149,7 +143,6 @@ module ts {
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost): Program {
|
||||
let program: Program;
|
||||
let files: SourceFile[] = [];
|
||||
let filesByName: Map<SourceFile> = {};
|
||||
let diagnostics = createDiagnosticCollection();
|
||||
let seenNoDefaultLib = options.noLib;
|
||||
let commonSourceDirectory: string;
|
||||
@@ -159,6 +152,8 @@ module ts {
|
||||
let start = new Date().getTime();
|
||||
|
||||
host = host || createCompilerHost(options);
|
||||
let filesByName = createFileMap<SourceFile>(host.getCanonicalFileName);
|
||||
|
||||
forEach(rootNames, name => processRootFile(name, false));
|
||||
if (!seenNoDefaultLib) {
|
||||
processRootFile(host.getDefaultLibFileName(options), true);
|
||||
@@ -175,6 +170,7 @@ module ts {
|
||||
getGlobalDiagnostics,
|
||||
getSemanticDiagnostics,
|
||||
getDeclarationDiagnostics,
|
||||
getCompilerOptionsDiagnostics,
|
||||
getTypeChecker,
|
||||
getDiagnosticsProducingTypeChecker,
|
||||
getCommonSourceDirectory: () => commonSourceDirectory,
|
||||
@@ -238,8 +234,7 @@ module ts {
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string) {
|
||||
fileName = host.getCanonicalFileName(normalizeSlashes(fileName));
|
||||
return hasProperty(filesByName, fileName) ? filesByName[fileName] : undefined;
|
||||
return filesByName.get(fileName);
|
||||
}
|
||||
|
||||
function getDiagnosticsHelper(sourceFile: SourceFile, getDiagnostics: (sourceFile: SourceFile) => Diagnostic[]): Diagnostic[] {
|
||||
@@ -291,6 +286,12 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getCompilerOptionsDiagnostics(): Diagnostic[] {
|
||||
let allDiagnostics: Diagnostic[] = [];
|
||||
addRange(allDiagnostics, diagnostics.getGlobalDiagnostics());
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
}
|
||||
|
||||
function getGlobalDiagnostics(): Diagnostic[] {
|
||||
let typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
@@ -358,19 +359,19 @@ module ts {
|
||||
// Get source file from normalized fileName
|
||||
function findSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refStart?: number, refLength?: number): SourceFile {
|
||||
let canonicalName = host.getCanonicalFileName(normalizeSlashes(fileName));
|
||||
if (hasProperty(filesByName, canonicalName)) {
|
||||
if (filesByName.contains(canonicalName)) {
|
||||
// We've already looked for this file, use cached result
|
||||
return getSourceFileFromCache(fileName, canonicalName, /*useAbsolutePath*/ false);
|
||||
}
|
||||
else {
|
||||
let normalizedAbsolutePath = getNormalizedAbsolutePath(fileName, host.getCurrentDirectory());
|
||||
let canonicalAbsolutePath = host.getCanonicalFileName(normalizedAbsolutePath);
|
||||
if (hasProperty(filesByName, canonicalAbsolutePath)) {
|
||||
if (filesByName.contains(canonicalAbsolutePath)) {
|
||||
return getSourceFileFromCache(normalizedAbsolutePath, canonicalAbsolutePath, /*useAbsolutePath*/ true);
|
||||
}
|
||||
|
||||
// We haven't looked for this file, do so now and cache result
|
||||
let file = filesByName[canonicalName] = host.getSourceFile(fileName, options.target, hostErrorMessage => {
|
||||
let file = host.getSourceFile(fileName, options.target, hostErrorMessage => {
|
||||
if (refFile) {
|
||||
diagnostics.add(createFileDiagnostic(refFile, refStart, refLength,
|
||||
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
@@ -379,11 +380,12 @@ module ts {
|
||||
diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
});
|
||||
filesByName.set(canonicalName, file);
|
||||
if (file) {
|
||||
seenNoDefaultLib = seenNoDefaultLib || file.hasNoDefaultLib;
|
||||
|
||||
// Set the source file for normalized absolute path
|
||||
filesByName[canonicalAbsolutePath] = file;
|
||||
filesByName.set(canonicalAbsolutePath, file);
|
||||
|
||||
if (!options.noResolve) {
|
||||
let basePath = getDirectoryPath(fileName);
|
||||
@@ -402,7 +404,7 @@ module ts {
|
||||
}
|
||||
|
||||
function getSourceFileFromCache(fileName: string, canonicalName: string, useAbsolutePath: boolean): SourceFile {
|
||||
let file = filesByName[canonicalName];
|
||||
let file = filesByName.get(canonicalName);
|
||||
if (file && host.useCaseSensitiveFileNames()) {
|
||||
let sourceFileName = useAbsolutePath ? getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()) : file.fileName;
|
||||
if (canonicalName !== sourceFileName) {
|
||||
|
||||
@@ -15,7 +15,7 @@ module ts {
|
||||
createDirectory(path: string): void;
|
||||
getExecutingFilePath(): string;
|
||||
getCurrentDirectory(): string;
|
||||
readDirectory(path: string, extension?: string): string[];
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
getMemoryUsage?(): number;
|
||||
exit(exitCode?: number): void;
|
||||
}
|
||||
@@ -109,7 +109,11 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[] {
|
||||
function getCanonicalPath(path: string): string {
|
||||
return path.toLowerCase();
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[]{
|
||||
var result: string[] = [];
|
||||
for (var e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
|
||||
result.push(e.item().Name);
|
||||
@@ -117,21 +121,26 @@ module ts {
|
||||
return result.sort();
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string): string[] {
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
var result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
var folder = fso.GetFolder(path || ".");
|
||||
var files = getNames(folder.files);
|
||||
for (let name of files) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(combinePaths(path, name));
|
||||
for (let current of files) {
|
||||
let name = combinePaths(path, current);
|
||||
if ((!extension || fileExtensionIs(name, extension)) && !contains(exclude, getCanonicalPath(name))) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
var subfolders = getNames(folder.subfolders);
|
||||
for (let current of subfolders) {
|
||||
visitDirectory(combinePaths(path, current));
|
||||
let name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
visitDirectory(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,8 +231,13 @@ module ts {
|
||||
_fs.writeFileSync(fileName, data, "utf8");
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string): string[] {
|
||||
function getCanonicalPath(path: string): string {
|
||||
return useCaseSensitiveFileNames ? path.toLowerCase() : path;
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
var result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
@@ -231,14 +245,16 @@ module ts {
|
||||
var directories: string[] = [];
|
||||
for (let current of files) {
|
||||
var name = combinePaths(path, current);
|
||||
var stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
var stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
for (let current of directories) {
|
||||
|
||||
@@ -3,6 +3,14 @@ module ts {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
export interface FileMap<T> {
|
||||
get(fileName: string): T;
|
||||
set(fileName: string, value: T): void;
|
||||
contains(fileName: string): boolean;
|
||||
delete(fileName: string): void;
|
||||
forEachValue(f: (v: T) => void): void;
|
||||
}
|
||||
|
||||
export interface TextRange {
|
||||
pos: number;
|
||||
end: number;
|
||||
@@ -1168,7 +1176,7 @@ module ts {
|
||||
}
|
||||
|
||||
export interface ParseConfigHost {
|
||||
readDirectory(rootDir: string, extension: string): string[];
|
||||
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
|
||||
}
|
||||
|
||||
export interface WriteFileCallback {
|
||||
@@ -1197,6 +1205,7 @@ module ts {
|
||||
getGlobalDiagnostics(): Diagnostic[];
|
||||
getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[];
|
||||
getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[];
|
||||
/* @internal */ getCompilerOptionsDiagnostics(): Diagnostic[];
|
||||
|
||||
/**
|
||||
* Gets a type checker that can be used to semantically analyze source fils in the program.
|
||||
@@ -1582,14 +1591,15 @@ module ts {
|
||||
Tuple = 0x00002000, // Tuple
|
||||
Union = 0x00004000, // Union
|
||||
Anonymous = 0x00008000, // Anonymous
|
||||
Instantiated = 0x00010000, // Instantiated anonymous type
|
||||
/* @internal */
|
||||
FromSignature = 0x00010000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00020000, // Originates in an object literal
|
||||
FromSignature = 0x00020000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00040000, // Originates in an object literal
|
||||
/* @internal */
|
||||
ContainsUndefinedOrNull = 0x00040000, // Type is or contains Undefined or Null type
|
||||
ContainsUndefinedOrNull = 0x00080000, // Type is or contains Undefined or Null type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00080000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00100000, // Type of symbol primitive introduced in ES6
|
||||
ContainsObjectLiteral = 0x00100000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00200000, // Type of symbol primitive introduced in ES6
|
||||
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||
@@ -1674,8 +1684,8 @@ module ts {
|
||||
properties: Symbol[]; // Properties
|
||||
callSignatures: Signature[]; // Call signatures of type
|
||||
constructSignatures: Signature[]; // Construct signatures of type
|
||||
stringIndexType: Type; // String index type
|
||||
numberIndexType: Type; // Numeric index type
|
||||
stringIndexType?: Type; // String index type
|
||||
numberIndexType?: Type; // Numeric index type
|
||||
}
|
||||
|
||||
// Just a place to cache element types of iterables and iterators
|
||||
@@ -1731,7 +1741,6 @@ module ts {
|
||||
/* @internal */
|
||||
export interface TypeMapper {
|
||||
(t: TypeParameter): Type;
|
||||
mappings?: Map<Type>; // Type mapping cache
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -1985,6 +1985,21 @@ module ts {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const carriageReturnLineFeed = "\r\n";
|
||||
const lineFeed = "\n";
|
||||
export function getNewLineCharacter(options: CompilerOptions): string {
|
||||
if (options.newLine === NewLineKind.CarriageReturnLineFeed) {
|
||||
return carriageReturnLineFeed;
|
||||
}
|
||||
else if (options.newLine === NewLineKind.LineFeed) {
|
||||
return lineFeed;
|
||||
}
|
||||
else if (sys) {
|
||||
return sys.newLine
|
||||
}
|
||||
return carriageReturnLineFeed;
|
||||
}
|
||||
}
|
||||
|
||||
module ts {
|
||||
|
||||
Reference in New Issue
Block a user