Skip to content

Commit e9f76d0

Browse files
committed
Add implementation for getTypeDefinitionAtPosition
1 parent dda598a commit e9f76d0

11 files changed

+197
-0
lines changed

src/harness/fourslash.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,27 @@ module FourSlash {
15701570
this.currentCaretPosition = definition.textSpan.start;
15711571
}
15721572

1573+
public goToTypeDefinition(definitionIndex: number) {
1574+
if (definitionIndex === 0) {
1575+
this.scenarioActions.push('<GoToTypeDefinition />');
1576+
} else {
1577+
this.taoInvalidReason = 'GoToTypeDefinition not supported for non-zero definition indices';
1578+
}
1579+
1580+
var definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
1581+
if (!definitions || !definitions.length) {
1582+
this.raiseError('goToTypeDefinition failed - expected to at least one definition location but got 0');
1583+
}
1584+
1585+
if (definitionIndex >= definitions.length) {
1586+
this.raiseError('goToTypeDefinition failed - definitionIndex value (' + definitionIndex + ') exceeds definition list size (' + definitions.length + ')');
1587+
}
1588+
1589+
var definition = definitions[definitionIndex];
1590+
this.openFile(definition.fileName);
1591+
this.currentCaretPosition = definition.textSpan.start;
1592+
}
1593+
15731594
public verifyDefinitionLocationExists(negative: boolean) {
15741595
this.taoInvalidReason = 'verifyDefinitionLocationExists NYI';
15751596

src/harness/harnessLanguageService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ module Harness.LanguageService {
333333
getDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] {
334334
return unwrapJSONCallResult(this.shim.getDefinitionAtPosition(fileName, position));
335335
}
336+
getTypeDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[]{
337+
return unwrapJSONCallResult(this.shim.getTypeDefinitionAtPosition(fileName, position));
338+
}
336339
getReferencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] {
337340
return unwrapJSONCallResult(this.shim.getReferencesAtPosition(fileName, position));
338341
}

src/server/client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ module ts.server {
300300
});
301301
}
302302

303+
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
304+
throw new Error("Not Implemented Yet.");
305+
}
306+
303307
findReferences(fileName: string, position: number): ReferencedSymbol[]{
304308
// Not yet implemented.
305309
return [];

src/services/services.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,8 @@ module ts {
987987
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[];
988988

989989
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
990+
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
991+
990992
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
991993
findReferences(fileName: string, position: number): ReferencedSymbol[];
992994
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[];
@@ -4017,6 +4019,46 @@ module ts {
40174019
return getDefintionFromSymbol(symbol, node);
40184020
}
40194021

4022+
/// Goto type
4023+
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
4024+
synchronizeHostData();
4025+
4026+
let sourceFile = getValidSourceFile(fileName);
4027+
4028+
let node = getTouchingPropertyName(sourceFile, position);
4029+
if (!node) {
4030+
return undefined;
4031+
}
4032+
4033+
let typeChecker = program.getTypeChecker();
4034+
4035+
let symbol = typeChecker.getSymbolAtLocation(node);
4036+
if (!symbol) {
4037+
return undefined;
4038+
}
4039+
4040+
let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node);
4041+
if (!type) {
4042+
return undefined;
4043+
}
4044+
4045+
if (type.flags & TypeFlags.Union) {
4046+
var result: DefinitionInfo[] = [];
4047+
forEach((<UnionType>type).types, t => {
4048+
if (t.symbol) {
4049+
result.push(...getDefintionFromSymbol(t.symbol, node));
4050+
}
4051+
});
4052+
return result;
4053+
}
4054+
4055+
if (!type.symbol) {
4056+
return undefined;
4057+
}
4058+
4059+
return getDefintionFromSymbol(type.symbol, node);
4060+
}
4061+
40204062
function getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
40214063
let results = getOccurrencesAtPositionCore(fileName, position);
40224064

