Skip to content

Commit 475125b

Browse files
author
Andy Hanson
committed
Merge branch 'master' into map4
2 parents e8c7224 + 4fde1af commit 475125b

File tree

55 files changed

+1784
-139
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1784
-139
lines changed

src/harness/fourslash.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,6 +2258,18 @@ namespace FourSlash {
22582258
}
22592259
}
22602260

2261+
public verifyNavigationTree(json: any) {
2262+
const tree = this.languageService.getNavigationTree(this.activeFile.fileName);
2263+
if (JSON.stringify(tree, replacer) !== JSON.stringify(json)) {
2264+
this.raiseError(`verifyNavigationTree failed - expected: ${stringify(json)}, got: ${stringify(tree, replacer)}`);
2265+
}
2266+
2267+
function replacer(key: string, value: any) {
2268+
// Don't check "spans", and omit falsy values.
2269+
return key === "spans" ? undefined : (value || undefined);
2270+
}
2271+
}
2272+
22612273
public printNavigationItems(searchValue: string) {
22622274
const items = this.languageService.getNavigateToItems(searchValue);
22632275
const length = items && items.length;
@@ -3346,6 +3358,10 @@ namespace FourSlashInterface {
33463358
this.state.verifyNavigationBar(json);
33473359
}
33483360

3361+
public navigationTree(json: any) {
3362+
this.state.verifyNavigationTree(json);
3363+
}
3364+
33493365
public navigationItemsListCount(count: number, searchValue: string, matchKind?: string, fileName?: string) {
33503366
this.state.verifyNavigationItemsCount(count, searchValue, matchKind, fileName);
33513367
}

src/harness/harnessLanguageService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,10 @@ namespace Harness.LanguageService {
459459
getNavigationBarItems(fileName: string): ts.NavigationBarItem[] {
460460
return unwrapJSONCallResult(this.shim.getNavigationBarItems(fileName));
461461
}
462+
getNavigationTree(fileName: string): ts.NavigationTree {
463+
return unwrapJSONCallResult(this.shim.getNavigationTree(fileName));
464+
}
465+
462466
getOutliningSpans(fileName: string): ts.OutliningSpan[] {
463467
return unwrapJSONCallResult(this.shim.getOutliningSpans(fileName));
464468
}

src/server/client.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ namespace ts.server {
512512
return this.lastRenameEntry.locations;
513513
}
514514

515-
decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string, lineMap: number[]): NavigationBarItem[] {
515+
private decodeNavigationBarItems(items: protocol.NavigationBarItem[], fileName: string, lineMap: number[]): NavigationBarItem[] {
516516
if (!items) {
517517
return [];
518518
}
@@ -521,10 +521,7 @@ namespace ts.server {
521521
text: item.text,
522522
kind: item.kind,
523523
kindModifiers: item.kindModifiers || "",
524-
spans: item.spans.map(span =>
525-
createTextSpanFromBounds(
526-
this.lineOffsetToPosition(fileName, span.start, lineMap),
527-
this.lineOffsetToPosition(fileName, span.end, lineMap))),
524+
spans: item.spans.map(span => this.decodeSpan(span, fileName, lineMap)),
528525
childItems: this.decodeNavigationBarItems(item.childItems, fileName, lineMap),
529526
indent: item.indent,
530527
bolded: false,
@@ -533,17 +530,37 @@ namespace ts.server {
533530
}
534531

535532
getNavigationBarItems(fileName: string): NavigationBarItem[] {
536-
const args: protocol.FileRequestArgs = {
537-
file: fileName
538-
};
539-
540-
const request = this.processRequest<protocol.NavBarRequest>(CommandNames.NavBar, args);
533+
const request = this.processRequest<protocol.NavBarRequest>(CommandNames.NavBar, { file: fileName });
541534
const response = this.processResponse<protocol.NavBarResponse>(request);
542535

543536
const lineMap = this.getLineMap(fileName);
544537
return this.decodeNavigationBarItems(response.body, fileName, lineMap);
545538
}
546539

540+
private decodeNavigationTree(tree: protocol.NavigationTree, fileName: string, lineMap: number[]): NavigationTree {
541+
return {
542+
text: tree.text,
543+
kind: tree.kind,
544+
kindModifiers: tree.kindModifiers,
545+
spans: tree.spans.map(span => this.decodeSpan(span, fileName, lineMap)),
546+
childItems: map(tree.childItems, item => this.decodeNavigationTree(item, fileName, lineMap))
547+
};
548+
}
549+
550+
getNavigationTree(fileName: string): NavigationTree {
551+
const request = this.processRequest<protocol.NavTreeRequest>(CommandNames.NavTree, { file: fileName });
552+
const response = this.processResponse<protocol.NavTreeResponse>(request);
553+
554+
const lineMap = this.getLineMap(fileName);
555+
return this.decodeNavigationTree(response.body, fileName, lineMap);
556+
}
557+
558+
private decodeSpan(span: protocol.TextSpan, fileName: string, lineMap: number[]) {
559+
return createTextSpanFromBounds(
560+
this.lineOffsetToPosition(fileName, span.start, lineMap),
561+
this.lineOffsetToPosition(fileName, span.end, lineMap));
562+
}
563+
547564
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan {
548565
throw new Error("Not Implemented Yet.");
549566
}

src/server/protocol.d.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ declare namespace ts.server.protocol {
110110
*/
111111
export interface TodoCommentRequestArgs extends FileRequestArgs {
112112
/**
113-
* Array of target TodoCommentDescriptors that describes TODO comments to be found
113+
* Array of target TodoCommentDescriptors that describes TODO comments to be found
114114
*/
115115
descriptors: TodoCommentDescriptor[];
116116
}
@@ -231,7 +231,7 @@ declare namespace ts.server.protocol {
231231
offset?: number;
232232

233233
/**
234-
* Position (can be specified instead of line/offset pair)
234+
* Position (can be specified instead of line/offset pair)
235235
*/
236236
position?: number;
237237
}
@@ -624,12 +624,12 @@ declare namespace ts.server.protocol {
624624

625625
/**
626626
* Represents a file in external project.
627-
* External project is project whose set of files, compilation options and open\close state
627+
* External project is project whose set of files, compilation options and open\close state
628628
* is maintained by the client (i.e. if all this data come from .csproj file in Visual Studio).
629629
* External project will exist even if all files in it are closed and should be closed explicity.
630-
* If external project includes one or more tsconfig.json/jsconfig.json files then tsserver will
630+
* If external project includes one or more tsconfig.json/jsconfig.json files then tsserver will
631631
* create configured project for every config file but will maintain a link that these projects were created
632-
* as a result of opening external project so they should be removed once external project is closed.
632+
* as a result of opening external project so they should be removed once external project is closed.
633633
*/
634634
export interface ExternalFile {
635635
/**
@@ -1045,7 +1045,7 @@ declare namespace ts.server.protocol {
10451045
}
10461046

10471047
/**
1048-
* Response for CompileOnSaveAffectedFileListRequest request;
1048+
* Response for CompileOnSaveAffectedFileListRequest request;
10491049
*/
10501050
export interface CompileOnSaveAffectedFileListResponse extends Response {
10511051
body: CompileOnSaveAffectedFileListSingleProject[];
@@ -1812,6 +1812,13 @@ declare namespace ts.server.protocol {
18121812
export interface NavBarRequest extends FileRequest {
18131813
}
18141814

1815+
/**
1816+
* NavTree request; value of command field is "navtree".
1817+
* Return response giving the navigation tree of the requested file.
1818+
*/
1819+
export interface NavTreeRequest extends FileRequest {
1820+
}
1821+
18151822
export interface NavigationBarItem {
18161823
/**
18171824
* The item's display text.
@@ -1844,7 +1851,20 @@ declare namespace ts.server.protocol {
18441851
indent: number;
18451852
}
18461853

1854+
/** protocol.NavigationTree is identical to ts.NavigationTree, except using protocol.TextSpan instead of ts.TextSpan */
1855+
export interface NavigationTree {
1856+
text: string;
1857+
kind: string;
1858+
kindModifiers: string;
1859+
spans: TextSpan[];
1860+
childItems?: NavigationTree[];
1861+
}
1862+
18471863
export interface NavBarResponse extends Response {
18481864
body?: NavigationBarItem[];
18491865
}
1866+
1867+
export interface NavTreeResponse extends Response {
1868+
body?: NavigationTree;
1869+
}
18501870
}

src/server/session.ts

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ namespace ts.server {
110110
export const SyntacticDiagnosticsSync = "syntacticDiagnosticsSync";
111111
export const NavBar = "navbar";
112112
export const NavBarFull = "navbar-full";
113+
export const NavTree = "navtree";
114+
export const NavTreeFull = "navtree-full";
113115
export const Navto = "navto";
114116
export const NavtoFull = "navto-full";
115117
export const Occurrences = "occurrences";
@@ -960,15 +962,8 @@ namespace ts.server {
960962
return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => {
961963
if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) === 0)) {
962964
const { name, kind, kindModifiers, sortText, replacementSpan } = entry;
963-
964-
let convertedSpan: protocol.TextSpan = undefined;
965-
if (replacementSpan) {
966-
convertedSpan = {
967-
start: scriptInfo.positionToLineOffset(replacementSpan.start),
968-
end: scriptInfo.positionToLineOffset(replacementSpan.start + replacementSpan.length)
969-
};
970-
}
971-
965+
const convertedSpan: protocol.TextSpan =
966+
replacementSpan ? this.decorateSpan(replacementSpan, scriptInfo) : undefined;
972967
result.push({ name, kind, kindModifiers, sortText, replacementSpan: convertedSpan });
973968
}
974969
return result;
@@ -1106,38 +1101,54 @@ namespace ts.server {
11061101
this.projectService.closeClientFile(file);
11071102
}
11081103

1109-
private decorateNavigationBarItem(project: Project, fileName: NormalizedPath, items: ts.NavigationBarItem[]): protocol.NavigationBarItem[] {
1110-
if (!items) {
1111-
return undefined;
1112-
}
1113-
1114-
const scriptInfo = project.getScriptInfoForNormalizedPath(fileName);
1115-
1116-
return items.map(item => ({
1104+
private decorateNavigationBarItems(items: ts.NavigationBarItem[], scriptInfo: ScriptInfo): protocol.NavigationBarItem[] {
1105+
return map(items, item => ({
11171106
text: item.text,
11181107
kind: item.kind,
11191108
kindModifiers: item.kindModifiers,
1120-
spans: item.spans.map(span => ({
1121-
start: scriptInfo.positionToLineOffset(span.start),
1122-
end: scriptInfo.positionToLineOffset(ts.textSpanEnd(span))
1123-
})),
1124-
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems),
1109+
spans: item.spans.map(span => this.decorateSpan(span, scriptInfo)),
1110+
childItems: this.decorateNavigationBarItems(item.childItems, scriptInfo),
11251111
indent: item.indent
11261112
}));
11271113
}
11281114

11291115
private getNavigationBarItems(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationBarItem[] | NavigationBarItem[] {
11301116
const { file, project } = this.getFileAndProject(args);
11311117
const items = project.getLanguageService(/*ensureSynchronized*/ false).getNavigationBarItems(file);
1132-
if (!items) {
1133-
return undefined;
1134-
}
1135-
1136-
return simplifiedResult
1137-
? this.decorateNavigationBarItem(project, file, items)
1118+
return !items
1119+
? undefined
1120+
: simplifiedResult
1121+
? this.decorateNavigationBarItems(items, project.getScriptInfoForNormalizedPath(file))
11381122
: items;
11391123
}
11401124

1125+
private decorateNavigationTree(tree: ts.NavigationTree, scriptInfo: ScriptInfo): protocol.NavigationTree {
1126+
return {
1127+
text: tree.text,
1128+
kind: tree.kind,
1129+
kindModifiers: tree.kindModifiers,
1130+
spans: tree.spans.map(span => this.decorateSpan(span, scriptInfo)),
1131+
childItems: map(tree.childItems, item => this.decorateNavigationTree(item, scriptInfo))
1132+
};
1133+
}
1134+
1135+
private decorateSpan(span: TextSpan, scriptInfo: ScriptInfo): protocol.TextSpan {
1136+
return {
1137+
start: scriptInfo.positionToLineOffset(span.start),
1138+
end: scriptInfo.positionToLineOffset(ts.textSpanEnd(span))
1139+
};
1140+
}
1141+
1142+
private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree {
1143+
const { file, project } = this.getFileAndProject(args);
1144+
const tree = project.getLanguageService(/*ensureSynchronized*/ false).getNavigationTree(file);
1145+
return !tree
1146+
? undefined
1147+
: simplifiedResult
1148+
? this.decorateNavigationTree(tree, project.getScriptInfoForNormalizedPath(file))
1149+
: tree;
1150+
}
1151+
11411152
private getNavigateToItems(args: protocol.NavtoRequestArgs, simplifiedResult: boolean): protocol.NavtoItem[] | NavigateToItem[] {
11421153
const projects = this.getProjects(args);
11431154

@@ -1274,19 +1285,11 @@ namespace ts.server {
12741285
const position = this.getPosition(args, scriptInfo);
12751286

12761287
const spans = project.getLanguageService(/*ensureSynchronized*/ false).getBraceMatchingAtPosition(file, position);
1277-
if (!spans) {
1278-
return undefined;
1279-
}
1280-
if (simplifiedResult) {
1281-
1282-
return spans.map(span => ({
1283-
start: scriptInfo.positionToLineOffset(span.start),
1284-
end: scriptInfo.positionToLineOffset(span.start + span.length)
1285-
}));
1286-
}
1287-
else {
1288-
return spans;
1289-
}
1288+
return !spans
1289+
? undefined
1290+
: simplifiedResult
1291+
? spans.map(span => this.decorateSpan(span, scriptInfo))
1292+
: spans;
12901293
}
12911294

12921295
getDiagnosticsForProject(delay: number, fileName: string) {
@@ -1571,6 +1574,12 @@ namespace ts.server {
15711574
[CommandNames.NavBarFull]: (request: protocol.FileRequest) => {
15721575
return this.requiredResponse(this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ false));
15731576
},
1577+
[CommandNames.NavTree]: (request: protocol.FileRequest) => {
1578+
return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ true));
1579+
},
1580+
[CommandNames.NavTreeFull]: (request: protocol.FileRequest) => {
1581+
return this.requiredResponse(this.getNavigationTree(request.arguments, /*simplifiedResult*/ false));
1582+
},
15741583
[CommandNames.Occurrences]: (request: protocol.FileLocationRequest) => {
15751584
return this.requiredResponse(this.getOccurrences(request.arguments));
15761585
},

0 commit comments

Comments
 (0)