Skip to content

Commit 12a0909

Browse files
committed
Add getTypeOfNode function to checker API
1 parent 96fba4d commit 12a0909

File tree

3 files changed

+171
-70
lines changed

3 files changed

+171
-70
lines changed

src/compiler/checker.ts

Lines changed: 166 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,16 @@ module ts {
8181
getTypeCount: () => typeCount,
8282
checkProgram: checkProgram,
8383
emitFiles: invokeEmitter,
84-
getSymbolOfNode: getSymbolOfNode,
8584
getParentOfSymbol: getParentOfSymbol,
8685
getTypeOfSymbol: getTypeOfSymbol,
87-
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
8886
getPropertiesOfType: getPropertiesOfType,
8987
getPropertyOfType: getPropertyOfType,
9088
getSignaturesOfType: getSignaturesOfType,
9189
getIndexTypeOfType: getIndexTypeOfType,
9290
getReturnTypeOfSignature: getReturnTypeOfSignature,
93-
resolveEntityName: resolveEntityName,
9491
getSymbolsInScope: getSymbolsInScope,
9592
getSymbolInfo: getSymbolInfo,
96-
getTypeOfExpression: getTypeOfExpression,
93+
getTypeOfNode: getTypeOfNode,
9794
typeToString: typeToString,
9895
symbolToString: symbolToString,
9996
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType
@@ -6546,30 +6543,42 @@ module ts {
65466543
return mapToArray(symbols);
65476544
}
65486545

6549-
// True if the given identifier is the identifier of a declaration node
6550-
function isDeclarationIdentifier(identifier: Identifier): boolean {
6551-
if (identifier.parent) {
6552-
switch (identifier.parent.kind) {
6553-
case SyntaxKind.TypeParameter:
6554-
case SyntaxKind.Parameter:
6555-
case SyntaxKind.VariableDeclaration:
6556-
case SyntaxKind.Property:
6557-
case SyntaxKind.PropertyAssignment:
6558-
case SyntaxKind.EnumMember:
6559-
case SyntaxKind.Method:
6560-
case SyntaxKind.FunctionDeclaration:
6561-
case SyntaxKind.FunctionExpression:
6562-
case SyntaxKind.GetAccessor:
6563-
case SyntaxKind.SetAccessor:
6564-
case SyntaxKind.ClassDeclaration:
6565-
case SyntaxKind.InterfaceDeclaration:
6566-
case SyntaxKind.EnumDeclaration:
6567-
case SyntaxKind.ModuleDeclaration:
6568-
case SyntaxKind.ImportDeclaration:
6569-
return (<Declaration>identifier.parent).name === identifier;
6570-
case SyntaxKind.CatchBlock:
6571-
return (<CatchBlock>identifier.parent).variable === identifier;
6572-
}
6546+
// True if the given identifier, string literal, or number literal is the name of a declaration node
6547+
function isDeclarationName(name: Node): boolean {
6548+
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
6549+
return false;
6550+
}
6551+
6552+
var parent = name.parent;
6553+
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
6554+
return (<Declaration>parent).name === name;
6555+
}
6556+
6557+
if (parent.kind === SyntaxKind.CatchBlock) {
6558+
return (<CatchBlock>parent).variable === name;
6559+
}
6560+
6561+
return false;
6562+
}
6563+
6564+
function isDeclaration(node: Node): boolean {
6565+
switch (node.kind) {
6566+
case SyntaxKind.TypeParameter:
6567+
case SyntaxKind.Parameter:
6568+
case SyntaxKind.VariableDeclaration:
6569+
case SyntaxKind.Property:
6570+
case SyntaxKind.PropertyAssignment:
6571+
case SyntaxKind.EnumMember:
6572+
case SyntaxKind.Method:
6573+
case SyntaxKind.FunctionDeclaration:
6574+
case SyntaxKind.GetAccessor:
6575+
case SyntaxKind.SetAccessor:
6576+
case SyntaxKind.ClassDeclaration:
6577+
case SyntaxKind.InterfaceDeclaration:
6578+
case SyntaxKind.EnumDeclaration:
6579+
case SyntaxKind.ModuleDeclaration:
6580+
case SyntaxKind.ImportDeclaration:
6581+
return true;
65736582
}
65746583
return false;
65756584
}
@@ -6582,6 +6591,7 @@ module ts {
65826591
}
65836592

65846593
function isExpression(node: Node): boolean {
6594+
// Omitted expression?
65856595
switch (node.kind) {
65866596
case SyntaxKind.ThisKeyword:
65876597
case SyntaxKind.SuperKeyword:
@@ -6605,49 +6615,119 @@ module ts {
66056615
case SyntaxKind.ConditionalExpression:
66066616
return true;
66076617
case SyntaxKind.QualifiedName:
6608-
while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
6609-
return node.parent && node.parent.kind === SyntaxKind.TypeQuery;
6618+
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
6619+
return node.parent.kind === SyntaxKind.TypeQuery;
66106620
case SyntaxKind.Identifier:
6621+
if (node.parent.kind === SyntaxKind.TypeQuery) {
6622+
return true;
6623+
}
6624+
// Fall through
66116625
case SyntaxKind.NumericLiteral:
66126626
case SyntaxKind.StringLiteral:
66136627
var parent = node.parent;
6614-
if (parent) {
6615-
if (isExpression(parent)) return true;
6616-
switch (parent.kind) {
6617-
case SyntaxKind.VariableDeclaration:
6618-
case SyntaxKind.Parameter:
6619-
case SyntaxKind.Property:
6620-
case SyntaxKind.EnumMember:
6621-
return (<VariableDeclaration>parent).initializer === node;
6622-
case SyntaxKind.ExpressionStatement:
6623-
case SyntaxKind.IfStatement:
6624-
case SyntaxKind.DoStatement:
6625-
case SyntaxKind.WhileStatement:
6626-
case SyntaxKind.ReturnStatement:
6627-
case SyntaxKind.WithStatement:
6628-
case SyntaxKind.SwitchStatement:
6629-
case SyntaxKind.CaseClause:
6630-
case SyntaxKind.ThrowStatement:
6631-
case SyntaxKind.SwitchStatement:
6632-
return (<ExpressionStatement>parent).expression === node;
6633-
case SyntaxKind.ForStatement:
6634-
return (<ForStatement>parent).initializer === node || (<ForStatement>parent).condition === node ||
6635-
(<ForStatement>parent).iterator === node;
6636-
case SyntaxKind.ForInStatement:
6637-
return (<ForInStatement>parent).variable === node || (<ForInStatement>parent).expression === node;
6638-
}
6628+
if (parent.kind === SyntaxKind.TypeAssertion) {
6629+
return node === (<TypeAssertion>parent).operand;
6630+
}
6631+
6632+
if (isExpression(parent)) {
6633+
return true;
6634+
}
6635+
6636+
switch (parent.kind) {
6637+
case SyntaxKind.VariableDeclaration:
6638+
case SyntaxKind.Parameter:
6639+
case SyntaxKind.Property:
6640+
case SyntaxKind.EnumMember:
6641+
return (<VariableDeclaration>parent).initializer === node;
6642+
case SyntaxKind.ExpressionStatement:
6643+
case SyntaxKind.IfStatement:
6644+
case SyntaxKind.DoStatement:
6645+
case SyntaxKind.WhileStatement:
6646+
case SyntaxKind.ReturnStatement:
6647+
case SyntaxKind.WithStatement:
6648+
case SyntaxKind.SwitchStatement:
6649+
case SyntaxKind.CaseClause:
6650+
case SyntaxKind.ThrowStatement:
6651+
case SyntaxKind.SwitchStatement:
6652+
return (<ExpressionStatement>parent).expression === node;
6653+
case SyntaxKind.ForStatement:
6654+
return (<ForStatement>parent).initializer === node || (<ForStatement>parent).condition === node ||
6655+
(<ForStatement>parent).iterator === node;
6656+
case SyntaxKind.ForInStatement:
6657+
return (<ForInStatement>parent).variable === node || (<ForInStatement>parent).expression === node;
66396658
}
66406659
}
66416660
return false;
66426661
}
66436662

6663+
function isTypeNode(node: Node): boolean {
6664+
if (node.kind >= SyntaxKind.FirstTypeNode && node.kind <= SyntaxKind.LastTypeNode) {
6665+
return true;
6666+
}
6667+
6668+
switch (node.kind) {
6669+
case SyntaxKind.AnyKeyword:
6670+
case SyntaxKind.NumberKeyword:
6671+
case SyntaxKind.StringKeyword:
6672+
case SyntaxKind.BooleanKeyword:
6673+
return true;
6674+
case SyntaxKind.VoidKeyword:
6675+
return node.parent.kind !== SyntaxKind.PrefixOperator;
6676+
case SyntaxKind.StringLiteral:
6677+
return node.parent.kind === SyntaxKind.Parameter;
6678+
// Identifiers and qualified names may be type nodes, depending on their context. Climb
6679+
// above them to find the lowest container
6680+
case SyntaxKind.Identifier:
6681+
// If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
6682+
if (node.parent.kind === SyntaxKind.QualifiedName) {
6683+
node = node.parent;
6684+
}
6685+
// Fall through
6686+
case SyntaxKind.QualifiedName:
6687+
var parent = node.parent;
6688+
if (parent.kind === SyntaxKind.TypeQuery) {
6689+
return false;
6690+
}
6691+
if (isTypeNode(parent)) {
6692+
return true;
6693+
}
6694+
switch (parent.kind) {
6695+
case SyntaxKind.TypeParameter:
6696+
return node === (<TypeParameterDeclaration>parent).constraint;
6697+
case SyntaxKind.Property:
6698+
case SyntaxKind.Parameter:
6699+
case SyntaxKind.VariableDeclaration:
6700+
return node === (<VariableDeclaration>parent).type;
6701+
case SyntaxKind.FunctionDeclaration:
6702+
case SyntaxKind.FunctionExpression:
6703+
case SyntaxKind.ArrowFunction:
6704+
case SyntaxKind.Constructor:
6705+
case SyntaxKind.Method:
6706+
case SyntaxKind.GetAccessor:
6707+
case SyntaxKind.SetAccessor:
6708+
return node === (<FunctionDeclaration>parent).type;
6709+
case SyntaxKind.CallSignature:
6710+
case SyntaxKind.ConstructSignature:
6711+
case SyntaxKind.IndexSignature:
6712+
return node === (<SignatureDeclaration>parent).type;
6713+
case SyntaxKind.TypeAssertion:
6714+
return node === (<TypeAssertion>parent).type;
6715+
case SyntaxKind.CallExpression:
6716+
case SyntaxKind.NewExpression:
6717+
return (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
6718+
}
6719+
}
6720+
6721+
return false;
6722+
}
6723+
66446724
function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
66456725
return (node.parent.kind === SyntaxKind.QualifiedName || node.parent.kind === SyntaxKind.PropertyAccess) &&
66466726
(<QualifiedName>node.parent).right === node;
66476727
}
66486728

66496729
function getSymbolOfIdentifier(identifier: Identifier) {
6650-
if (isDeclarationIdentifier(identifier)) {
6730+
if (isDeclarationName(identifier)) {
66516731
return getSymbolOfNode(identifier.parent);
66526732
}
66536733

@@ -6725,14 +6805,36 @@ module ts {
67256805
return undefined;
67266806
}
67276807

6728-
function getTypeOfExpression(node: Node) {
6808+
function getTypeOfNode(node: Node): Type {
67296809
if (isExpression(node)) {
6730-
while (isRightSideOfQualifiedNameOrPropertyAccess(node)) {
6731-
node = node.parent;
6810+
return getTypeOfExpression(<Expression>node);
6811+
}
6812+
if (isTypeNode(node)) {
6813+
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) {
6814+
var symbol = getSymbolInfo(node);
6815+
return getDeclaredTypeOfSymbol(symbol);
67326816
}
6733-
return <Type>getApparentType(checkExpression(node));
6817+
return getTypeFromTypeNode(<TypeNode>node);
67346818
}
6735-
return unknownType;
6819+
6820+
if (isDeclaration(node)) {
6821+
// In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
6822+
var symbol = getSymbolOfNode(node);
6823+
return getTypeOfSymbol(symbol);
6824+
}
6825+
6826+
var isExportAssignment = node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.ExportAssignment;
6827+
if (isDeclarationName(node) || isExportAssignment) {
6828+
var symbol = getSymbolInfo(node);
6829+
return getTypeOfSymbol(symbol);
6830+
}
6831+
}
6832+
6833+
function getTypeOfExpression(expr: Expression): Type {
6834+
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
6835+
expr = expr.parent;
6836+
}
6837+
return <Type>getApparentType(checkExpression(expr));
67366838
}
67376839

67386840
function getAugmentedPropertiesOfApparentType(type: Type): Symbol[]{
@@ -6743,21 +6845,21 @@ module ts {
67436845
var propertiesByName: Map<Symbol> = {};
67446846
var results: Symbol[] = [];
67456847

6746-
forEach(getPropertiesOfType(apparentType), (s) => {
6848+
forEach(getPropertiesOfType(apparentType), s => {
67476849
propertiesByName[s.name] = s;
67486850
results.push(s);
67496851
});
67506852

67516853
var resolved = resolveObjectTypeMembers(<ObjectType>type);
6752-
forEachValue(resolved.members, (s) => {
6854+
forEachValue(resolved.members, s => {
67536855
if (symbolIsValue(s) && !propertiesByName[s.name]) {
67546856
propertiesByName[s.name] = s;
67556857
results.push(s);
67566858
}
67576859
});
67586860

67596861
if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
6760-
forEach(getPropertiesOfType(globalFunctionType), (s) => {
6862+
forEach(getPropertiesOfType(globalFunctionType), s => {
67616863
if (!propertiesByName[s.name]) {
67626864
propertiesByName[s.name] = s;
67636865
results.push(s);

src/compiler/types.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ module ts {
217217
FirstKeyword = BreakKeyword,
218218
LastKeyword = StringKeyword,
219219
FirstFutureReservedWord = ImplementsKeyword,
220-
LastFutureReservedWord = YieldKeyword
220+
LastFutureReservedWord = YieldKeyword,
221+
FirstTypeNode = TypeReference,
222+
LastTypeNode = ArrayType
221223
}
222224

223225
export enum NodeFlags {
@@ -593,19 +595,16 @@ module ts {
593595
getTypeCount(): number;
594596
checkProgram(): void;
595597
emitFiles(): EmitResult;
596-
getSymbolOfNode(node: Node): Symbol;
597598
getParentOfSymbol(symbol: Symbol): Symbol;
598599
getTypeOfSymbol(symbol: Symbol): Type;
599-
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
600600
getPropertiesOfType(type: Type): Symbol[];
601601
getPropertyOfType(type: Type, propetyName: string): Symbol;
602602
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
603603
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
604604
getReturnTypeOfSignature(signature: Signature): Type;
605-
resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol;
606605
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
607606
getSymbolInfo(node: Node): Symbol;
608-
getTypeOfExpression(node: Expression, contextualType?: Type, contextualMapper?: TypeMapper): Type;
607+
getTypeOfNode(node: Node): Type;
609608
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
610609
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
611610
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];

src/services/services.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1693,7 +1693,7 @@ module ts {
16931693

16941694
// Right of dot member completion list
16951695
if (isRightOfDot) {
1696-
var type: Type = typeInfoResolver.getTypeOfExpression(mappedNode);
1696+
var type: Type = typeInfoResolver.getTypeOfNode(mappedNode);
16971697
if (!type) {
16981698
return undefined;
16991699
}

0 commit comments

Comments
 (0)