merge with master

This commit is contained in:
Vladimir Matveev
2015-06-04 10:57:34 -07:00
69 changed files with 2506 additions and 1865 deletions

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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,

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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 */

View File

@@ -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 {