Merge pull request #726 from Microsoft/sigHelp

Signature help in the new compiler
This commit is contained in:
Jason Freeman
2014-09-24 10:58:50 -07:00
80 changed files with 1958 additions and 710 deletions
+111 -62
View File
@@ -91,6 +91,7 @@ module ts {
getRootSymbol: getRootSymbol,
getContextualType: getContextualType,
getFullyQualifiedName: getFullyQualifiedName,
getResolvedSignature: getResolvedSignature,
getEnumMemberValue: getEnumMemberValue
};
@@ -4330,55 +4331,26 @@ module ts {
return unknownSignature;
}
function isCandidateSignature(node: CallExpression, signature: Signature) {
function signatureHasCorrectArity(node: CallExpression, signature: Signature): boolean {
var args = node.arguments || emptyArray;
return args.length >= signature.minArgumentCount &&
var isCorrect = args.length >= signature.minArgumentCount &&
(signature.hasRestParameter || args.length <= signature.parameters.length) &&
(!node.typeArguments || signature.typeParameters && node.typeArguments.length === signature.typeParameters.length);
}
// The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
// A nit here is that we reorder only signatures that belong to the same symbol,
// so order how inherited signatures are processed is still preserved.
// interface A { (x: string): void }
// interface B extends A { (x: 'foo'): string }
// var b: B;
// b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
function collectCandidates(node: CallExpression, signatures: Signature[]): Signature[]{
var result: Signature[] = [];
var lastParent: Node;
var lastSymbol: Symbol;
var cutoffPos: number = 0;
var pos: number;
for (var i = 0; i < signatures.length; i++) {
var signature = signatures[i];
if (isCandidateSignature(node, signature)) {
var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
var parent = signature.declaration && signature.declaration.parent;
if (!lastSymbol || symbol === lastSymbol) {
if (lastParent && parent === lastParent) {
pos++;
}
else {
lastParent = parent;
pos = cutoffPos;
}
}
else {
// current declaration belongs to a different symbol
// set cutoffPos so re-orderings in the future won't change result set from 0 to cutoffPos
pos = cutoffPos = result.length;
lastParent = parent;
}
lastSymbol = symbol;
for (var j = result.length; j > pos; j--) {
result[j] = result[j - 1];
}
result[pos] = signature;
// For error recovery, since we have parsed OmittedExpressions for any extra commas
// in the argument list, if we see any OmittedExpressions, just return true.
// The reason this is ok is because omitted expressions here are syntactically
// illegal, and will cause a parse error.
// Note: It may be worth keeping the upper bound check on arity, but removing
// the lower bound check if there are omitted expressions.
if (!isCorrect) {
// Technically this type assertion is not safe because args could be initialized to emptyArray
// above.
if ((<NodeArray<Node>>args).hasTrailingComma || forEach(args, arg => arg.kind === SyntaxKind.OmittedExpression)) {
return true;
}
}
return result;
return isCorrect;
}
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
@@ -4409,6 +4381,9 @@ module ts {
var mapper = createInferenceMapper(context);
// First infer from arguments that are not context sensitive
for (var i = 0; i < args.length; i++) {
if (args[i].kind === SyntaxKind.OmittedExpression) {
continue;
}
if (!excludeArgument || excludeArgument[i] === undefined) {
var parameterType = getTypeAtPosition(signature, i);
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
@@ -4417,6 +4392,9 @@ module ts {
// Next, infer from those context sensitive arguments that are no longer excluded
if (excludeArgument) {
for (var i = 0; i < args.length; i++) {
if (args[i].kind === SyntaxKind.OmittedExpression) {
continue;
}
if (excludeArgument[i] === false) {
var parameterType = getTypeAtPosition(signature, i);
inferTypes(context, checkExpressionWithContextualType(args[i], parameterType, mapper), parameterType);
@@ -4445,6 +4423,10 @@ module ts {
if (node.arguments) {
for (var i = 0; i < node.arguments.length; i++) {
var arg = node.arguments[i];
if (arg.kind === SyntaxKind.OmittedExpression) {
continue;
}
var paramType = getTypeAtPosition(signature, i);
// String literals get string literal types unless we're reporting errors
var argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors ?
@@ -4462,9 +4444,11 @@ module ts {
return true;
}
function resolveCall(node: CallExpression, signatures: Signature[]): Signature {
function resolveCall(node: CallExpression, signatures: Signature[], candidatesOutArray: Signature[]): Signature {
forEach(node.typeArguments, checkSourceElement);
var candidates = collectCandidates(node, signatures);
var candidates = candidatesOutArray || [];
// collectCandidates fills up the candidates array directly
collectCandidates();
if (!candidates.length) {
error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
return resolveErrorCall(node);
@@ -4480,20 +4464,24 @@ module ts {
var relation = candidates.length === 1 ? assignableRelation : subtypeRelation;
while (true) {
for (var i = 0; i < candidates.length; i++) {
if (!signatureHasCorrectArity(node, candidates[i])) {
continue;
}
while (true) {
var candidate = candidates[i];
if (candidate.typeParameters) {
var candidateWithCorrectArity = candidates[i];
if (candidateWithCorrectArity.typeParameters) {
var typeArguments = node.typeArguments ?
checkTypeArguments(candidate, node.typeArguments) :
inferTypeArguments(candidate, args, excludeArgument);
candidate = getSignatureInstantiation(candidate, typeArguments);
checkTypeArguments(candidateWithCorrectArity, node.typeArguments) :
inferTypeArguments(candidateWithCorrectArity, args, excludeArgument);
candidateWithCorrectArity = getSignatureInstantiation(candidateWithCorrectArity, typeArguments);
}
if (!checkApplicableSignature(node, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
if (!checkApplicableSignature(node, candidateWithCorrectArity, relation, excludeArgument, /*reportErrors*/ false)) {
break;
}
var index = excludeArgument ? indexOf(excludeArgument, true) : -1;
if (index < 0) {
return candidate;
return candidateWithCorrectArity;
}
excludeArgument[index] = false;
}
@@ -4503,17 +4491,70 @@ module ts {
}
relation = assignableRelation;
}
// No signatures were applicable. Now report errors based on the last applicable signature with
// no arguments excluded from assignability checks.
checkApplicableSignature(node, candidate, relation, undefined, /*reportErrors*/ true);
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
// skip the checkApplicableSignature check.
if (candidateWithCorrectArity) {
checkApplicableSignature(node, candidateWithCorrectArity, relation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
}
else {
error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
return resolveErrorCall(node);
}
return resolveErrorCall(node);
// The candidate list orders groups in reverse, but within a group signatures are kept in declaration order
// A nit here is that we reorder only signatures that belong to the same symbol,
// so order how inherited signatures are processed is still preserved.
// interface A { (x: string): void }
// interface B extends A { (x: 'foo'): string }
// var b: B;
// b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void]
function collectCandidates(): void {
var result = candidates;
var lastParent: Node;
var lastSymbol: Symbol;
var cutoffPos: number = 0;
var pos: number;
Debug.assert(!result.length);
for (var i = 0; i < signatures.length; i++) {
var signature = signatures[i];
if (true) {
var symbol = signature.declaration && getSymbolOfNode(signature.declaration);
var parent = signature.declaration && signature.declaration.parent;
if (!lastSymbol || symbol === lastSymbol) {
if (lastParent && parent === lastParent) {
pos++;
}
else {
lastParent = parent;
pos = cutoffPos;
}
}
else {
// current declaration belongs to a different symbol
// set cutoffPos so re-orderings in the future won't change result set from 0 to cutoffPos
pos = cutoffPos = result.length;
lastParent = parent;
}
lastSymbol = symbol;
for (var j = result.length; j > pos; j--) {
result[j] = result[j - 1];
}
result[pos] = signature;
}
}
}
}
function resolveCallExpression(node: CallExpression): Signature {
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature {
if (node.func.kind === SyntaxKind.SuperKeyword) {
var superType = checkSuperExpression(node.func);
if (superType !== unknownType) {
return resolveCall(node, getSignaturesOfType(superType, SignatureKind.Construct));
return resolveCall(node, getSignaturesOfType(superType, SignatureKind.Construct), candidatesOutArray);
}
return resolveUntypedCall(node);
}
@@ -4561,10 +4602,10 @@ module ts {
}
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures);
return resolveCall(node, callSignatures, candidatesOutArray);
}
function resolveNewExpression(node: NewExpression): Signature {
function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[]): Signature {
var expressionType = checkExpression(node.func);
if (expressionType === unknownType) {
// Another error has already been reported
@@ -4599,7 +4640,7 @@ module ts {
// that the user will not add any.
var constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
if (constructSignatures.length) {
return resolveCall(node, constructSignatures);
return resolveCall(node, constructSignatures, candidatesOutArray);
}
// If ConstructExpr's apparent type is an object type with no construct signatures but
@@ -4608,7 +4649,7 @@ module ts {
// operation is Any.
var callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
if (callSignatures.length) {
var signature = resolveCall(node, callSignatures);
var signature = resolveCall(node, callSignatures, candidatesOutArray);
if (getReturnTypeOfSignature(signature) !== voidType) {
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
}
@@ -4619,11 +4660,19 @@ module ts {
return resolveErrorCall(node);
}
function getResolvedSignature(node: CallExpression): Signature {
// candidatesOutArray is passed by signature help in the language service, and collectCandidates
// must fill it up with the appropriate candidate signatures
function getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature {
var links = getNodeLinks(node);
if (!links.resolvedSignature) {
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
// However, it is possible that either candidatesOutArray was not passed in the first time,
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
// to correctly fill the candidatesOutArray.
if (!links.resolvedSignature || candidatesOutArray) {
links.resolvedSignature = anySignature;
links.resolvedSignature = node.kind === SyntaxKind.CallExpression ? resolveCallExpression(node) : resolveNewExpression(node);
links.resolvedSignature = node.kind === SyntaxKind.CallExpression
? resolveCallExpression(node, candidatesOutArray)
: resolveNewExpression(node, candidatesOutArray);
}
return links.resolvedSignature;
}
+15 -1
View File
@@ -11,7 +11,9 @@ module ts {
var result: U;
if (array) {
for (var i = 0, len = array.length; i < len; i++) {
if (result = callback(array[i])) break;
if (result = callback(array[i])) {
break;
}
}
}
return result;
@@ -39,6 +41,18 @@ module ts {
return -1;
}
export function countWhere<T>(array: T[], predicate: (x: T) => boolean): number {
var count = 0;
if (array) {
for (var i = 0, len = array.length; i < len; i++) {
if (predicate(array[i])) {
count++;
}
}
}
return count;
}
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
if (array) {
var result: T[] = [];
+41 -18
View File
@@ -748,23 +748,46 @@ module ts {
}
}
function emitCommaList(nodes: Node[], count?: number) {
if (!(count >= 0)) count = nodes.length;
if (nodes) {
for (var i = 0; i < count; i++) {
if (i) write(", ");
emit(nodes[i]);
function emitTrailingCommaIfPresent(nodeList: NodeArray<Node>, isMultiline: boolean): void {
if (nodeList.hasTrailingComma) {
write(",");
if (isMultiline) {
writeLine();
}
}
}
function emitMultiLineList(nodes: Node[]) {
function emitCommaList(nodes: NodeArray<Node>, includeTrailingComma: boolean, count?: number) {
if (!(count >= 0)) {
count = nodes.length;
}
if (nodes) {
for (var i = 0; i < count; i++) {
if (i) {
write(", ");
}
emit(nodes[i]);
}
if (includeTrailingComma) {
emitTrailingCommaIfPresent(nodes, /*isMultiline*/ false);
}
}
}
function emitMultiLineList(nodes: NodeArray<Node>, includeTrailingComma: boolean) {
if (nodes) {
for (var i = 0; i < nodes.length; i++) {
if (i) write(",");
if (i) {
write(",");
}
writeLine();
emit(nodes[i]);
}
if (includeTrailingComma) {
emitTrailingCommaIfPresent(nodes, /*isMultiline*/ true);
}
}
}
@@ -876,14 +899,14 @@ module ts {
if (node.flags & NodeFlags.MultiLine) {
write("[");
increaseIndent();
emitMultiLineList(node.elements);
emitMultiLineList(node.elements, /*includeTrailingComma*/ true);
decreaseIndent();
writeLine();
write("]");
}
else {
write("[");
emitCommaList(node.elements);
emitCommaList(node.elements, /*includeTrailingComma*/ true);
write("]");
}
}
@@ -895,14 +918,14 @@ module ts {
else if (node.flags & NodeFlags.MultiLine) {
write("{");
increaseIndent();
emitMultiLineList(node.properties);
emitMultiLineList(node.properties, /*includeTrailingComma*/ compilerOptions.target >= ScriptTarget.ES5);
decreaseIndent();
writeLine();
write("}");
}
else {
write("{ ");
emitCommaList(node.properties);
emitCommaList(node.properties, /*includeTrailingComma*/ compilerOptions.target >= ScriptTarget.ES5);
write(" }");
}
}
@@ -949,13 +972,13 @@ module ts {
emitThis(node.func);
if (node.arguments.length) {
write(", ");
emitCommaList(node.arguments);
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
}
write(")");
}
else {
write("(");
emitCommaList(node.arguments);
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
write(")");
}
}
@@ -965,7 +988,7 @@ module ts {
emit(node.func);
if (node.arguments) {
write("(");
emitCommaList(node.arguments);
emitCommaList(node.arguments, /*includeTrailingComma*/ false);
write(")");
}
}
@@ -1138,7 +1161,7 @@ module ts {
if (node.declarations) {
emitToken(SyntaxKind.VarKeyword, endPos);
write(" ");
emitCommaList(node.declarations);
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
}
if (node.initializer) {
emit(node.initializer);
@@ -1286,7 +1309,7 @@ module ts {
function emitVariableStatement(node: VariableStatement) {
emitLeadingComments(node);
if (!(node.flags & NodeFlags.Export)) write("var ");
emitCommaList(node.declarations);
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
write(";");
emitTrailingComments(node);
}
@@ -1395,7 +1418,7 @@ module ts {
increaseIndent();
write("(");
if (node) {
emitCommaList(node.parameters, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
emitCommaList(node.parameters, /*includeTrailingComma*/ false, node.parameters.length - (hasRestParameters(node) ? 1 : 0));
}
write(")");
decreaseIndent();
+44 -24
View File
@@ -628,12 +628,6 @@ module ts {
Parameters, // Parameters in parameter list
}
enum TrailingCommaBehavior {
Disallow,
Allow,
Preserve
}
// Tracks whether we nested (directly or indirectly) in a certain control block.
// Used for validating break and continue statements.
enum ControlBlockContext {
@@ -1205,7 +1199,7 @@ module ts {
}
// Parses a comma-delimited list of elements
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, trailingCommaBehavior: TrailingCommaBehavior): NodeArray<T> {
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, allowTrailingComma: boolean): NodeArray<T> {
var saveParsingContext = parsingContext;
parsingContext |= 1 << kind;
var result = <NodeArray<T>>[];
@@ -1230,15 +1224,14 @@ module ts {
else if (isListTerminator(kind)) {
// Check if the last token was a comma.
if (commaStart >= 0) {
if (trailingCommaBehavior === TrailingCommaBehavior.Disallow) {
if (!allowTrailingComma) {
if (file.syntacticErrors.length === errorCountBeforeParsingList) {
// Report a grammar error so we don't affect lookahead
grammarErrorAtPos(commaStart, scanner.getStartPos() - commaStart, Diagnostics.Trailing_comma_not_allowed);
}
}
else if (trailingCommaBehavior === TrailingCommaBehavior.Preserve) {
result.push(<T>createNode(SyntaxKind.OmittedExpression));
}
// Always preserve a trailing comma by marking it on the NodeArray
result.hasTrailingComma = true;
}
break;
@@ -1273,7 +1266,7 @@ module ts {
function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, startToken: SyntaxKind, endToken: SyntaxKind): NodeArray<T> {
if (parseExpected(startToken)) {
var result = parseDelimitedList(kind, parseElement, TrailingCommaBehavior.Disallow);
var result = parseDelimitedList(kind, parseElement, /*allowTrailingComma*/ false);
parseExpected(endToken);
return result;
}
@@ -2309,7 +2302,11 @@ module ts {
else {
parseExpected(SyntaxKind.OpenParenToken);
}
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseAssignmentExpression, TrailingCommaBehavior.Disallow);
// It is an error to have a trailing comma in an argument list. However, the checker
// needs evidence of a trailing comma in order to give good results for signature help.
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
parseArgumentExpression, /*allowTrailingComma*/ false);
parseExpected(SyntaxKind.CloseParenToken);
expr = finishNode(callExpr);
continue;
@@ -2378,15 +2375,33 @@ module ts {
return finishNode(node);
}
function parseAssignmentExpressionOrOmittedExpression(omittedExpressionDiagnostic: DiagnosticMessage): Expression {
if (token === SyntaxKind.CommaToken) {
if (omittedExpressionDiagnostic) {
var errorStart = scanner.getTokenPos();
var errorLength = scanner.getTextPos() - errorStart;
grammarErrorAtPos(errorStart, errorLength, omittedExpressionDiagnostic);
}
return createNode(SyntaxKind.OmittedExpression);
}
return parseAssignmentExpression();
}
function parseArrayLiteralElement(): Expression {
return token === SyntaxKind.CommaToken ? createNode(SyntaxKind.OmittedExpression) : parseAssignmentExpression();
return parseAssignmentExpressionOrOmittedExpression(/*omittedExpressionDiagnostic*/ undefined);
}
function parseArgumentExpression(): Expression {
return parseAssignmentExpressionOrOmittedExpression(Diagnostics.Argument_expression_expected);
}
function parseArrayLiteral(): ArrayLiteral {
var node = <ArrayLiteral>createNode(SyntaxKind.ArrayLiteral);
parseExpected(SyntaxKind.OpenBracketToken);
if (scanner.hasPrecedingLineBreak()) node.flags |= NodeFlags.MultiLine;
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArrayLiteralElement, TrailingCommaBehavior.Preserve);
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers,
parseArrayLiteralElement, /*allowTrailingComma*/ true);
parseExpected(SyntaxKind.CloseBracketToken);
return finishNode(node);
}
@@ -2428,10 +2443,7 @@ module ts {
node.flags |= NodeFlags.MultiLine;
}
// ES3 itself does not accept a trailing comma in an object literal, however, we'd like to preserve it in ES5.
var trailingCommaBehavior = languageVersion === ScriptTarget.ES3 ? TrailingCommaBehavior.Allow : TrailingCommaBehavior.Preserve;
node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralMember, trailingCommaBehavior);
node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralMember, /*allowTrailingComma*/ true);
parseExpected(SyntaxKind.CloseBraceToken);
var seen: Map<SymbolFlags> = {};
@@ -2520,7 +2532,11 @@ module ts {
parseExpected(SyntaxKind.NewKeyword);
node.func = parseCallAndAccess(parsePrimaryExpression(), /* inNewExpression */ true);
if (parseOptional(SyntaxKind.OpenParenToken) || token === SyntaxKind.LessThanToken && (node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen))) {
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseAssignmentExpression, TrailingCommaBehavior.Disallow);
// It is an error to have a trailing comma in an argument list. However, the checker
// needs evidence of a trailing comma in order to give good results for signature help.
// That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions,
parseArgumentExpression, /*allowTrailingComma*/ false);
parseExpected(SyntaxKind.CloseParenToken);
}
return finishNode(node);
@@ -3089,7 +3105,8 @@ module ts {
}
function parseVariableDeclarationList(flags: NodeFlags, noIn?: boolean): NodeArray<VariableDeclaration> {
return parseDelimitedList(ParsingContext.VariableDeclarations, () => parseVariableDeclaration(flags, noIn), TrailingCommaBehavior.Disallow);
return parseDelimitedList(ParsingContext.VariableDeclarations,
() => parseVariableDeclaration(flags, noIn), /*allowTrailingComma*/ false);
}
function parseVariableStatement(pos?: number, flags?: NodeFlags): VariableStatement {
@@ -3488,7 +3505,8 @@ module ts {
var implementsKeywordLength: number;
if (parseOptional(SyntaxKind.ImplementsKeyword)) {
implementsKeywordLength = scanner.getStartPos() - implementsKeywordStart;
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference, TrailingCommaBehavior.Disallow);
node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences,
parseTypeReference, /*allowTrailingComma*/ false);
}
var errorCountBeforeClassBody = file.syntacticErrors.length;
if (parseExpected(SyntaxKind.OpenBraceToken)) {
@@ -3516,7 +3534,8 @@ module ts {
var extendsKeywordLength: number;
if (parseOptional(SyntaxKind.ExtendsKeyword)) {
extendsKeywordLength = scanner.getStartPos() - extendsKeywordStart;
node.baseTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference, TrailingCommaBehavior.Disallow);
node.baseTypes = parseDelimitedList(ParsingContext.BaseTypeReferences,
parseTypeReference, /*allowTrailingComma*/ false);
}
var errorCountBeforeInterfaceBody = file.syntacticErrors.length;
node.members = parseTypeLiteral().members;
@@ -3580,7 +3599,8 @@ module ts {
parseExpected(SyntaxKind.EnumKeyword);
node.name = parseIdentifier();
if (parseExpected(SyntaxKind.OpenBraceToken)) {
node.members = parseDelimitedList(ParsingContext.EnumMembers, parseAndCheckEnumMember, TrailingCommaBehavior.Allow);
node.members = parseDelimitedList(ParsingContext.EnumMembers,
parseAndCheckEnumMember, /*allowTrailingComma*/ true);
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
+5 -2
View File
@@ -261,7 +261,9 @@ module ts {
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
}
export interface NodeArray<T> extends Array<T>, TextRange { }
export interface NodeArray<T> extends Array<T>, TextRange {
hasTrailingComma?: boolean;
}
export interface Identifier extends Node {
text: string; // Text of identifier (with escapes converted to characters)
@@ -648,6 +650,7 @@ module ts {
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
getRootSymbol(symbol: Symbol): Symbol;
getContextualType(node: Node): Type;
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
// Returns the constant value of this enum member, or 'undefined' if the enum member has a
// computed value.
@@ -935,7 +938,7 @@ module ts {
resolvedReturnType: Type; // Resolved return type
minArgumentCount: number; // Number of non-optional parameters
hasRestParameter: boolean; // True if last parameter is rest parameter
hasStringLiterals: boolean; // True if instantiated
hasStringLiterals: boolean; // True if specialized
target?: Signature; // Instantiation target
mapper?: TypeMapper; // Instantiation mapper
erasedSignatureCache?: Signature; // Erased version of signature (deferred)