@@ -6403,6 +6445,7 @@ module ts {
64036445
getSignatureHelpItems,
64046446
getQuickInfoAtPosition,
64056447
getDefinitionAtPosition,
6448+
getTypeDefinitionAtPosition,
64066449
getReferencesAtPosition,
64076450
findReferences,
64086451
getOccurrencesAtPosition,

src/services/shims.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ module ts {
130130
*/
131131
getDefinitionAtPosition(fileName: string, position: number): string;
132132

133+
/**
134+
* Returns a JSON-encoded value of the type:
135+
* { fileName: string; textSpan: { start: number; length: number}; kind: string; name: string; containerKind: string; containerName: string }
136+
*
137+
* Or undefined value if no definition can be found.
138+
*/
139+
getTypeDefinitionAtPosition(fileName: string, position: number): string;
140+
133141
/**
134142
* Returns a JSON-encoded value of the type:
135143
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
@@ -557,6 +565,20 @@ module ts {
557565
});
558566
}
559567

568+
/// GOTO Type
569+
570+
/**
571+
* Computes the definition location of the type of the symbol
572+
* at the requested position.
573+
*/
574+
public getTypeDefinitionAtPosition(fileName: string, position: number): string {
575+
return this.forwardJSONCall(
576+
"getTypeDefinitionAtPosition('" + fileName + "', " + position + ")",
577+
() => {
578+
return this.languageService.getTypeDefinitionAtPosition(fileName, position);
579+
});
580+
}
581+
560582
public getRenameInfo(fileName: string, position: number): string {
561583
return this.forwardJSONCall(
562584
"getRenameInfo('" + fileName + "', " + position + ")",

tests/cases/fourslash/fourslash.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ module FourSlashInterface {
119119
FourSlash.currentTestState.goToDefinition(definitionIndex);
120120
}
121121

122+
public type(definitionIndex: number = 0) {
123+
FourSlash.currentTestState.goToTypeDefinition(definitionIndex);
124+
}
125+
122126
public position(position: number, fileIndex?: number);
123127
public position(position: number, fileName?: string);
124128
public position(position: number, fileNameOrIndex?: any) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: goToTypeDefinition_Definition.ts
4+
/////*definition*/class C {
5+
//// p;
6+
////}
7+
////var c: C;
8+
9+
// @Filename: goToTypeDefinition_Consumption.ts
10+
/////*reference*/c = undefined;
11+
12+
goTo.marker('reference');
13+
goTo.type();
14+
verify.caretAtMarker('definition');
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: goToTypeDefinition2_Definition.ts
4+
/////*definition*/interface I1 {
5+
//// p;
6+
////}
7+
////type propertyType = I1;
8+
////interface I2 {
9+
//// property: propertyType;
10+
////}
11+
12+
// @Filename: goToTypeDefinition2_Consumption.ts
13+
////var i2: I2;
14+
////i2.prop/*reference*/erty;
15+
16+
goTo.marker('reference');
17+
goTo.type();
18+
verify.caretAtMarker('definition');
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: goToTypeDefinitioAliases_module1.ts
4+
/////*definition*/interface I {
5+
//// p;
6+
////}
7+
////export {I as I2};
8+
9+
// @Filename: goToTypeDefinitioAliases_module2.ts
10+
////import {I2 as I3} from "goToTypeDefinitioAliases_module1";
11+
////var v1: I3;
12+
////export {v1 as v2};
13+
14+
// @Filename: goToTypeDefinitioAliases_module3.ts
15+
////import {/*reference1*/v2 as v3} from "goToTypeDefinitioAliases_module2";
16+
/////*reference2*/v3;
17+
18+
goTo.marker('reference1');
19+
goTo.type();
20+
verify.caretAtMarker('definition');
21+
22+
goTo.marker('reference2');
23+
goTo.type();
24+
verify.caretAtMarker('definition');
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
/////*definition*/enum E {
4+
//// value1,
5+
//// value2
6+
////}
7+
////var x = E.value2;
8+
////
9+
/////*reference*/x;
10+
11+
goTo.marker('reference');
12+
goTo.type();
13+
verify.caretAtMarker('definition');
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
/////*definition0*/class C {
4+
//// p;
5+
////}
6+
////
7+
/////*definition1*/interface I {
8+
//// x;
9+
////}
10+
////
11+
////module M {
12+
//// /*definition2*/export interface I {
13+
//// y;
14+
//// }
15+
////}
16+
////
17+
////var x: C | I | M.I;
18+
////
19+
/////*reference*/x;
20+
21+
goTo.marker('reference');
22+
goTo.type(0);
23+
verify.caretAtMarker('definition0');
24+
25+
goTo.marker('reference');
26+
goTo.type(1);
27+
verify.caretAtMarker('definition1');
28+
29+
goTo.marker('reference');
30+
goTo.type(2);
31+
verify.caretAtMarker('definition2');

0 commit comments

Comments
 (0)