mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Add getTypeOfNode function to checker API
This commit is contained in:
parent
96fba4d867
commit
12a0909fdd
@ -81,19 +81,16 @@ module ts {
|
||||
getTypeCount: () => typeCount,
|
||||
checkProgram: checkProgram,
|
||||
emitFiles: invokeEmitter,
|
||||
getSymbolOfNode: getSymbolOfNode,
|
||||
getParentOfSymbol: getParentOfSymbol,
|
||||
getTypeOfSymbol: getTypeOfSymbol,
|
||||
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
|
||||
getPropertiesOfType: getPropertiesOfType,
|
||||
getPropertyOfType: getPropertyOfType,
|
||||
getSignaturesOfType: getSignaturesOfType,
|
||||
getIndexTypeOfType: getIndexTypeOfType,
|
||||
getReturnTypeOfSignature: getReturnTypeOfSignature,
|
||||
resolveEntityName: resolveEntityName,
|
||||
getSymbolsInScope: getSymbolsInScope,
|
||||
getSymbolInfo: getSymbolInfo,
|
||||
getTypeOfExpression: getTypeOfExpression,
|
||||
getTypeOfNode: getTypeOfNode,
|
||||
typeToString: typeToString,
|
||||
symbolToString: symbolToString,
|
||||
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType
|
||||
@ -6546,30 +6543,42 @@ module ts {
|
||||
return mapToArray(symbols);
|
||||
}
|
||||
|
||||
// True if the given identifier is the identifier of a declaration node
|
||||
function isDeclarationIdentifier(identifier: Identifier): boolean {
|
||||
if (identifier.parent) {
|
||||
switch (identifier.parent.kind) {
|
||||
case SyntaxKind.TypeParameter:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.Method:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return (<Declaration>identifier.parent).name === identifier;
|
||||
case SyntaxKind.CatchBlock:
|
||||
return (<CatchBlock>identifier.parent).variable === identifier;
|
||||
}
|
||||
// True if the given identifier, string literal, or number literal is the name of a declaration node
|
||||
function isDeclarationName(name: Node): boolean {
|
||||
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var parent = name.parent;
|
||||
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
|
||||
return (<Declaration>parent).name === name;
|
||||
}
|
||||
|
||||
if (parent.kind === SyntaxKind.CatchBlock) {
|
||||
return (<CatchBlock>parent).variable === name;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isDeclaration(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TypeParameter:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.Method:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -6582,6 +6591,7 @@ module ts {
|
||||
}
|
||||
|
||||
function isExpression(node: Node): boolean {
|
||||
// Omitted expression?
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
@ -6605,49 +6615,119 @@ module ts {
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return true;
|
||||
case SyntaxKind.QualifiedName:
|
||||
while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
|
||||
return node.parent && node.parent.kind === SyntaxKind.TypeQuery;
|
||||
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
|
||||
return node.parent.kind === SyntaxKind.TypeQuery;
|
||||
case SyntaxKind.Identifier:
|
||||
if (node.parent.kind === SyntaxKind.TypeQuery) {
|
||||
return true;
|
||||
}
|
||||
// Fall through
|
||||
case SyntaxKind.NumericLiteral:
|
||||
case SyntaxKind.StringLiteral:
|
||||
var parent = node.parent;
|
||||
if (parent) {
|
||||
if (isExpression(parent)) return true;
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.EnumMember:
|
||||
return (<VariableDeclaration>parent).initializer === node;
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
case SyntaxKind.IfStatement:
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
case SyntaxKind.ReturnStatement:
|
||||
case SyntaxKind.WithStatement:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseClause:
|
||||
case SyntaxKind.ThrowStatement:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return (<ExpressionStatement>parent).expression === node;
|
||||
case SyntaxKind.ForStatement:
|
||||
return (<ForStatement>parent).initializer === node || (<ForStatement>parent).condition === node ||
|
||||
(<ForStatement>parent).iterator === node;
|
||||
case SyntaxKind.ForInStatement:
|
||||
return (<ForInStatement>parent).variable === node || (<ForInStatement>parent).expression === node;
|
||||
}
|
||||
if (parent.kind === SyntaxKind.TypeAssertion) {
|
||||
return node === (<TypeAssertion>parent).operand;
|
||||
}
|
||||
|
||||
if (isExpression(parent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.EnumMember:
|
||||
return (<VariableDeclaration>parent).initializer === node;
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
case SyntaxKind.IfStatement:
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
case SyntaxKind.ReturnStatement:
|
||||
case SyntaxKind.WithStatement:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
case SyntaxKind.CaseClause:
|
||||
case SyntaxKind.ThrowStatement:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return (<ExpressionStatement>parent).expression === node;
|
||||
case SyntaxKind.ForStatement:
|
||||
return (<ForStatement>parent).initializer === node || (<ForStatement>parent).condition === node ||
|
||||
(<ForStatement>parent).iterator === node;
|
||||
case SyntaxKind.ForInStatement:
|
||||
return (<ForInStatement>parent).variable === node || (<ForInStatement>parent).expression === node;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isTypeNode(node: Node): boolean {
|
||||
if (node.kind >= SyntaxKind.FirstTypeNode && node.kind <= SyntaxKind.LastTypeNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.NumberKeyword:
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
return true;
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return node.parent.kind !== SyntaxKind.PrefixOperator;
|
||||
case SyntaxKind.StringLiteral:
|
||||
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
|
||||
case SyntaxKind.Identifier:
|
||||
// If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
|
||||
if (node.parent.kind === SyntaxKind.QualifiedName) {
|
||||
node = node.parent;
|
||||
}
|
||||
// Fall through
|
||||
case SyntaxKind.QualifiedName:
|
||||
var parent = node.parent;
|
||||
if (parent.kind === SyntaxKind.TypeQuery) {
|
||||
return false;
|
||||
}
|
||||
if (isTypeNode(parent)) {
|
||||
return true;
|
||||
}
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.TypeParameter:
|
||||
return node === (<TypeParameterDeclaration>parent).constraint;
|
||||
case SyntaxKind.Property:
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return node === (<VariableDeclaration>parent).type;
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.Method:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return node === (<FunctionDeclaration>parent).type;
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
return node === (<SignatureDeclaration>parent).type;
|
||||
case SyntaxKind.TypeAssertion:
|
||||
return node === (<TypeAssertion>parent).type;
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
return (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
return (node.parent.kind === SyntaxKind.QualifiedName || node.parent.kind === SyntaxKind.PropertyAccess) &&
|
||||
(<QualifiedName>node.parent).right === node;
|
||||
}
|
||||
|
||||
function getSymbolOfIdentifier(identifier: Identifier) {
|
||||
if (isDeclarationIdentifier(identifier)) {
|
||||
if (isDeclarationName(identifier)) {
|
||||
return getSymbolOfNode(identifier.parent);
|
||||
}
|
||||
|
||||
@ -6725,14 +6805,36 @@ module ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getTypeOfExpression(node: Node) {
|
||||
function getTypeOfNode(node: Node): Type {
|
||||
if (isExpression(node)) {
|
||||
while (isRightSideOfQualifiedNameOrPropertyAccess(node)) {
|
||||
node = node.parent;
|
||||
}
|
||||
return <Type>getApparentType(checkExpression(node));
|
||||
return getTypeOfExpression(<Expression>node);
|
||||
}
|
||||
return unknownType;
|
||||
if (isTypeNode(node)) {
|
||||
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) {
|
||||
var symbol = getSymbolInfo(node);
|
||||
return getDeclaredTypeOfSymbol(symbol);
|
||||
}
|
||||
return getTypeFromTypeNode(<TypeNode>node);
|
||||
}
|
||||
|
||||
if (isDeclaration(node)) {
|
||||
// In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
|
||||
var symbol = getSymbolOfNode(node);
|
||||
return getTypeOfSymbol(symbol);
|
||||
}
|
||||
|
||||
var isExportAssignment = node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.ExportAssignment;
|
||||
if (isDeclarationName(node) || isExportAssignment) {
|
||||
var symbol = getSymbolInfo(node);
|
||||
return getTypeOfSymbol(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeOfExpression(expr: Expression): Type {
|
||||
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
|
||||
expr = expr.parent;
|
||||
}
|
||||
return <Type>getApparentType(checkExpression(expr));
|
||||
}
|
||||
|
||||
function getAugmentedPropertiesOfApparentType(type: Type): Symbol[]{
|
||||
@ -6743,13 +6845,13 @@ module ts {
|
||||
var propertiesByName: Map<Symbol> = {};
|
||||
var results: Symbol[] = [];
|
||||
|
||||
forEach(getPropertiesOfType(apparentType), (s) => {
|
||||
forEach(getPropertiesOfType(apparentType), s => {
|
||||
propertiesByName[s.name] = s;
|
||||
results.push(s);
|
||||
});
|
||||
|
||||
var resolved = resolveObjectTypeMembers(<ObjectType>type);
|
||||
forEachValue(resolved.members, (s) => {
|
||||
forEachValue(resolved.members, s => {
|
||||
if (symbolIsValue(s) && !propertiesByName[s.name]) {
|
||||
propertiesByName[s.name] = s;
|
||||
results.push(s);
|
||||
@ -6757,7 +6859,7 @@ module ts {
|
||||
});
|
||||
|
||||
if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
|
||||
forEach(getPropertiesOfType(globalFunctionType), (s) => {
|
||||
forEach(getPropertiesOfType(globalFunctionType), s => {
|
||||
if (!propertiesByName[s.name]) {
|
||||
propertiesByName[s.name] = s;
|
||||
results.push(s);
|
||||
|
||||
@ -217,7 +217,9 @@ module ts {
|
||||
FirstKeyword = BreakKeyword,
|
||||
LastKeyword = StringKeyword,
|
||||
FirstFutureReservedWord = ImplementsKeyword,
|
||||
LastFutureReservedWord = YieldKeyword
|
||||
LastFutureReservedWord = YieldKeyword,
|
||||
FirstTypeNode = TypeReference,
|
||||
LastTypeNode = ArrayType
|
||||
}
|
||||
|
||||
export enum NodeFlags {
|
||||
@ -593,19 +595,16 @@ module ts {
|
||||
getTypeCount(): number;
|
||||
checkProgram(): void;
|
||||
emitFiles(): EmitResult;
|
||||
getSymbolOfNode(node: Node): Symbol;
|
||||
getParentOfSymbol(symbol: Symbol): Symbol;
|
||||
getTypeOfSymbol(symbol: Symbol): Type;
|
||||
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
|
||||
getPropertiesOfType(type: Type): Symbol[];
|
||||
getPropertyOfType(type: Type, propetyName: string): Symbol;
|
||||
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
|
||||
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
|
||||
getReturnTypeOfSignature(signature: Signature): Type;
|
||||
resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol;
|
||||
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
|
||||
getSymbolInfo(node: Node): Symbol;
|
||||
getTypeOfExpression(node: Expression, contextualType?: Type, contextualMapper?: TypeMapper): Type;
|
||||
getTypeOfNode(node: Node): Type;
|
||||
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
|
||||
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
|
||||
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
|
||||
|
||||
@ -1693,7 +1693,7 @@ module ts {
|
||||
|
||||
// Right of dot member completion list
|
||||
if (isRightOfDot) {
|
||||
var type: Type = typeInfoResolver.getTypeOfExpression(mappedNode);
|
||||
var type: Type = typeInfoResolver.getTypeOfNode(mappedNode);
|
||||
if (!type) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user