Support decorators and templates

This commit is contained in:
Andy Hanson
2016-08-30 06:39:13 -07:00
parent 4514f8fde5
commit 59774733d6
5 changed files with 71 additions and 23 deletions

View File

@@ -1035,6 +1035,18 @@ namespace ts {
return undefined;
}
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
switch (node.kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.Decorator:
return true;
default:
return false;
}
}
export function getInvokedExpression(node: CallLikeExpression): Expression {
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
return (<TaggedTemplateExpression>node).tag;

View File

@@ -2793,32 +2793,25 @@ namespace ts {
}
function isCallExpressionTarget(node: Node): boolean {
return !!getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression);
node = climbPastPropertyAccess(node);
return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).expression === node;
}
function isNewExpressionTarget(node: Node): boolean {
return !!getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression);
node = climbPastPropertyAccess(node);
return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).expression === node;
}
function getCallOrNewExpressionTargetingNode(node: Node): CallExpression | NewExpression | undefined {
return <CallExpression>getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression) || <NewExpression>getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression);
}
function tryGetCalledDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
const callOrNewExpression = getCallOrNewExpressionTargetingNode(node);
if (callOrNewExpression) {
const signature = typeChecker.getResolvedSignature(callOrNewExpression);
return signature.declaration;
}
}
function getCallOrNewExpressionWorker(node: Node, kind: SyntaxKind): Node | undefined {
/** Returns a CallLikeExpression where `node` is the target being invoked. */
function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined {
const target = climbPastPropertyAccess(node);
return target &&
target.parent &&
target.parent.kind === kind &&
(<CallExpression>target.parent).expression === target &&
target.parent;
const callLike = target.parent;
return isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike;
}
function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
const callLike = getAncestorCallLikeExpression(node);
return callLike && typeChecker.getResolvedSignature(callLike).declaration;
}
function isNameOfModuleDeclaration(node: Node) {
@@ -5232,7 +5225,7 @@ namespace ts {
const typeChecker = program.getTypeChecker();
const calledDeclaration = tryGetCalledDeclaration(typeChecker, node);
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
if (calledDeclaration) {
return [getDefinitionFromSignatureDeclaration(calledDeclaration)];
}

View File

@@ -0,0 +1,22 @@
// @Target: ES6
// @experimentaldecorators: true
////async function f() {}
////
/////*defDecString*/function dec(target: any, propertyKey: string): void;
/////*defDecSymbol*/function dec(target: any, propertyKey: symbol): void;
////function dec(target: any, propertyKey: string | symbol) {}
////
////declare const s: symbol;
////class C {
//// @/*useDecString*/dec f() {}
//// @/*useDecSymbol*/dec [s]() {}
////}
goTo.marker("useDecString");
goTo.definition();
verify.caretAtMarker("defDecString");
goTo.marker("useDecSymbol");
goTo.definition();
verify.caretAtMarker("defDecSymbol");

View File

@@ -1,11 +1,12 @@
/// <reference path='fourslash.ts' />
/////*functionOverload1*/function /*functionOverload*/functionOverload();
/////*functionOverload1*/function /*functionOverload*/functionOverload(value: number);
/////*functionOverload2*/function functionOverload(value: string);
/////*functionOverloadDefinition*/function functionOverload() {}
////
/////*functionOverloadReference1*/functionOverload();
/////*functionOverloadReference1*/functionOverload(123);
/////*functionOverloadReference2*/functionOverload("123");
/////*brokenOverload*/functionOverload({});
goTo.marker('functionOverloadReference1');
goTo.definition();
@@ -15,6 +16,10 @@ goTo.marker('functionOverloadReference2');
goTo.definition();
verify.caretAtMarker('functionOverload2');
goTo.marker('brokenOverload');
goTo.definition();
verify.caretAtMarker('functionOverload1');
goTo.marker('functionOverload');
goTo.definition();
verify.caretAtMarker('functionOverloadDefinition');

View File

@@ -0,0 +1,16 @@
/// <reference path='fourslash.ts' />
/////*defFNumber*/function f(strs: TemplateStringsArray, x: number): void;
/////*defFBool*/function f(strs: TemplateStringsArray, x: boolean): void;
////function f(strs: TemplateStringsArray, x: number | boolean) {}
////
/////*useFNumber*/f`${0}`;
/////*useFBool*/f`${false}`;
goTo.marker("useFNumber");
goTo.definition();
verify.caretAtMarker("defFNumber");
goTo.marker("useFBool");
goTo.definition();
verify.caretAtMarker("defFBool");