UNPKG

coc-ccls

Version:

C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting

102 lines (83 loc) 2.96 kB
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(); } }