提交 49323b37 编写于 作者: J Johannes Rieken

explore Hierarchy<T> idea, #34968

上级 72e6a7d6
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { DocumentSymbolProvider, SymbolInformation, SymbolKind, TextDocument, CancellationToken, Uri, HierarchicalSymbolInformation } from 'vscode'; import { DocumentSymbolProvider, SymbolInformation, SymbolKind, TextDocument, CancellationToken, Uri, Hierarchy, SymbolInformation2 } from 'vscode';
import * as Proto from '../protocol'; import * as Proto from '../protocol';
import * as PConst from '../protocol.const'; import * as PConst from '../protocol.const';
...@@ -31,7 +31,7 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP ...@@ -31,7 +31,7 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
public constructor( public constructor(
private readonly client: ITypeScriptServiceClient) { } private readonly client: ITypeScriptServiceClient) { }
public async provideDocumentSymbols(resource: TextDocument, token: CancellationToken): Promise<any[]> { // todo@joh `any[]` temporary hack to make typescript happy... public async provideDocumentSymbols(resource: TextDocument, token: CancellationToken): Promise<any> { // todo@joh `any[]` temporary hack to make typescript happy...
const filepath = this.client.normalizePath(resource.uri); const filepath = this.client.normalizePath(resource.uri);
if (!filepath) { if (!filepath) {
return []; return [];
...@@ -41,24 +41,27 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP ...@@ -41,24 +41,27 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
}; };
try { try {
const result: SymbolInformation[] | HierarchicalSymbolInformation[] = [];
if (this.client.apiVersion.has206Features()) { if (this.client.apiVersion.has206Features()) {
const response = await this.client.execute('navtree', args, token); const response = await this.client.execute('navtree', args, token);
if (response.body) { if (response.body) {
// The root represents the file. Ignore this when showing in the UI // The root represents the file. Ignore this when showing in the UI
let tree = response.body; let tree = response.body;
if (tree.childItems) { if (tree.childItems) {
tree.childItems.forEach(item => TypeScriptDocumentSymbolProvider.convertNavTree(resource.uri, result as HierarchicalSymbolInformation[], item)); let result = new Array<Hierarchy<SymbolInformation2>>();
tree.childItems.forEach(item => TypeScriptDocumentSymbolProvider.convertNavTree(resource.uri, result, item));
return result;
} }
} }
} else { } else {
const response = await this.client.execute('navbar', args, token); const response = await this.client.execute('navbar', args, token);
if (response.body) { if (response.body) {
let result = new Array<SymbolInformation>();
let foldingMap: ObjectMap<SymbolInformation> = Object.create(null); let foldingMap: ObjectMap<SymbolInformation> = Object.create(null);
response.body.forEach(item => TypeScriptDocumentSymbolProvider.convertNavBar(resource.uri, 0, foldingMap, result as SymbolInformation[], item)); response.body.forEach(item => TypeScriptDocumentSymbolProvider.convertNavBar(resource.uri, 0, foldingMap, result as SymbolInformation[], item));
return result;
} }
} }
return result; return [];
} catch (e) { } catch (e) {
return []; return [];
} }
...@@ -82,24 +85,25 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP ...@@ -82,24 +85,25 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
} }
} }
private static convertNavTree(resource: Uri, bucket: HierarchicalSymbolInformation[], item: Proto.NavigationTree): void { private static convertNavTree(resource: Uri, bucket: Hierarchy<SymbolInformation>[], item: Proto.NavigationTree): void {
const result = new HierarchicalSymbolInformation( if (!TypeScriptDocumentSymbolProvider.shouldInclueEntry(item.text)) {
return;
}
const symbolInfo = new SymbolInformation2(
item.text, item.text,
'', // detail, e.g. signature etc '', // todo@joh detail
outlineTypeTable[item.kind as string] || SymbolKind.Variable, outlineTypeTable[item.kind as string] || SymbolKind.Variable,
typeConverters.Range.fromTextSpan(item.spans[0]),
typeConverters.Location.fromTextSpan(resource, item.spans[0]), typeConverters.Location.fromTextSpan(resource, item.spans[0]),
typeConverters.Range.fromTextSpan(item.spans[0])
); );
const hierarchy = new Hierarchy(symbolInfo);
if (item.childItems && item.childItems.length > 0) { if (item.childItems && item.childItems.length > 0) {
result.children = [];
for (const child of item.childItems) { for (const child of item.childItems) {
TypeScriptDocumentSymbolProvider.convertNavTree(resource, result.children, child); TypeScriptDocumentSymbolProvider.convertNavTree(resource, hierarchy.children, child);
} }
} }
bucket.push(hierarchy);
if (TypeScriptDocumentSymbolProvider.shouldInclueEntry(result.name)) {
bucket.push(result);
}
} }
private static shouldInclueEntry(name: string): boolean { private static shouldInclueEntry(name: string): boolean {
......
...@@ -571,19 +571,20 @@ declare module 'vscode' { ...@@ -571,19 +571,20 @@ declare module 'vscode' {
//#region Joh: hierarchical document symbols, https://github.com/Microsoft/vscode/issues/34968 //#region Joh: hierarchical document symbols, https://github.com/Microsoft/vscode/issues/34968
export class HierarchicalSymbolInformation { export class Hierarchy<T> {
name: string; parent: T;
kind: SymbolKind; children: Hierarchy<T>[];
constructor(element: T);
}
export class SymbolInformation2 extends SymbolInformation {
detail: string; detail: string;
location: Location;
range: Range; range: Range;
children: HierarchicalSymbolInformation[]; constructor(name: string, detail: string, kind: SymbolKind, range: Range, location: Location);
constructor(name: string, detail: string, kind: SymbolKind, location: Location, range: Range);
} }
export interface DocumentSymbolProvider { export interface DocumentSymbolProvider {
provideDocumentSymbols(document: TextDocument, token: CancellationToken): ProviderResult<HierarchicalSymbolInformation[] | SymbolInformation[]>; provideDocumentSymbols(document: TextDocument, token: CancellationToken): ProviderResult<SymbolInformation[] | Hierarchy<SymbolInformation>[]>;
} }
//#endregion //#endregion
......
...@@ -700,10 +700,16 @@ export function createApiFactory( ...@@ -700,10 +700,16 @@ export function createApiFactory(
SourceBreakpoint: extHostTypes.SourceBreakpoint, SourceBreakpoint: extHostTypes.SourceBreakpoint,
StatusBarAlignment: extHostTypes.StatusBarAlignment, StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation, SymbolInformation: extHostTypes.SymbolInformation,
HierarchicalSymbolInformation: class extends extHostTypes.HierarchicalSymbolInformation { SymbolInformation2: class extends extHostTypes.SymbolInformation2 {
constructor(name, detail, kind, keyof, range) { constructor(name, detail, kind, range, location) {
checkProposedApiEnabled(extension); checkProposedApiEnabled(extension);
super(name, detail, kind, keyof, range); super(name, detail, kind, range, location);
}
},
Hierarchy: class <T> extends extHostTypes.Hierarchy<T> {
constructor(parent: T) {
checkProposedApiEnabled(extension);
super(parent);
} }
}, },
SymbolKind: extHostTypes.SymbolKind, SymbolKind: extHostTypes.SymbolKind,
......
...@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; ...@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as typeConvert from 'vs/workbench/api/node/extHostTypeConverters'; import * as typeConvert from 'vs/workbench/api/node/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, HierarchicalSymbolInformation, SymbolInformation } from 'vs/workbench/api/node/extHostTypes'; import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, Hierarchy, SymbolInformation2 } from 'vs/workbench/api/node/extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/model'; import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes'; import * as modes from 'vs/editor/common/modes';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService'; import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
...@@ -44,14 +44,14 @@ class OutlineAdapter { ...@@ -44,14 +44,14 @@ class OutlineAdapter {
return undefined; return undefined;
} }
let [probe] = value; let [probe] = value;
if (!(probe instanceof HierarchicalSymbolInformation)) { if (!(probe instanceof Hierarchy)) {
value = OutlineAdapter._asSymbolTree(<SymbolInformation[]>value); value = OutlineAdapter._asSymbolHierarchy(<SymbolInformation[]>value);
} }
return (<HierarchicalSymbolInformation[]>value).map(typeConvert.HierarchicalSymbolInformation.from); return (<Hierarchy<SymbolInformation2>[]>value).map(typeConvert.HierarchicalSymbolInformation.from);
}); });
} }
private static _asSymbolTree(info: SymbolInformation[]): vscode.HierarchicalSymbolInformation[] { private static _asSymbolHierarchy(info: SymbolInformation[]): vscode.Hierarchy<SymbolInformation2>[] {
// first sort by start (and end) and then loop over all elements // first sort by start (and end) and then loop over all elements
// and build a tree based on containment. // and build a tree based on containment.
info = info.slice(0).sort((a, b) => { info = info.slice(0).sort((a, b) => {
...@@ -61,10 +61,10 @@ class OutlineAdapter { ...@@ -61,10 +61,10 @@ class OutlineAdapter {
} }
return res; return res;
}); });
let res: HierarchicalSymbolInformation[] = []; let res: Hierarchy<SymbolInformation2>[] = [];
let parentStack: HierarchicalSymbolInformation[] = []; let parentStack: Hierarchy<SymbolInformation2>[] = [];
for (let i = 0; i < info.length; i++) { for (let i = 0; i < info.length; i++) {
let element = new HierarchicalSymbolInformation(info[i].name, '', info[i].kind, info[i].location, info[i].location.range); let element = new Hierarchy(new SymbolInformation2(info[i].name, '', info[i].kind, info[i].location.range, info[i].location));
while (true) { while (true) {
if (parentStack.length === 0) { if (parentStack.length === 0) {
parentStack.push(element); parentStack.push(element);
...@@ -72,7 +72,7 @@ class OutlineAdapter { ...@@ -72,7 +72,7 @@ class OutlineAdapter {
break; break;
} }
let parent = parentStack[parentStack.length - 1]; let parent = parentStack[parentStack.length - 1];
if (parent.range.contains(element.range)) { if (parent.parent.range.contains(element.parent.range)) {
parent.children.push(element); parent.children.push(element);
parentStack.push(element); parentStack.push(element);
break; break;
......
...@@ -364,27 +364,27 @@ export namespace SymbolInformation { ...@@ -364,27 +364,27 @@ export namespace SymbolInformation {
} }
export namespace HierarchicalSymbolInformation { export namespace HierarchicalSymbolInformation {
export function from(info: vscode.HierarchicalSymbolInformation): modes.SymbolInformation { export function from(info: vscode.Hierarchy<vscode.SymbolInformation2>): modes.SymbolInformation {
let result: modes.SymbolInformation = { let result: modes.SymbolInformation = {
name: info.name, name: info.parent.name,
detail: info.detail, detail: info.parent.detail,
location: location.from(info.location), location: location.from(info.parent.location),
definingRange: Range.from(info.range), definingRange: Range.from(info.parent.range),
kind: SymbolKind.from(info.kind) kind: SymbolKind.from(info.parent.kind)
}; };
if (info.children) { if (info.children) {
result.children = info.children.map(from); result.children = info.children.map(from);
} }
return result; return result;
} }
export function to(info: modes.SymbolInformation): types.HierarchicalSymbolInformation { export function to(info: modes.SymbolInformation): types.Hierarchy<vscode.SymbolInformation2> {
let result = new types.HierarchicalSymbolInformation( let result = new types.Hierarchy<vscode.SymbolInformation2>(new types.SymbolInformation2(
info.name, info.name,
info.detail, info.detail,
SymbolKind.to(info.kind), SymbolKind.to(info.kind),
Range.to(info.definingRange),
location.to(info.location), location.to(info.location),
Range.to(info.definingRange) ));
);
if (info.children) { if (info.children) {
result.children = info.children.map(to); result.children = info.children.map(to);
} }
......
...@@ -876,19 +876,24 @@ export class SymbolInformation { ...@@ -876,19 +876,24 @@ export class SymbolInformation {
} }
} }
export class HierarchicalSymbolInformation { export class SymbolInformation2 extends SymbolInformation {
name: string;
location: Location;
detail: string; detail: string;
kind: SymbolKind;
range: Range; range: Range;
children: HierarchicalSymbolInformation[];
constructor(name: string, detail: string, kind: SymbolKind, location: Location, range: Range) { constructor(name: string, detail: string, kind: SymbolKind, range: Range, location: Location) {
this.name = name; super(name, kind, undefined, location);
this.kind = kind; this.detail = detail;
this.location = location;
this.range = range; this.range = range;
}
}
export class Hierarchy<T> {
parent: T;
children: Hierarchy<T>[];
constructor(parent: T) {
this.parent = parent;
this.children = []; this.children = [];
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册