coc-ccls
Version:
C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting
90 lines (81 loc) • 2.63 kB
text/typescript
import { commands } from 'coc.nvim';
import { LanguageClient } from 'vscode-languageclient/lib/main';
import {
Position,
} from "vscode-languageserver-protocol";
import Uri from "vscode-uri";
import { Icon, IHierarchyNode } from '../types';
import { resourcePath } from '../utils';
import { Hierarchy } from './hierarchy';
enum CallType {
Normal = 0,
Base = 1,
Derived = 2,
All = CallType.Base | CallType.Derived // Normal and Base and Derived
}
interface CallHierarchyNode extends IHierarchyNode {
children: CallHierarchyNode[];
callType: CallType;
}
export class CallHierarchyProvider extends Hierarchy<CallHierarchyNode> {
protected contextValue: string = 'extension.ccls.callHierarchyVisible';
private baseIcon: Icon;
private derivedIcon: Icon;
private useCallee = false;
constructor(
languageClient: LanguageClient
) {
super(languageClient, 'ccls.callHierarchy', 'ccls.closeCallHierarchy');
this.baseIcon = {
dark: resourcePath("base-dark.svg"),
light: resourcePath("base-light.svg")
};
this.derivedIcon = {
dark: resourcePath("derived-dark.svg"),
light: resourcePath("derived-light.svg")
};
this._dispose.push(commands.registerCommand("ccls.call.useCallers", () => this.updateCallee(false)));
this._dispose.push(commands.registerCommand("ccls.call.useCallees", () => this.updateCallee(true)));
}
public onTreeItem(ti: TreeItem, element: CallHierarchyNode) {
if (element.callType === CallType.Base)
ti.iconPath = this.baseIcon;
else if (element.callType === CallType.Derived)
ti.iconPath = this.derivedIcon;
}
protected async onGetChildren(element: CallHierarchyNode): Promise<CallHierarchyNode[]> {
const result = await this.languageClient.sendRequest<CallHierarchyNode>('$ccls/call', {
callType: CallType.All,
callee: this.useCallee,
hierarchy: true,
id: element.id,
levels: 1,
qualified: false,
});
element.children = result.children;
return result.children;
}
protected async onReveal(uri: Uri, position: Position): Promise<CallHierarchyNode> {
return this.languageClient.sendRequest<CallHierarchyNode>(
'$ccls/call',
{
callType: CallType.All,
callee: this.useCallee,
hierarchy: true,
levels: 2,
position,
qualified: false,
textDocument: {
uri: uri.toString(true),
},
}
);
}
private updateCallee(val: boolean) {
this.useCallee = val;
if (this.root) {
this.root.children = [];
this.onDidChangeEmitter.fire();
}
}
}