Skip to content

Commit 5977473

Browse files
author
Andy Hanson
committed
Support decorators and templates
1 parent 4514f8f commit 5977473

5 files changed

Lines changed: 70 additions & 22 deletions

File tree

src/compiler/utilities.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,18 @@ namespace ts {
10351035
return undefined;
10361036
}
10371037

1038+
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
1039+
switch (node.kind) {
1040+
case SyntaxKind.CallExpression:
1041+
case SyntaxKind.NewExpression:
1042+
case SyntaxKind.TaggedTemplateExpression:
1043+
case SyntaxKind.Decorator:
1044+
return true;
1045+
default:
1046+
return false;
1047+
}
1048+
}
1049+
10381050
export function getInvokedExpression(node: CallLikeExpression): Expression {
10391051
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
10401052
return (<TaggedTemplateExpression>node).tag;

src/services/services.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,32 +2793,25 @@ namespace ts {
27932793
}
27942794

27952795
function isCallExpressionTarget(node: Node): boolean {
2796-
return !!getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression);
2796+
node = climbPastPropertyAccess(node);
2797+
return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).expression === node;
27972798
}
27982799

27992800
function isNewExpressionTarget(node: Node): boolean {
2800-
return !!getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression);
2801+
node = climbPastPropertyAccess(node);
2802+
return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).expression === node;
28012803
}
28022804

2803-
function getCallOrNewExpressionTargetingNode(node: Node): CallExpression | NewExpression | undefined {
2804-
return <CallExpression>getCallOrNewExpressionWorker(node, SyntaxKind.CallExpression) || <NewExpression>getCallOrNewExpressionWorker(node, SyntaxKind.NewExpression);
2805-
}
2806-
2807-
function tryGetCalledDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
2808-
const callOrNewExpression = getCallOrNewExpressionTargetingNode(node);
2809-
if (callOrNewExpression) {
2810-
const signature = typeChecker.getResolvedSignature(callOrNewExpression);
2811-
return signature.declaration;
2812-
}
2805+
/** Returns a CallLikeExpression where `node` is the target being invoked. */
2806+
function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined {
2807+
const target = climbPastPropertyAccess(node);
2808+
const callLike = target.parent;
2809+
return isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target && callLike;
28132810
}
28142811

2815-
function getCallOrNewExpressionWorker(node: Node, kind: SyntaxKind): Node | undefined {
2816-
const target = climbPastPropertyAccess(node);
2817-
return target &&
2818-
target.parent &&
2819-
target.parent.kind === kind &&
2820-
(<CallExpression>target.parent).expression === target &&
2821-
target.parent;
2812+
function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined {
2813+
const callLike = getAncestorCallLikeExpression(node);
2814+
return callLike && typeChecker.getResolvedSignature(callLike).declaration;
28222815
}
28232816

28242817
function isNameOfModuleDeclaration(node: Node) {
@@ -5232,7 +5225,7 @@ namespace ts {
52325225

52335226
const typeChecker = program.getTypeChecker();
52345227

5235-
const calledDeclaration = tryGetCalledDeclaration(typeChecker, node);
5228+
const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
52365229
if (calledDeclaration) {
52375230
return [getDefinitionFromSignatureDeclaration(calledDeclaration)];
52385231
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @Target: ES6
2+
// @experimentaldecorators: true
3+
4+
////async function f() {}
5+
////
6+
/////*defDecString*/function dec(target: any, propertyKey: string): void;
7+
/////*defDecSymbol*/function dec(target: any, propertyKey: symbol): void;
8+
////function dec(target: any, propertyKey: string | symbol) {}
9+
////
10+
////declare const s: symbol;
11+
////class C {
12+
//// @/*useDecString*/dec f() {}
13+
//// @/*useDecSymbol*/dec [s]() {}
14+
////}
15+
16+
goTo.marker("useDecString");
17+
goTo.definition();
18+
verify.caretAtMarker("defDecString");
19+
20+
goTo.marker("useDecSymbol");
21+
goTo.definition();
22+
verify.caretAtMarker("defDecSymbol");
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/// <reference path='fourslash.ts' />
22

3-
/////*functionOverload1*/function /*functionOverload*/functionOverload();
3+
/////*functionOverload1*/function /*functionOverload*/functionOverload(value: number);
44
/////*functionOverload2*/function functionOverload(value: string);
55
/////*functionOverloadDefinition*/function functionOverload() {}
66
////
7-
/////*functionOverloadReference1*/functionOverload();
7+
/////*functionOverloadReference1*/functionOverload(123);
88
/////*functionOverloadReference2*/functionOverload("123");
9+
/////*brokenOverload*/functionOverload({});
910

1011
goTo.marker('functionOverloadReference1');
1112
goTo.definition();
@@ -15,6 +16,10 @@ goTo.marker('functionOverloadReference2');
1516
goTo.definition();
1617
verify.caretAtMarker('functionOverload2');
1718

19+
goTo.marker('brokenOverload');
20+
goTo.definition();
21+
verify.caretAtMarker('functionOverload1');
22+
1823
goTo.marker('functionOverload');
1924
goTo.definition();
2025
verify.caretAtMarker('functionOverloadDefinition');
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
/////*defFNumber*/function f(strs: TemplateStringsArray, x: number): void;
4+
/////*defFBool*/function f(strs: TemplateStringsArray, x: boolean): void;
5+
////function f(strs: TemplateStringsArray, x: number | boolean) {}
6+
////
7+
/////*useFNumber*/f`${0}`;
8+
/////*useFBool*/f`${false}`;
9+
10+
goTo.marker("useFNumber");
11+
goTo.definition();
12+
verify.caretAtMarker("defFNumber");
13+
14+
goTo.marker("useFBool");
15+
goTo.definition();
16+
verify.caretAtMarker("defFBool");

0 commit comments

Comments
 (0)