diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f46ef3ed38..938d4987276 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2296,6 +2296,12 @@ module ts { return getTypeFromArrayTypeNode(node); case SyntaxKind.TypeLiteral: return getTypeFromTypeLiteralNode(node); + // This function assumes that an identifier or qualified name is a type expression + // Callers should first ensure this by calling isTypeNode + case SyntaxKind.Identifier: + case SyntaxKind.QualifiedName: + var symbol = getSymbolInfo(node); + return getDeclaredTypeOfSymbol(symbol); default: return unknownType; } @@ -6544,13 +6550,15 @@ module ts { return mapToArray(symbols); } - // True if the given identifier, string literal, or number literal is the name of a declaration node + // True if the given identifier is the name of a type declaration node (class, interface, enum, type parameter, etc) function isTypeDeclarationName(name: Node): boolean { - return name.kind == SyntaxKind.Identifier && isTypeDeclaration(name.parent); + return name.kind == SyntaxKind.Identifier && + isTypeDeclaration(name.parent) && + (name.parent).name === name; } // True if the given identifier, string literal, or number literal is the name of a declaration node - function isDeclarationName(name: Node): boolean { + function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { return false; } @@ -6607,7 +6615,6 @@ module ts { } function isExpression(node: Node): boolean { - // Omitted expression? switch (node.kind) { case SyntaxKind.ThisKeyword: case SyntaxKind.SuperKeyword: @@ -6629,6 +6636,7 @@ module ts { case SyntaxKind.PostfixOperator: case SyntaxKind.BinaryExpression: case SyntaxKind.ConditionalExpression: + case SyntaxKind.OmittedExpression: return true; case SyntaxKind.QualifiedName: while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent; @@ -6641,14 +6649,6 @@ module ts { case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: var parent = node.parent; - if (parent.kind === SyntaxKind.TypeAssertion) { - return node === (parent).operand; - } - - if (isExpression(parent)) { - return true; - } - switch (parent.kind) { case SyntaxKind.VariableDeclaration: case SyntaxKind.Parameter: @@ -6667,10 +6667,18 @@ module ts { case SyntaxKind.SwitchStatement: return (parent).expression === node; case SyntaxKind.ForStatement: - return (parent).initializer === node || (parent).condition === node || + return (parent).initializer === node || + (parent).condition === node || (parent).iterator === node; case SyntaxKind.ForInStatement: - return (parent).variable === node || (parent).expression === node; + return (parent).variable === node || + (parent).expression === node; + case SyntaxKind.TypeAssertion: + return node === (parent).operand; + default: + if (isExpression(parent)) { + return true; + } } } return false; @@ -6690,6 +6698,7 @@ module ts { case SyntaxKind.VoidKeyword: return node.parent.kind !== SyntaxKind.PrefixOperator; case SyntaxKind.StringLiteral: + // Specialized signatures can have string literals as their parameters' type names return node.parent.kind === SyntaxKind.Parameter; // Identifiers and qualified names may be type nodes, depending on their context. Climb // above them to find the lowest container @@ -6700,6 +6709,7 @@ module ts { } // Fall through case SyntaxKind.QualifiedName: + // At this point, node is either a qualified name or an identifier var parent = node.parent; if (parent.kind === SyntaxKind.TypeQuery) { return false; @@ -6710,7 +6720,7 @@ module ts { // // Calling isTypeNode would consider the qualified name A.B a type node. Only C or // A.B.C is a type node. - if (node.kind >= SyntaxKind.FirstTypeNode && node.kind <= SyntaxKind.LastTypeNode) { + if (parent.kind >= SyntaxKind.FirstTypeNode && parent.kind <= SyntaxKind.LastTypeNode) { return true; } switch (parent.kind) { @@ -6764,7 +6774,7 @@ module ts { } function getSymbolOfIdentifier(identifier: Identifier) { - if (isDeclarationName(identifier)) { + if (isDeclarationOrFunctionExpressionOrCatchVariableName(identifier)) { return getSymbolOfNode(identifier.parent); } @@ -6852,10 +6862,6 @@ module ts { return getTypeOfExpression(node); } if (isTypeNode(node)) { - if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) { - var symbol = getSymbolInfo(node); - return getDeclaredTypeOfSymbol(symbol); - } return getTypeFromTypeNode(node); } @@ -6876,7 +6882,7 @@ module ts { return getTypeOfSymbol(symbol); } - if (isDeclarationName(node)) { + if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { var symbol = getSymbolInfo(node); return getTypeOfSymbol(symbol); } diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 6b37d5765a5..87f215d5b72 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -76,15 +76,18 @@ class TypeWriterWalker { private log(node: ts.Node, type: ts.Type): void { var actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos); var lineAndCharacter = this.currentSourceFile.getLineAndCharacterFromPosition(actualPos); - var name = ts.getSourceTextOfNodeFromSourceText(this.currentSourceFile.text, node); - var isUnkownType = (type).intrinsicName === "unknown"; + var sourceText = ts.getSourceTextOfNodeFromSourceText(this.currentSourceFile.text, node); + var isUnknownType = (type).intrinsicName === "unknown"; + // If we got an unknown type, we temporarily want to fall back to just pretending the name + // (source text) of the node is the type. This is to align with the old typeWriter to make + // baseline comparisons easier. In the long term, we will want to just call typeToString this.results.push({ line: lineAndCharacter.line - 1, column: lineAndCharacter.character, syntaxKind: ts.SyntaxKind[node.kind], - identifierName: name, - type: isUnkownType ? name : this.checker.typeToString(type) + identifierName: sourceText, + type: isUnknownType ? sourceText : this.checker.typeToString(type) }); } diff --git a/src/services/services.ts b/src/services/services.ts index c1f86f89b24..e60bd18a4c2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1693,7 +1693,7 @@ module ts { // Right of dot member completion list if (isRightOfDot) { - var type: Type = typeInfoResolver.getApparentType(typeInfoResolver.getTypeOfNode(mappedNode)); + var type: ApparentType = typeInfoResolver.getApparentType(typeInfoResolver.getTypeOfNode(mappedNode)); if (!type) { return undefined; }