coc-ccls
Version:
C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting
102 lines (83 loc) • 2.96 kB
text/typescript
import {
commands,
} from 'coc.nvim';
import * as path from 'path';
import { Disposable, LanguageClient } from 'vscode-languageclient/lib/main';
import {
Event,
Position,
} from "vscode-languageserver-protocol";
import Uri from "vscode-uri";
import { IHierarchyNode } from '../types';
import { disposeAll, setContext } from '../utils';
function nodeIsIncomplete(node: IHierarchyNode) {
return node.children.length !== node.numChildren;
}
export abstract class Hierarchy<T extends IHierarchyNode> implements TreeDataProvider<IHierarchyNode>, Disposable {
protected abstract contextValue: string;
protected _dispose: Disposable[] = [];
protected readonly onDidChangeEmitter: EventEmitter<IHierarchyNode> = new EventEmitter<IHierarchyNode>();
// tslint:disable-next-line:member-ordering
public readonly onDidChangeTreeData: Event<IHierarchyNode> = this.onDidChangeEmitter.event;
protected root?: T;
constructor(
readonly languageClient: LanguageClient,
revealCmdName: string,
closeCmdName: string
) {
this._dispose.push(commands.registerTextEditorCommand(
revealCmdName, this.reveal, this
));
this._dispose.push(commands.registerCommand(
closeCmdName, this.close, this
));
}
public dispose() {
disposeAll(this._dispose);
}
public getTreeItem(element: T): TreeItem {
const ti = new TreeItem(element.name);
ti.contextValue = 'cclsGoto';
ti.command = {
arguments: [element, element.numChildren > 0],
command: 'ccls.hackGotoForTreeView',
title: 'Goto',
};
if (element.numChildren > 0) {
if (element.children.length > 0)
ti.collapsibleState = TreeItemCollapsibleState.Expanded;
else
ti.collapsibleState = TreeItemCollapsibleState.Collapsed;
}
const elpath = Uri.parse(element.location.uri).path;
ti.description = `${path.basename(elpath)}:${element.location.range.start.line + 1}`;
this.onTreeItem(ti, element);
return ti;
}
public async getChildren(element?: T): Promise<IHierarchyNode[]> {
if (!this.root)
return [];
if (!element)
return [this.root];
if (!nodeIsIncomplete(element))
return element.children;
return this.onGetChildren(element);
}
protected abstract onTreeItem(ti: TreeItem, element: T): void;
protected abstract async onReveal(uri: Uri, position: Position): Promise<T>;
protected abstract async onGetChildren(element: T): Promise<IHierarchyNode[]>;
private async reveal(editor: TextEditor) {
setContext(this.contextValue, true);
const position = editor.selection.active;
const uri = editor.document.uri;
const callNode = await this.onReveal(uri, position);
this.root = callNode;
this.onDidChangeEmitter.fire();
commands.executeCommand('workbench.view.explorer');
}
private close() {
setContext(this.contextValue, false);
this.root = undefined;
this.onDidChangeEmitter.fire();
}
}