Merge branch 'master' into tupleTypes

This commit is contained in:
Anders Hejlsberg
2014-09-15 11:04:58 -07:00
343 changed files with 9089 additions and 5260 deletions
+279 -212
View File
@@ -24,9 +24,9 @@ module ts {
}
/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
/// If fullTypeCheck === true - then typechecker should do every possible check to produce all errors
/// If fullTypeCheck === false - typechecker can shortcut and skip checks that only produce errors.
/// NOTE: checks that somehow affects decisions being made during typechecking should be executed in both cases.
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
/// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
/// NOTE: checks that somehow affect decisions being made during typechecking should be executed in both cases.
export function createTypeChecker(program: Program, fullTypeCheck: boolean): TypeChecker {
var Symbol = objectAllocator.getSymbolConstructor();
@@ -37,7 +37,9 @@ module ts {
var emptyArray: any[] = [];
var emptySymbols: SymbolTable = {};
var compilerOptions = program.getCompilerOptions();
var checker: TypeChecker = {
getProgram: () => program,
getDiagnostics: getDiagnostics,
@@ -412,7 +414,7 @@ module ts {
}
}
function getFullyQualifiedName(symbol: Symbol) {
function getFullyQualifiedName(symbol: Symbol): string {
return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
}
@@ -574,7 +576,7 @@ module ts {
return (resolveImport(symbol).flags & SymbolFlags.Value) !== 0;
}
// If it is an instantiated symbol, then it is a value if hte symbol it is an
// If it is an instantiated symbol, then it is a value if the symbol it is an
// instantiation of is a value.
if (symbol.flags & SymbolFlags.Instantiated) {
return (getSymbolLinks(symbol).target.flags & SymbolFlags.Value) !== 0;
@@ -697,7 +699,7 @@ module ts {
function getAccessibleSymbolChain(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): Symbol[] {
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] {
function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) {
// If the symbol is equivalent and doesnt need futher qualification, this symbol is accessible
// If the symbol is equivalent and doesn't need further qualification, this symbol is accessible
if (!needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning)) {
return true;
}
@@ -793,9 +795,9 @@ module ts {
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible: hasAccessibleDeclarations.aliasesToMakeVisible };
}
// If we havent got the accessible symbol doesnt mean the symbol is actually inaccessible.
// It could be qualified symbol and hence verify the path
// eg:
// If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible.
// It could be a qualified symbol and hence verify the path
// e.g.:
// module m {
// export class c {
// }
@@ -803,7 +805,7 @@ module ts {
// var x: typeof m.c
// In the above example when we start with checking if typeof m.c symbol is accessible,
// we are going to see if c can be accessed in scope directly.
// But it cant, hence the accessible is going to be undefined, but that doesnt mean m.c is accessible
// But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible
// It is accessible if the parent m is accessible because then m.c can be accessed through qualification
meaningToLook = getQualifiedLeftMeaning(meaning);
symbol = getParentOfSymbol(symbol);
@@ -815,7 +817,7 @@ module ts {
if (symbolExternalModule) {
var enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration);
if (symbolExternalModule !== enclosingExternalModule) {
// name from different external module that is not visibile
// name from different external module that is not visible
return {
accessibility: SymbolAccessibility.CannotBeNamed,
errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
@@ -892,7 +894,7 @@ module ts {
{ accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: firstIdentifierName };
}
// Enclosing declaration is optional when we dont want to get qualified name in the enclosing declaration scope
// Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
// Meaning needs to be specified if the enclosing declaration is given
function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
function getSymbolName(symbol: Symbol) {
@@ -907,8 +909,8 @@ module ts {
// Get qualified name
if (enclosingDeclaration &&
// Properties/methods/Signatures/Constructors/TypeParameters do not need qualification
!(symbol.flags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Signature | SymbolFlags.Constructor | SymbolFlags.Method | SymbolFlags.TypeParameter))) {
// TypeParameters do not need qualification
!(symbol.flags & SymbolFlags.TypeParameter)) {
var symbolName: string;
while (symbol) {
var isFirstName = !symbolName;
@@ -919,7 +921,7 @@ module ts {
currentSymbolName = ts.map(accessibleSymbolChain, accessibleSymbol => getSymbolName(accessibleSymbol)).join(".");
}
else {
// If we didnt find accessible symbol chain for this symbol, break if this is external module
// If we didn't find accessible symbol chain for this symbol, break if this is external module
if (!isFirstName && ts.forEach(symbol.declarations, declaration => hasExternalModuleSymbol(declaration))) {
break;
}
@@ -943,20 +945,37 @@ module ts {
writer.write(symbolToString(symbol, enclosingDeclaration, meaning));
}
function createSingleLineTextWriter() {
function createSingleLineTextWriter(maxLength?: number) {
var result = "";
var overflow = false;
function write(s: string) {
if (!overflow) {
result += s;
if (result.length > maxLength) {
result = result.substr(0, maxLength - 3) + "...";
overflow = true;
}
}
}
return {
write(s: string) { result += s; },
writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { writeSymbolToTextWriter(symbol, enclosingDeclaration, meaning, this); },
writeLine() { result += " "; },
write: write,
writeSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
writeSymbolToTextWriter(symbol, enclosingDeclaration, meaning, this);
},
writeLine() {
write(" ");
},
increaseIndent() { },
decreaseIndent() { },
getText() { return result; }
getText() {
return result;
}
};
}
function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
var stringWriter = createSingleLineTextWriter();
var maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100;
var stringWriter = createSingleLineTextWriter(maxLength);
// TODO(shkamat): typeToString should take enclosingDeclaration as input, once we have implemented enclosingDeclaration
writeTypeToTextWriter(type, enclosingDeclaration, flags, stringWriter);
return stringWriter.getText();
@@ -1003,7 +1022,7 @@ module ts {
function writeTypeReference(type: TypeReference) {
if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) {
// If we are writing array element type the arrow style signatures are not allowed as
// we need to surround it by curlies, eg. { (): T; }[]; as () => T[] would mean something different
// we need to surround it by curlies, e.g. { (): T; }[]; as () => T[] would mean something different
writeType(type.typeArguments[0], /*allowFunctionOrConstructorTypeLiteral*/ false);
writer.write("[]");
}
@@ -1257,7 +1276,7 @@ module ts {
!(node.kind !== SyntaxKind.ImportDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) {
return isGlobalSourceFile(parent) || isUsedInExportAssignment(node);
}
// Exported members/ambient module elements (exception import declaraiton) are visible if parent is visible
// Exported members/ambient module elements (exception import declaration) are visible if parent is visible
return isDeclarationVisible(parent);
case SyntaxKind.Property:
@@ -1348,10 +1367,14 @@ module ts {
}
// Use the type of the initializer expression if one is present
if (declaration.initializer) {
var unwidenedType = checkAndMarkExpression(declaration.initializer);
var type = getWidenedType(unwidenedType);
if (type !== unwidenedType) {
checkImplicitAny(type);
var type = checkAndMarkExpression(declaration.initializer);
// Widening of property assignments is handled by checkObjectLiteral, exclude them here
if (declaration.kind !== SyntaxKind.PropertyAssignment) {
var unwidenedType = type;
type = getWidenedType(type);
if (type !== unwidenedType) {
checkImplicitAny(type);
}
}
return type;
}
@@ -1361,7 +1384,7 @@ module ts {
return type;
function checkImplicitAny(type: Type) {
if (!fullTypeCheck || !program.getCompilerOptions().noImplicitAny) {
if (!fullTypeCheck || !compilerOptions.noImplicitAny) {
return;
}
// We need to have ended up with 'any', 'any[]', 'any[][]', etc.
@@ -1410,6 +1433,12 @@ module ts {
}
else if (links.type === resolvingType) {
links.type = anyType;
if (compilerOptions.noImplicitAny) {
var diagnostic = (<VariableDeclaration>symbol.valueDeclaration).type ?
Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation :
Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
}
}
return links.type;
}
@@ -1464,8 +1493,8 @@ module ts {
}
// Otherwise, fall back to 'any'.
else {
if (program.getCompilerOptions().noImplicitAny) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbol.name);
if (compilerOptions.noImplicitAny) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
}
type = anyType;
@@ -1479,6 +1508,10 @@ module ts {
}
else if (links.type === resolvingType) {
links.type = anyType;
if (compilerOptions.noImplicitAny) {
var getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
}
}
}
@@ -1542,7 +1575,7 @@ module ts {
function hasBaseType(type: InterfaceType, checkBase: InterfaceType) {
return check(type);
function check(type: InterfaceType) {
function check(type: InterfaceType): boolean {
var target = <InterfaceType>getTargetType(type);
return target === checkBase || forEach(target.baseTypes, check);
}
@@ -2046,6 +2079,15 @@ module ts {
}
else if (signature.resolvedReturnType === resolvingType) {
signature.resolvedReturnType = anyType;
if (compilerOptions.noImplicitAny) {
var declaration = <Declaration>signature.declaration;
if (declaration.name) {
error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, identifierToString(declaration.name));
}
else {
error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
}
}
}
return signature.resolvedReturnType;
}
@@ -3188,45 +3230,6 @@ module ts {
return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false;
}
function getWidenedTypeOfObjectLiteral(type: Type): Type {
var properties = getPropertiesOfType(type);
if (properties.length) {
var widenedTypes: Type[] = [];
var propTypeWasWidened: boolean = false;
forEach(properties, p => {
var propType = getTypeOfSymbol(p);
var widenedType = getWidenedType(propType);
if (propType !== widenedType) {
propTypeWasWidened = true;
if (program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
}
}
widenedTypes.push(widenedType);
});
if (propTypeWasWidened) {
var members: SymbolTable = {};
var index = 0;
forEach(properties, p => {
var symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name);
symbol.declarations = p.declarations;
symbol.parent = p.parent;
symbol.type = widenedTypes[index++];
symbol.target = p;
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
members[symbol.name] = symbol;
});
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
type = createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
}
}
return type;
}
function isArrayType(type: Type): boolean {
return type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType;
}
@@ -3238,14 +3241,8 @@ module ts {
return type;
}
function getWidenedTypeOfArrayLiteral(type: Type): Type {
var elementType = (<TypeReference>type).typeArguments[0];
var widenedType = getWidenedType(elementType);
type = elementType !== widenedType ? createArrayType(widenedType) : type;
return type;
}
function getWidenedType(type: Type): Type {
/* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */
function getWidenedType(type: Type, supressNoImplicitAnyErrors?: boolean): Type {
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
return anyType;
}
@@ -3256,6 +3253,54 @@ module ts {
return getWidenedTypeOfArrayLiteral(type);
}
return type;
function getWidenedTypeOfObjectLiteral(type: Type): Type {
var properties = getPropertiesOfType(type);
if (properties.length) {
var widenedTypes: Type[] = [];
var propTypeWasWidened: boolean = false;
forEach(properties, p => {
var propType = getTypeOfSymbol(p);
var widenedType = getWidenedType(propType);
if (propType !== widenedType) {
propTypeWasWidened = true;
if (!supressNoImplicitAnyErrors && program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
}
}
widenedTypes.push(widenedType);
});
if (propTypeWasWidened) {
var members: SymbolTable = {};
var index = 0;
forEach(properties, p => {
var symbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name);
symbol.declarations = p.declarations;
symbol.parent = p.parent;
symbol.type = widenedTypes[index++];
symbol.target = p;
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
members[symbol.name] = symbol;
});
var stringIndexType = getIndexTypeOfType(type, IndexKind.String);
var numberIndexType = getIndexTypeOfType(type, IndexKind.Number);
if (stringIndexType) stringIndexType = getWidenedType(stringIndexType);
if (numberIndexType) numberIndexType = getWidenedType(numberIndexType);
type = createAnonymousType(type.symbol, members, emptyArray, emptyArray, stringIndexType, numberIndexType);
}
}
return type;
}
function getWidenedTypeOfArrayLiteral(type: Type): Type {
var elementType = (<TypeReference>type).typeArguments[0];
var widenedType = getWidenedType(elementType, supressNoImplicitAnyErrors);
type = elementType !== widenedType ? createArrayType(widenedType) : type;
return type;
}
}
function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
@@ -3501,29 +3546,6 @@ module ts {
return getTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol));
}
function getThisContainer(node: Node): Node {
while (true) {
node = node.parent;
if (!node) {
return node;
}
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.Property:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.SourceFile:
case SyntaxKind.ArrowFunction:
return node;
}
}
}
function captureLexicalThis(node: Node, container: Node): void {
var classNode = container.parent && container.parent.kind === SyntaxKind.ClassDeclaration ? container.parent : undefined;
getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis;
@@ -3536,11 +3558,14 @@ module ts {
}
function checkThisExpression(node: Node): Type {
var container = getThisContainer(node);
// Stop at the first arrow function so that we can
// tell whether 'this' needs to be captured.
var container = getThisContainer(node, /* includeArrowFunctions */ true);
var needToCaptureLexicalThis = false;
// skip arrow functions
while (container.kind === SyntaxKind.ArrowFunction) {
container = getThisContainer(container);
// Now skip arrow functions to get the "real" owner of 'this'.
if (container.kind === SyntaxKind.ArrowFunction) {
container = getThisContainer(container, /* includeArrowFunctions */ false);
needToCaptureLexicalThis = true;
}
@@ -4059,7 +4084,7 @@ module ts {
}
// Fall back to any.
if (program.getCompilerOptions().noImplicitAny && objectType !== anyType) {
if (compilerOptions.noImplicitAny && objectType !== anyType) {
error(node, Diagnostics.Index_signature_of_object_type_implicitly_has_an_any_type);
}
@@ -4120,7 +4145,7 @@ module ts {
}
else {
// current declaration belongs to a different symbol
// set cutoffPos so reorderings in the future won't change result set from 0 to cutoffPos
// set cutoffPos so re-orderings in the future won't change result set from 0 to cutoffPos
pos = cutoffPos = result.length;
lastParent = parent;
}
@@ -4157,19 +4182,6 @@ module ts {
return getSignatureInstantiation(signature, getInferredTypes(context));
}
// Inferentially type an expression by a contextual parameter type (section 4.12.2 in TypeScript spec)
function inferentiallyTypeExpession(expr: Expression, contextualType: Type, contextualMapper: TypeMapper): Type {
var type = checkExpressionWithContextualType(expr, contextualType, contextualMapper);
var signature = getSingleCallSignature(type);
if (signature && signature.typeParameters) {
var contextualSignature = getSingleCallSignature(contextualType);
if (contextualSignature && !contextualSignature.typeParameters) {
type = getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
}
}
return type;
}
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument?: boolean[]): Type[] {
var typeParameters = signature.typeParameters;
var context = createInferenceContext(typeParameters);
@@ -4178,7 +4190,7 @@ module ts {
for (var i = 0; i < args.length; i++) {
if (!excludeArgument || excludeArgument[i] === undefined) {
var parameterType = getTypeAtPosition(signature, i);
inferTypes(context, inferentiallyTypeExpession(args[i], parameterType, mapper), parameterType);
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
}
}
// Next, infer from those context sensitive arguments that are no longer excluded
@@ -4186,7 +4198,7 @@ module ts {
for (var i = 0; i < args.length; i++) {
if (excludeArgument[i] === false) {
var parameterType = getTypeAtPosition(signature, i);
inferTypes(context, inferentiallyTypeExpession(args[i], parameterType, mapper), parameterType);
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
}
}
}
@@ -4404,7 +4416,7 @@ module ts {
var declaration = signature.declaration;
if (declaration && (declaration.kind !== SyntaxKind.Constructor && declaration.kind !== SyntaxKind.ConstructSignature)) {
// When resolved signature is a call signature (and not a construct signature) the result type is any
if (program.getCompilerOptions().noImplicitAny) {
if (compilerOptions.noImplicitAny) {
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
}
return anyType;
@@ -4417,9 +4429,9 @@ module ts {
var exprType = checkExpression(node.operand);
var targetType = getTypeFromTypeNode(node.type);
if (fullTypeCheck && targetType !== unknownType) {
var widenedType = getWidenedType(exprType);
if (!(isTypeAssignableTo(exprType, targetType) || isTypeAssignableTo(targetType, widenedType))) {
checkTypeAssignableTo(targetType, widenedType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other_Colon, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
var widenedType = getWidenedType(exprType, /*supressNoImplicitAnyErrors*/ true);
if (!(isTypeAssignableTo(targetType, widenedType))) {
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other_Colon, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
}
}
return targetType;
@@ -4450,7 +4462,7 @@ module ts {
var unwidenedType = checkAndMarkExpression(func.body, contextualMapper);
var widenedType = getWidenedType(unwidenedType);
if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
if (fullTypeCheck && compilerOptions.noImplicitAny && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
error(func, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeToString(widenedType));
}
@@ -4472,7 +4484,7 @@ module ts {
var widenedType = getWidenedType(commonType);
// Check and report for noImplicitAny if the best common type implicitly gets widened to an 'any'/arrays-of-'any' type.
if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
if (fullTypeCheck && compilerOptions.noImplicitAny && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
var typeName = typeToString(widenedType);
if (func.name) {
@@ -4489,37 +4501,6 @@ module ts {
return voidType;
}
// WARNING: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
return traverse(body);
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(node);
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabelledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
return forEachChild(node, traverse);
}
}
}
/// Returns a set of types relating to every return expression relating to a function block.
function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper): Type[] {
var aggregatedTypes: Type[] = [];
@@ -4612,27 +4593,28 @@ module ts {
}
}
}
checkSignatureDeclaration(node);
}
}
if (fullTypeCheck && !(links.flags & NodeCheckFlags.TypeChecked)) {
checkSignatureDeclaration(node);
if (node.type) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
}
if (node.body.kind === SyntaxKind.FunctionBlock) {
checkSourceElement(node.body);
}
else {
var exprType = checkExpression(node.body);
if (node.type) {
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, undefined, undefined);
}
}
links.flags |= NodeCheckFlags.TypeChecked;
}
return type;
}
function checkFunctionExpressionBody(node: FunctionExpression) {
if (node.type) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
}
if (node.body.kind === SyntaxKind.FunctionBlock) {
checkSourceElement(node.body);
}
else {
var exprType = checkExpression(node.body);
if (node.type) {
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, undefined, undefined);
}
checkFunctionExpressionBodies(node.body);
}
}
function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean {
if (!(type.flags & (TypeFlags.Any | TypeFlags.NumberLike))) {
error(operand, diagnostic);
@@ -4869,7 +4851,7 @@ module ts {
var ok = checkReferenceExpression(node.left, Diagnostics.Invalid_left_hand_side_of_assignment_expression);
// Use default messages
if (ok) {
// to avoid cascading errors check assignability only if 'isReference' check succeded and no errors were reported
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
checkTypeAssignableTo(valueType, leftType, node.left, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
}
}
@@ -4915,11 +4897,28 @@ module ts {
// Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
// contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
// expression is being inferentially typed (section 4.12.2 in spec) and provides the type mapper to use in
// conjuction with the generic contextual type. When contextualMapper is equal to the identityMapper function
// conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function
// object, it serves as an indicator that all contained function and arrow expressions should be considered to
// have the wildcard function type; this form of type check is used during overload resolution to exclude
// contextually typed function and arrow expressions in the initial phase.
function checkExpression(node: Expression, contextualMapper?: TypeMapper): Type {
var type = checkExpressionNode(node, contextualMapper);
if (contextualMapper && contextualMapper !== identityMapper) {
var signature = getSingleCallSignature(type);
if (signature && signature.typeParameters) {
var contextualType = getContextualType(node);
if (contextualType) {
var contextualSignature = getSingleCallSignature(contextualType);
if (contextualSignature && !contextualSignature.typeParameters) {
type = getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper));
}
}
}
}
return type;
}
function checkExpressionNode(node: Expression, contextualMapper: TypeMapper): Type {
switch (node.kind) {
case SyntaxKind.Identifier:
return checkIdentifier(<Identifier>node);
@@ -5020,7 +5019,7 @@ module ts {
// legal case - parameter initializer references some parameter strictly on left of current parameter declaration
return;
}
// fallthrough to error reporting
// fall through to error reporting
}
error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, identifierToString(parameterDeclaration.name), identifierToString(<Identifier>n));
@@ -5047,7 +5046,7 @@ module ts {
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
checkCollisionWithArgumentsInGeneratedCode(node);
if (program.getCompilerOptions().noImplicitAny && !node.type) {
if (compilerOptions.noImplicitAny && !node.type) {
switch (node.kind) {
case SyntaxKind.ConstructSignature:
error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
@@ -5416,7 +5415,7 @@ module ts {
}
// when checking exported function declarations across modules check only duplicate implementations
// names and consistensy of modifiers are verified when we check local symbol
// names and consistency of modifiers are verified when we check local symbol
var isExportSymbolInsideModule = symbol.parent && symbol.parent.flags & SymbolFlags.Module;
for (var i = 0; i < declarations.length; i++) {
var node = <FunctionDeclaration>declarations[i];
@@ -5512,7 +5511,7 @@ module ts {
var symbol: Symbol;
// Exports should be checked only if enclosing module contains both exported and non exported declarations.
// In case if all declarations are non-exported check is unnecesary.
// In case if all declarations are non-exported check is unnecessary.
// if localSymbol is defined on node then node itself is exported - check is required
var symbol = node.localSymbol;
@@ -5607,7 +5606,7 @@ module ts {
}
// If there is no body and no explicit return type, then report an error.
if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && !node.body && !node.type) {
if (fullTypeCheck && compilerOptions.noImplicitAny && !node.body && !node.type) {
// Ignore privates within ambient contexts; they exist purely for documentative purposes to avoid name clashing.
// (e.g. privates within .d.ts files do not expose type information)
if (!isPrivateWithinAmbient(node)) {
@@ -5924,17 +5923,6 @@ module ts {
// TODO: Check that target label is valid
}
function getContainingFunction(node: Node): SignatureDeclaration {
while (true) {
node = node.parent;
if (!node || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression ||
node.kind === SyntaxKind.ArrowFunction || node.kind === SyntaxKind.Method || node.kind === SyntaxKind.Constructor ||
node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
return <SignatureDeclaration>node;
}
}
}
function checkReturnStatement(node: ReturnStatement) {
if (node.expression && !(getNodeLinks(node.expression).flags & NodeCheckFlags.TypeChecked)) {
var func = getContainingFunction(node);
@@ -5957,7 +5945,7 @@ module ts {
checkTypeAssignableTo(checkExpression(node.expression), returnType, node.expression, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
}
else if (func.kind == SyntaxKind.Constructor) {
// constructor doesn't have explicit return type annontation and yet its return type is known - declaring type
// constructor doesn't have explicit return type annotation and yet its return type is known - declaring type
// handle constructors and issue specialized error message for them.
if (!isTypeAssignableTo(checkExpression(node.expression), returnType)) {
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
@@ -6204,7 +6192,7 @@ module ts {
}
if ((base.flags & derived.flags & SymbolFlags.Method) || ((base.flags & SymbolFlags.PropertyOrAccessor) && (derived.flags & SymbolFlags.PropertyOrAccessor))) {
// method is overridden with method or property\accessor is overridden with property\accessor - correct case
// method is overridden with method or property/accessor is overridden with property/accessor - correct case
continue;
}
@@ -6532,9 +6520,10 @@ module ts {
case SyntaxKind.FunctionDeclaration:
return checkFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.Block:
return checkBlock(<Block>node);
case SyntaxKind.FunctionBlock:
case SyntaxKind.ModuleBlock:
return checkBlock(<Block>node);
return checkBody(<Block>node);
case SyntaxKind.VariableStatement:
return checkVariableStatement(<VariableStatement>node);
case SyntaxKind.ExpressionStatement:
@@ -6581,13 +6570,91 @@ module ts {
}
}
// Function expression bodies are checked after all statements in the enclosing body. This is to ensure
// constructs like the following are permitted:
// var foo = function () {
// var s = foo();
// return "hello";
// }
// Here, performing a full type check of the body of the function expression whilst in the process of
// determining the type of foo would cause foo to be given type any because of the recursive reference.
// Delaying the type check of the body ensures foo has been assigned a type.
function checkFunctionExpressionBodies(node: Node): void {
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
forEach((<FunctionDeclaration>node).parameters, checkFunctionExpressionBodies);
checkFunctionExpressionBody(<FunctionExpression>node);
break;
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionDeclaration:
forEach((<FunctionDeclaration>node).parameters, checkFunctionExpressionBodies);
break;
case SyntaxKind.WithStatement:
checkFunctionExpressionBodies((<WithStatement>node).expression);
break;
case SyntaxKind.Parameter:
case SyntaxKind.Property:
case SyntaxKind.ArrayLiteral:
case SyntaxKind.ObjectLiteral:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyAccess:
case SyntaxKind.IndexedAccess:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TypeAssertion:
case SyntaxKind.ParenExpression:
case SyntaxKind.PrefixOperator:
case SyntaxKind.PostfixOperator:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.VariableStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.BreakStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabelledStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.SourceFile:
forEachChild(node, checkFunctionExpressionBodies);
break;
}
}
function checkBody(node: Block) {
checkBlock(node);
checkFunctionExpressionBodies(node);
}
// Fully type check a source file and collect the relevant diagnostics.
function checkSourceFile(node: SourceFile) {
var links = getNodeLinks(node);
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
emitExtends = false;
potentialThisCollisions.length = 0;
forEach(node.statements, checkSourceElement);
checkBody(node);
if (isExternalModule(node)) {
var symbol = getExportAssignmentSymbol(node.symbol);
if (symbol && symbol.flags & SymbolFlags.Import) {
@@ -6636,7 +6703,7 @@ module ts {
// Language service support
function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
function findChildAtPosition(parent: Node) {
function findChildAtPosition(parent: Node): Node {
var child = forEachChild(parent, node => {
if (position >= node.pos && position <= node.end && position >= getTokenPosOfNode(node)) {
return findChildAtPosition(node);
@@ -6979,7 +7046,7 @@ module ts {
return moduleType ? moduleType.symbol : undefined;
}
// Intentinal fallthrough
// Intentional fall-through
case SyntaxKind.NumericLiteral:
// index access
if (node.parent.kind == SyntaxKind.IndexedAccess && (<IndexedAccess>node.parent).index === node) {
@@ -7044,7 +7111,7 @@ module ts {
var apparentType = getApparentType(type);
if (apparentType.flags & TypeFlags.ObjectType) {
// Augment the apprent type with Function and Object memeber as applicaple
// Augment the apparent type with Function and Object members as applicable
var propertiesByName: Map<Symbol> = {};
var results: Symbol[] = [];
@@ -7175,7 +7242,7 @@ module ts {
function shouldEmitDeclarations() {
// If the declaration emit and there are no errors being reported in program or by checker
// declarations can be emitted
return program.getCompilerOptions().declaration &&
return compilerOptions.declaration &&
!program.getDiagnostics().length &&
!getDiagnostics().length;
}
@@ -7201,17 +7268,17 @@ module ts {
var symbol = getSymbolOfNode(node);
var signaturesOfSymbol = getSignaturesOfSymbol(symbol);
// If this function body corresponds to function with multiple signature, it is implementation of overload
// eg: function foo(a: string): string;
// function foo(a: number): number;
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
// e.g.: function foo(a: string): string;
// function foo(a: number): number;
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
return signaturesOfSymbol.length > 1 ||
// If there is single signature for the symbol, it is overload if that signature isnt coming from the node
// eg: function foo(a: string): string;
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
// If there is single signature for the symbol, it is overload if that signature isn't coming from the node
// e.g.: function foo(a: string): string;
// function foo(a: any) { // This is implementation of the overloads
// return a;
// }
(signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node);
}
return false;
+6
View File
@@ -204,6 +204,9 @@ module ts {
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
Debug.assert(start >= 0, "start must be non-negative, is " + start);
Debug.assert(length >= 0, "length must be non-negative, is " + length);
var text = getLocaleSpecificMessage(message.key);
if (arguments.length > 4) {
@@ -258,6 +261,9 @@ module ts {
}
export function flattenDiagnosticChain(file: SourceFile, start: number, length: number, diagnosticChain: DiagnosticMessageChain, newLine: string): Diagnostic {
Debug.assert(start >= 0, "start must be non-negative, is " + start);
Debug.assert(length >= 0, "length must be non-negative, is " + length);
var code = diagnosticChain.code;
var category = diagnosticChain.category;
var messageText = "";
@@ -391,6 +391,10 @@ module ts {
Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
_0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 7021, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation." },
_0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: { code: 7022, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer." },
_0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7023, category: DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
};
}
+16
View File
@@ -1561,6 +1561,22 @@
"category": "Error",
"code": 7020
},
"'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.": {
"category": "Error",
"code": 7021
},
"'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer.": {
"category": "Error",
"code": 7022
},
"'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.": {
"category": "Error",
"code": 7023
},
"Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.": {
"category": "Error",
"code": 7024
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000
+50 -57
View File
@@ -266,7 +266,7 @@ module ts {
}
}
else {
// Single line comment of styly //....
// Single line comment of style //....
writer.write(currentSourceFile.text.substring(comment.pos, comment.end));
}
@@ -393,7 +393,7 @@ module ts {
}
var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
// Line/Comma deliminators
// Line/Comma delimiters
if (lastEncodedSourceMapSpan.emittedLine == lastRecordedSourceMapSpan.emittedLine) {
// Emit comma to separate the entry
if (sourceMapData.sourceMapMappings) {
@@ -401,7 +401,7 @@ module ts {
}
}
else {
// Emit line deliminators
// Emit line delimiters
for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
sourceMapData.sourceMapMappings += ";";
}
@@ -470,7 +470,7 @@ module ts {
var emittedLine = writer.getLine();
var emittedColumn = writer.getColumn();
// If this location wasnt recorded or the location in source is going backwards, record the span
// If this location wasn't recorded or the location in source is going backwards, record the span
if (!lastRecordedSourceMapSpan ||
lastRecordedSourceMapSpan.emittedLine != emittedLine ||
lastRecordedSourceMapSpan.emittedColumn != emittedColumn ||
@@ -516,7 +516,7 @@ module ts {
}
function recordNewSourceFileStart(node: SourceFile) {
// Add the the file to tsFilePaths
// Add the file to tsFilePaths
// If sourceroot option: Use the relative path corresponding to the common directory path
// otherwise source locations relative to map file location
var sourcesDirectoryPath = compilerOptions.sourceRoot ? program.getCommonSourceDirectory() : sourceMapDir;
@@ -953,7 +953,7 @@ module ts {
write(tokenToString(node.operator));
}
// In some cases, we need to emit a space between the operator and the operand. One obvious case
// is when the operator is an identifer, like delete or typeof. We also need to do this for plus
// is when the operator is an identifier, like delete or typeof. We also need to do this for plus
// and minus expressions in certain cases. Specifically, consider the following two cases (parens
// are just for clarity of exposition, and not part of the source code):
//
@@ -1755,16 +1755,13 @@ module ts {
if (!isInstantiated(node)) {
return emitPinnedOrTripleSlashComments(node);
}
emitLeadingComments(node);
if (!(node.flags & NodeFlags.Export)) {
emitStart(node);
write("var ");
emit(node.name);
write(";");
emitEnd(node);
writeLine();
}
emitStart(node);
write("var ");
emit(node.name);
write(";");
emitEnd(node);
writeLine();
emitStart(node);
write("(function (");
emitStart(node.name);
@@ -1788,21 +1785,15 @@ module ts {
scopeEmitEnd();
}
write(")(");
if (node.flags & NodeFlags.Export) {
emit(node.name);
write(" = ");
}
emitModuleMemberName(node);
write(" || (");
emitModuleMemberName(node);
write(" = {}));");
emitEnd(node);
if (node.flags & NodeFlags.Export) {
writeLine();
emitStart(node);
write("var ");
emit(node.name);
write(" = ");
emitModuleMemberName(node);
emitEnd(node);
write(";");
}
emitTrailingComments(node);
}
@@ -1982,7 +1973,7 @@ module ts {
}
}
function emitNode(node: Node) {
function emitNode(node: Node): void {
if (!node) {
return;
}
@@ -2125,7 +2116,7 @@ module ts {
}
function getLeadingCommentsToEmit(node: Node) {
// Emit the leading comments only if the parent's pos doesnt match because parent should take care of emitting these comments
// Emit the leading comments only if the parent's pos doesn't match because parent should take care of emitting these comments
if (node.parent.kind === SyntaxKind.SourceFile || node.pos !== node.parent.pos) {
var leadingComments: Comment[];
if (hasDetachedComments(node.pos)) {
@@ -2148,7 +2139,7 @@ module ts {
}
function emitTrailingDeclarationComments(node: Node) {
// Emit the trailing comments only if the parent's end doesnt match
// Emit the trailing comments only if the parent's end doesn't match
if (node.parent.kind === SyntaxKind.SourceFile || node.end !== node.parent.end) {
var trailingComments = getTrailingComments(currentSourceFile.text, node.end);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
@@ -2224,7 +2215,7 @@ module ts {
return currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.exclamation;
}
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
// so that we dont end up computing comment string and doing match for all // comments
// so that we don't end up computing comment string and doing match for all // comments
else if (currentSourceFile.text.charCodeAt(comment.pos + 1) === CharacterCodes.slash &&
comment.pos + 2 < comment.end &&
currentSourceFile.text.charCodeAt(comment.pos + 2) === CharacterCodes.slash &&
@@ -2700,7 +2691,7 @@ module ts {
}
function emitVariableDeclaration(node: VariableDeclaration) {
// If we are emitting property it isnt moduleElement and hence we already know it needs to be emitted
// If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
// so there is no check needed to see if declaration is visible
if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
emitSourceTextOfNode(node.name);
@@ -2724,7 +2715,7 @@ module ts {
Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 :
Diagnostics.Exported_variable_0_has_or_is_using_private_name_1;
}
// This check is to ensure we dont report error on constructor parameter property as that error would be reported during parameter emit
// This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
else if (node.kind === SyntaxKind.Property) {
if (node.flags & NodeFlags.Static) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
@@ -2829,7 +2820,7 @@ module ts {
}
function emitFunctionDeclaration(node: FunctionDeclaration) {
// If we are emitting Method/Constructor it isnt moduleElement and hence already determined to be emitting
// If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting
// so no need to verify if the declaration is visible
if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) &&
!resolver.isImplementationOfOverload(node)) {
@@ -3080,9 +3071,7 @@ module ts {
}
function resolveScriptReference(sourceFile: SourceFile, reference: FileReference) {
var referenceFileName = compilerOptions.noResolve
? reference.filename
: normalizePath(combinePaths(getDirectoryPath(sourceFile.filename), reference.filename));
var referenceFileName = normalizePath(combinePaths(getDirectoryPath(sourceFile.filename), reference.filename));
return program.getSourceFile(referenceFileName);
}
@@ -3107,22 +3096,24 @@ module ts {
}
if (root) {
// Emiting single file so emit references in this file only
var addedGlobalFileReference = false;
forEach(root.referencedFiles, fileReference => {
var referencedFile = resolveScriptReference(root, fileReference);
// Emitting just a single file, so emit references in this file only
if (!compilerOptions.noResolve) {
var addedGlobalFileReference = false;
forEach(root.referencedFiles, fileReference => {
var referencedFile = resolveScriptReference(root, fileReference);
// All the references that are not going to be part of same file
if ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
shouldEmitToOwnFile(referencedFile) || // This is referenced file is emitting its own js file
!addedGlobalFileReference) { // Or the global out file corresponding to this reference was not added
// All the references that are not going to be part of same file
if ((referencedFile.flags & NodeFlags.DeclarationFile) || // This is a declare file reference
shouldEmitToOwnFile(referencedFile) || // This is referenced file is emitting its own js file
!addedGlobalFileReference) { // Or the global out file corresponding to this reference was not added
writeReferencePath(referencedFile);
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
addedGlobalFileReference = true;
writeReferencePath(referencedFile);
if (!isExternalModuleOrDeclarationFile(referencedFile)) {
addedGlobalFileReference = true;
}
}
}
});
});
}
emitNode(root);
}
@@ -3132,17 +3123,19 @@ module ts {
forEach(program.getSourceFiles(), sourceFile => {
if (!isExternalModuleOrDeclarationFile(sourceFile)) {
// Check what references need to be added
forEach(sourceFile.referencedFiles, fileReference => {
var referencedFile = resolveScriptReference(sourceFile, fileReference);
if (!compilerOptions.noResolve) {
forEach(sourceFile.referencedFiles, fileReference => {
var referencedFile = resolveScriptReference(sourceFile, fileReference);
// If the reference file is declaration file or external module emit that reference
if (isExternalModuleOrDeclarationFile(referencedFile) &&
!contains(emittedReferencedFiles, referencedFile)) { // If the file refernece was not already emitted
// If the reference file is a declaration file or an external module, emit that reference
if (isExternalModuleOrDeclarationFile(referencedFile) &&
!contains(emittedReferencedFiles, referencedFile)) { // If the file reference was not already emitted
writeReferencePath(referencedFile);
emittedReferencedFiles.push(referencedFile);
}
});
writeReferencePath(referencedFile);
emittedReferencedFiles.push(referencedFile);
}
});
}
emitNode(sourceFile);
}
+119 -17
View File
@@ -81,7 +81,7 @@ module ts {
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
node = getErrorSpanForNode(node);
var file = getSourceFileOfNode(node);
var start = skipTrivia(file.text, node.pos);
var start = node.kind === SyntaxKind.Missing ? node.pos : skipTrivia(file.text, node.pos);
var length = node.end - start;
return createFileDiagnostic(file, start, length, message, arg0, arg1, arg2);
@@ -141,11 +141,11 @@ module ts {
export function getLeadingCommentsOfNode(node: Node, sourceFileOfNode: SourceFile) {
// If parameter/type parameter, the prev token trailing comments are part of this node too
if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) {
// eg (/** blah */ a, /** blah */ b);
// e.g. (/** blah */ a, /** blah */ b);
return concatenate(getTrailingComments(sourceFileOfNode.text, node.pos),
// eg: (
// /** blah */ a,
// /** blah */ b);
// e.g.: (
// /** blah */ a,
// /** blah */ b);
getLeadingComments(sourceFileOfNode.text, node.pos));
}
else {
@@ -157,7 +157,7 @@ module ts {
return filter(getLeadingCommentsOfNode(node, sourceFileOfNode), comment => isJsDocComment(comment));
function isJsDocComment(comment: Comment) {
// js doc is if comment is starting with /** but not if it is /**/
// True if the comment starts with '/**' but not if it is '/**/'
return sourceFileOfNode.text.charCodeAt(comment.pos + 1) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 2) === CharacterCodes.asterisk &&
sourceFileOfNode.text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash;
@@ -352,6 +352,107 @@ module ts {
}
}
// Warning: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
export function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
return traverse(body);
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(node);
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabelledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
return forEachChild(node, traverse);
}
}
}
export function isAnyFunction(node: Node): boolean {
if (node) {
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Method:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
return true;
}
}
return false;
}
export function getContainingFunction(node: Node): SignatureDeclaration {
while (true) {
node = node.parent;
if (!node || isAnyFunction(node)) {
return <SignatureDeclaration>node;
}
}
}
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.ArrowFunction:
if (!includeArrowFunctions) {
continue;
}
// Fall through
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.Property:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.SourceFile:
return node;
}
}
}
export function getSuperContainer(node: Node): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.Property:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return node;
}
}
}
export function hasRestParameters(s: SignatureDeclaration): boolean {
return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0;
}
@@ -665,7 +766,7 @@ module ts {
}
function reportInvalidUseInStrictMode(node: Identifier): void {
// identifierToString cannot be used here since it uses backreference to 'parent' that is not yet set
// identifierToString cannot be used here since it uses a backreference to 'parent' that is not yet set
var name = sourceText.substring(skipTrivia(sourceText, node.pos), node.end);
grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name);
}
@@ -736,7 +837,7 @@ module ts {
lookAheadMode = LookAheadMode.NoErrorYet;
var result = callback();
// If we switched from 1 to to -1 then a parse error occurred during the callback.
// If we switched from 1 to -1 then a parse error occurred during the callback.
// If that's the case, then we want to act as if we never got any result at all.
Debug.assert(lookAheadMode === LookAheadMode.Error || lookAheadMode === LookAheadMode.NoErrorYet);
if (lookAheadMode === LookAheadMode.Error) {
@@ -1654,7 +1755,7 @@ module ts {
// (i.e. they're both BinaryExpressions with an assignment operator in it).
// First, check if we have an arrow function (production '4') that starts with a parenthesized
// parameter list. If we do, we must *not* recurse for productsion 1, 2 or 3. An ArrowFunction is
// parameter list. If we do, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
// not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done
// with AssignmentExpression if we see one.
var arrowExpression = tryParseParenthesizedArrowFunctionExpression();
@@ -1842,7 +1943,7 @@ module ts {
if (token === SyntaxKind.EqualsGreaterThanToken) {
// ERROR RECOVERY TWEAK:
// If we see a standalone => try to parse it as an arrow function expression as that's
// likely whatthe user intended to write.
// likely what the user intended to write.
return Tristate.True;
}
// Definitely not a parenthesized arrow function.
@@ -2745,8 +2846,8 @@ module ts {
switch (token) {
case SyntaxKind.SemicolonToken:
// If we're in error recovery, then we don't want to treat ';' as an empty statement.
// The problem is that ';' can show up in far too many contexts, and if we see one
// and assume it's a statement, then we may bail out innapropriately from whatever
// The problem is that ';' can show up in far too many contexts, and if we see one
// and assume it's a statement, then we may bail out inappropriately from whatever
// we're parsing. For example, if we have a semicolon in the middle of a class, then
// we really don't want to assume the class is over and we're on a statement in the
// outer module. We just want to consume and move on.
@@ -2896,10 +2997,11 @@ module ts {
parseExpected(SyntaxKind.VarKeyword);
node.declarations = parseVariableDeclarationList(flags, /*noIn*/false);
parseSemicolon();
finishNode(node);
if (!node.declarations.length && file.syntacticErrors.length === errorCountBeforeVarStatement) {
grammarErrorOnNode(node, Diagnostics.Variable_declaration_list_cannot_be_empty);
}
return finishNode(node);
return node;
}
function parseFunctionDeclaration(pos?: number, flags?: NodeFlags): FunctionDeclaration {
@@ -3306,7 +3408,7 @@ module ts {
function isIntegerLiteral(expression: Expression): boolean {
function isInteger(literalExpression: LiteralExpression): boolean {
// Allows for scientific notation since literalExpression.text was formed by
// coercing a number to a string. Sometimes this coersion can yield a string
// coercing a number to a string. Sometimes this coercion can yield a string
// in scientific notation.
// We also don't need special logic for hex because a hex integer is converted
// to decimal when it is coerced.
@@ -3328,7 +3430,7 @@ module ts {
var inConstantEnumMemberSection = true;
// In an ambient declaration, the grammar only allows integer literals as initializers.
// In a nonambient declaration, the grammar allows uninitialized members only in a
// In a non-ambient declaration, the grammar allows uninitialized members only in a
// ConstantEnumMemberSection, which starts at the beginning of an enum declaration
// or any time an integer literal initializer is encountered.
function parseAndCheckEnumMember(): EnumMember {
@@ -3451,7 +3553,7 @@ module ts {
return finishNode(node);
}
function isDeclaration() {
function isDeclaration(): boolean {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.FunctionKeyword:
@@ -3868,7 +3970,7 @@ module ts {
commonSourceDirectory = getNormalizedPathFromPathCompoments(commonPathComponents);
if (commonSourceDirectory) {
// Make sure directory path ends with directory separator so this string can directly
// used to replace with "" to get the relative path of the source file and the relative path doesnt
// used to replace with "" to get the relative path of the source file and the relative path doesn't
// start with / making it rooted path
commonSourceDirectory += directorySeparator;
}
+4 -4
View File
@@ -192,7 +192,7 @@ module ts {
return false;
}
// Perform binary search in one of the unicode range maps
// Perform binary search in one of the Unicode range maps
var lo: number = 0;
var hi: number = map.length;
var mid: number;
@@ -281,8 +281,8 @@ module ts {
if (lineNumber < 0) {
// If the actual position was not found,
// the binary search returns the negative value of the next line start
// eg. if line starts at [5, 10, 23, 80] and position requested was 20
// the search will return -2
// e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
// then the search will return -2
lineNumber = (~lineNumber) - 1;
}
return {
@@ -369,7 +369,7 @@ module ts {
// Extract comments from the given source text starting at the given position. If trailing is false, whitespace is skipped until
// the first line break and comments between that location and the next token are returned. If trailing is true, comments occurring
// between the given position and the next line break are returned. The return value is an array containing a TextRange for each
// comment. Single-line comment ranges include the the beginning '//' characters but not the ending line break. Multi-line comment
// comment. Single-line comment ranges include the beginning '//' characters but not the ending line break. Multi-line comment
// ranges include the beginning '/* and ending '*/' characters. The return value is undefined if no comments were found.
function getCommentRanges(text: string, pos: number, trailing: boolean): Comment[] {
var result: Comment[];
+8 -10
View File
@@ -220,8 +220,8 @@ module ts {
FirstFutureReservedWord = ImplementsKeyword,
LastFutureReservedWord = YieldKeyword,
FirstTypeNode = TypeReference,
LastTypeNode = ArrayType,
FirstPunctuation= OpenBraceToken,
LastTypeNode = TupleType,
FirstPunctuation = OpenBraceToken,
LastPunctuation = CaretEqualsToken
}
@@ -636,12 +636,10 @@ module ts {
}
export enum TypeFormatFlags {
None = 0x00000000,
/** writes Array<T> instead T[] */
WriteArrayAsGenericType = 0x00000001, // Declarations
UseTypeOfFunction = 0x00000002, // instead of writing signature type of function use typeof
None = 0x00000000,
WriteArrayAsGenericType = 0x00000001, // Write Array<T> instead T[]
UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal
NoTruncation = 0x00000004, // Don't truncate typeToString result
}
export enum SymbolAccessibility {
@@ -653,7 +651,7 @@ module ts {
export interface SymbolAccessiblityResult {
accessibility: SymbolAccessibility;
errorSymbolName?: string // Optional symbol name that results in error
errorModuleName?: string // If the symbol is not visibile from module, module's name
errorModuleName?: string // If the symbol is not visible from module, module's name
aliasesToMakeVisible?: ImportDeclaration[]; // aliases that need to have this symbol visible
}
@@ -968,6 +966,7 @@ module ts {
locale?: string;
mapRoot?: string;
module?: ModuleKind;
noErrorTruncation?: boolean;
noImplicitAny?: boolean;
noLib?: boolean;
noLibCheck?: boolean;
@@ -980,7 +979,6 @@ module ts {
target?: ScriptTarget;
version?: boolean;
watch?: boolean;
[option: string]: any;
}