mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Start testing signature counts and adjust some syntactic computations
This commit is contained in:
parent
8a765d7680
commit
49ae281059
@ -4435,7 +4435,11 @@ module ts {
|
||||
// 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, candidatesOutArray)
|
||||
|
||||
@ -96,7 +96,6 @@ module ts {
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
private _children: Node[];
|
||||
private _syntheticParent: Node;
|
||||
|
||||
public getSourceFile(): SourceFile {
|
||||
var node: Node = this;
|
||||
@ -152,9 +151,6 @@ module ts {
|
||||
if (pos < node.pos) {
|
||||
pos = this.addSyntheticNodes(list._children, pos, node.pos);
|
||||
}
|
||||
else {
|
||||
(<NodeObject>node)._syntheticParent = list;
|
||||
}
|
||||
list._children.push(node);
|
||||
pos = node.end;
|
||||
}
|
||||
@ -207,11 +203,6 @@ module ts {
|
||||
return this._children;
|
||||
}
|
||||
|
||||
public getIndexOfChild(child: Node): number {
|
||||
if (!this._children) this.createChildren();
|
||||
return this._children.indexOf(child);
|
||||
}
|
||||
|
||||
public getFirstToken(sourceFile?: SourceFile): Node {
|
||||
var children = this.getChildren();
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
@ -229,10 +220,6 @@ module ts {
|
||||
if (child.kind > SyntaxKind.Missing) return child.getLastToken(sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
public getSyntheticParentOrParent(): Node {
|
||||
return this._syntheticParent || this.parent;
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolObject implements Symbol {
|
||||
@ -3496,26 +3483,43 @@ module ts {
|
||||
// If node is an argument, returns its index in the argument list
|
||||
// If not, returns -1
|
||||
function getArgumentIndex(node: Node): number {
|
||||
// Treat the open paren / angle bracket of a call as the introduction of parameter slot 0
|
||||
var parent = (<NodeObject>node).getSyntheticParentOrParent();
|
||||
if (parent.kind === SyntaxKind.SyntaxList) {
|
||||
var grandparent = parent.parent;
|
||||
if (grandparent.kind === SyntaxKind.CallExpression || grandparent.kind === SyntaxKind.NewExpression) {
|
||||
var index = (<NodeObject>parent).getIndexOfChild(node);
|
||||
Debug.assert(index >= 0);
|
||||
return index;
|
||||
}
|
||||
if (node.parent.kind !== SyntaxKind.CallExpression && node.parent.kind !== SyntaxKind.NewExpression) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var parent = <CallExpression>node.parent;
|
||||
// Find out if 'node' is an argument, a type argument, or neither
|
||||
// Treat the open paren / angle bracket of a call as the introduction of parameter slot 0
|
||||
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
|
||||
return parent.kind === SyntaxKind.CallExpression || parent.kind === SyntaxKind.NewExpression
|
||||
? 0
|
||||
: -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
var argumentListOrTypeArgumentList: NodeArray<Node>;
|
||||
if (parent.typeArguments && node.pos >= parent.typeArguments.pos && node.end <= parent.typeArguments.end) {
|
||||
argumentListOrTypeArgumentList = parent.typeArguments;
|
||||
}
|
||||
else if (parent.arguments && node.pos >= parent.arguments.pos && node.end <= parent.arguments.end) {
|
||||
argumentListOrTypeArgumentList = parent.arguments;
|
||||
}
|
||||
|
||||
return argumentListOrTypeArgumentList ? argumentListOrTypeArgumentList.indexOf(node) : -1;
|
||||
|
||||
// if (parent.kind === SyntaxKind.SyntaxList) {
|
||||
// var grandparent = parent.parent;
|
||||
// if (grandparent.kind === SyntaxKind.CallExpression || grandparent.kind === SyntaxKind.NewExpression) {
|
||||
// var index = (<NodeObject>parent).getIndexOfChild(node);
|
||||
// Debug.assert(index >= 0);
|
||||
// return index;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
|
||||
// return parent.kind === SyntaxKind.CallExpression || parent.kind === SyntaxKind.NewExpression
|
||||
// ? 0
|
||||
// : -1;
|
||||
// }
|
||||
|
||||
// TODO: Handle close paren or close angle bracket on nonempty list
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
function getSignatureHelpArgumentContext(node: Node): {
|
||||
@ -3529,7 +3533,7 @@ module ts {
|
||||
if (!isToken || position <= node.getStart() || position >= node.getEnd()) {
|
||||
// This is a temporary hack until we figure out our token story.
|
||||
// The correct solution is to get the previous token
|
||||
node = SignatureInfoHelpers.findClosestRightmostSiblingFromLeft(position, sourceFile);
|
||||
node = SignatureInfoHelpers.findPrecedingToken(position, sourceFile);
|
||||
|
||||
if (!node) {
|
||||
return undefined;
|
||||
@ -3559,9 +3563,8 @@ module ts {
|
||||
|
||||
// TODO: Handle previous token logic
|
||||
// TODO: Handle generic call with incomplete
|
||||
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
synchronizeHostData();
|
||||
@ -3578,7 +3581,7 @@ module ts {
|
||||
var candidates = <Signature[]>[];
|
||||
var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
|
||||
return candidates.length
|
||||
? new SignatureHelpItems(undefined, undefined, undefined)
|
||||
? new SignatureHelpItems(new Array<SignatureHelpItem>(candidates.length), undefined, undefined)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -345,82 +345,70 @@ module ts {
|
||||
// return null;
|
||||
//}
|
||||
|
||||
export function findClosestRightmostSiblingFromLeft(position: number, sourceFile: SourceFile): Node {
|
||||
return search(sourceFile);
|
||||
|
||||
function search(n: Node): Node {
|
||||
|
||||
var childCandidate: Node;
|
||||
forEachChild(n, c => {
|
||||
if (c.kind === SyntaxKind.OmittedExpression || c.kind === SyntaxKind.Missing) {
|
||||
return;
|
||||
}
|
||||
if (c.end <= position || c.getStart() < position) {
|
||||
childCandidate = c;
|
||||
}
|
||||
return c.end > position;
|
||||
});
|
||||
|
||||
if (childCandidate) {
|
||||
if (childCandidate.end > position || !isCompletedNode(childCandidate, position, sourceFile)) {
|
||||
return search(childCandidate) || childCandidate;
|
||||
}
|
||||
else {
|
||||
return childCandidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
export function findPrecedingToken(position: number, sourceFile: SourceFile): Node {
|
||||
return find(sourceFile, /*diveIntoLastChild*/ false);
|
||||
|
||||
function find(n: Node, diveIntoLastChild: boolean): Node {
|
||||
if (isToken(n)) {
|
||||
return n;
|
||||
}
|
||||
|
||||
var children = n.getChildren();
|
||||
if (diveIntoLastChild) {
|
||||
var candidate = findLastChildNodeCandidate(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && find(candidate, /*diveIntoLastChild*/ true);
|
||||
}
|
||||
|
||||
for (var i = 0, len = children.length; i < len; ++i) {
|
||||
var child = children[i];
|
||||
if (nodeHasTokens(child)) {
|
||||
if (position < child.end) {
|
||||
if (child.getStart() >= position) {
|
||||
// actual start of the node is past the position - previous token should be at the end of previous child
|
||||
var candidate = findLastChildNodeCandidate(children, /*exclusiveStartPosition*/ i);
|
||||
return candidate && find(candidate, /*diveIntoLastChild*/ true)
|
||||
}
|
||||
else {
|
||||
// candidate should be in this node
|
||||
return find(child, diveIntoLastChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// here we know that none of child token nodes embrace the position
|
||||
// try to find the closest token on the left
|
||||
if (children.length) {
|
||||
var candidate = findLastChildNodeCandidate(children, /*exclusiveStartPosition*/ children.length);
|
||||
return candidate && find(candidate, /*diveIntoLastChild*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
|
||||
function findLastChildNodeCandidate(children: Node[], exclusiveStartPosition: number): Node {
|
||||
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
|
||||
if (nodeHasTokens(children[i])) {
|
||||
return children[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isToken(n: Node): boolean {
|
||||
return n.kind < SyntaxKind.Missing;
|
||||
}
|
||||
|
||||
function nodeHasTokens(n: Node): boolean {
|
||||
if (n.kind === SyntaxKind.ExpressionStatement) {
|
||||
return nodeHasTokens((<ExpressionStatement>n).expression);
|
||||
}
|
||||
|
||||
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SyntaxList is already realized so getChildCount should be fast and non-expensive
|
||||
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
|
||||
}
|
||||
}
|
||||
|
||||
function isCompletedNode(n: Node, position: number, sourceFile: SourceFile): boolean {
|
||||
switch (n.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ObjectLiteral:
|
||||
case SyntaxKind.Block:
|
||||
case SyntaxKind.CatchBlock:
|
||||
case SyntaxKind.FinallyBlock:
|
||||
case SyntaxKind.FunctionBlock:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return isNodeEndWith(n, sourceFile, CharacterCodes.closeBrace);
|
||||
case SyntaxKind.ParenExpression:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.CallExpression:
|
||||
return isNodeEndWith(n, sourceFile, CharacterCodes.closeParen);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.Method:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return !(<FunctionDeclaration>n).body || isCompletedNode((<FunctionDeclaration>n).body, position, sourceFile);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return (<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, position, sourceFile);
|
||||
case SyntaxKind.IfStatement:
|
||||
if ((<IfStatement>n).thenStatement && (<IfStatement>n).thenStatement.end > position) {
|
||||
return isCompletedNode((<IfStatement>n).thenStatement, position, sourceFile);
|
||||
}
|
||||
else if ((<IfStatement>n).elseStatement) {
|
||||
return isCompletedNode((<IfStatement>n).elseStatement, position, sourceFile);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return isCompletedNode((<ExpressionStatement>n).expression, position, sourceFile);
|
||||
case SyntaxKind.ArrayLiteral:
|
||||
return isNodeEndWith(n, sourceFile, CharacterCodes.closeBracket);
|
||||
case SyntaxKind.Missing:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function isNodeEndWith(n: Node, sourceFile: SourceFile, charCode: CharacterCodes): boolean {
|
||||
var pos = n.end - 1; // Node.end is exclusive
|
||||
return pos < sourceFile.text.length && sourceFile.text.charCodeAt(pos) === charCode;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -291,7 +291,7 @@ module FourSlashInterface {
|
||||
}
|
||||
|
||||
public signatureHelpCountIs(expected: number) {
|
||||
// FourSlash.currentTestState.verifySignatureHelpCount(expected);
|
||||
FourSlash.currentTestState.verifySignatureHelpCount(expected);
|
||||
}
|
||||
|
||||
public currentSignatureParamterCountIs(expected: number) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user