Skip to content

Commit

Permalink
Export client from activation as API for use in other extensions (#575)
Browse files Browse the repository at this point in the history
  • Loading branch information
thegecko authored Jul 4, 2024
1 parent 37ba1e9 commit 290f1bb
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 15 deletions.
38 changes: 38 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# VS Code clangd Extension API

The VS Code clangd extension exposes an API that other extensions can consume:

```typescript
import * as vscode from 'vscode';
import type { ClangdExtension, ASTParams, ASTNode } from '@clangd/vscode-clangd';

const CLANGD_EXTENSION = 'llvm-vs-code-extensions.vscode-clangd';
const CLANGD_API_VERSION = 1;

const ASTRequestMethod = 'textDocument/ast';

const provideHover = async (document: vscode.TextDocument, position: vscode.Position, _token: vscode.CancellationToken): Promise<vscode.Hover | undefined> => {

const clangdExtension = vscode.extensions.getExtension<ClangdExtension>(CLANGD_EXTENSION);

if (clangdExtension) {
const api = (await clangdExtension.activate()).getApi(CLANGD_API_VERSION);

const textDocument = api.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document);
const range = api.languageClient.code2ProtocolConverter.asRange(new vscode.Range(position, position));
const params: ASTParams = { textDocument, range };

const ast: ASTNode | undefined = await api.languageClient.sendRequest(ASTRequestMethod, params);

if (!ast) {
return undefined;
}

return {
contents: [ast.kind]
};
}
};

vscode.languages.registerHoverProvider(['c', 'cpp'], { provideHover });
```
15 changes: 15 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "@clangd/vscode-clangd",
"version": "0.0.0",
"description": "API for the llvm-vs-code-extensions.vscode-clangd VS Code extension",
"types": "vscode-clangd.d.ts",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
},
"repository": "https://github.com/clangd/vscode-clangd",
"license": "MIT",
"homepage": "https://github.com/clangd/vscode-clangd/blob/master/api/README.md",
"dependencies": {
"vscode-languageclient": "8.0.2"
}
}
36 changes: 36 additions & 0 deletions api/vscode-clangd.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {BaseLanguageClient} from 'vscode-languageclient';
import * as vscodelc from 'vscode-languageclient/node';

export interface ClangdApiV1 {
// vscode-clangd's language client which can be used to send requests to the
// clangd language server
// Standard requests:
// https://microsoft.github.io/language-server-protocol/specifications/specification-current
// clangd custom requests:
// https://clangd.llvm.org/extensions
languageClient: BaseLanguageClient
}

export interface ClangdExtension {
getApi(version: 1): ClangdApiV1;
}

// clangd custom request types
// (type declarations for other requests may be added later)

// textDocument/ast wire format
// Send: position
export interface ASTParams {
textDocument: vscodelc.TextDocumentIdentifier;
range: vscodelc.Range;
}

// Receive: tree of ASTNode
export interface ASTNode {
role: string; // e.g. expression
kind: string; // e.g. BinaryOperator
detail?: string; // e.g. ||
arcana?: string; // e.g. BinaryOperator <0x12345> <col:12, col:1> 'bool' '||'
children?: Array<ASTNode>;
range?: vscodelc.Range;
}
16 changes: 16 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {BaseLanguageClient} from 'vscode-languageclient';

import {ClangdApiV1, ClangdExtension} from '../api/vscode-clangd';

export class ClangdExtensionImpl implements ClangdExtension {
constructor(private readonly client: BaseLanguageClient) {}

public getApi(version: 1): ClangdApiV1;
public getApi(version: number): unknown {
if (version === 1) {
return {languageClient: this.client};
}

throw new Error(`No API version ${version} found`);
}
}
18 changes: 4 additions & 14 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,17 @@ import * as vscode from 'vscode';
import * as vscodelc from 'vscode-languageclient/node';

import {ClangdContext} from './clangd-context';
import type {ASTParams, ASTNode} from '../api/vscode-clangd';

const ASTRequestMethod = 'textDocument/ast';

export function activate(context: ClangdContext) {
const feature = new ASTFeature(context);
context.client.registerFeature(feature);
}

// The wire format: we send a position, and get back a tree of ASTNode.
interface ASTParams {
textDocument: vscodelc.TextDocumentIdentifier;
range: vscodelc.Range;
}
interface ASTNode {
role: string; // e.g. expression
kind: string; // e.g. BinaryOperator
detail?: string; // e.g. ||
arcana?: string; // e.g. BinaryOperator <0x12345> <col:12, col:1> 'bool' '||'
children?: Array<ASTNode>;
range?: vscodelc.Range;
}
const ASTRequestType =
new vscodelc.RequestType<ASTParams, ASTNode|null, void>('textDocument/ast');
new vscodelc.RequestType<ASTParams, ASTNode|null, void>(ASTRequestMethod);

class ASTFeature implements vscodelc.StaticFeature {
constructor(private context: ClangdContext) {
Expand Down
8 changes: 7 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import * as vscode from 'vscode';

import {ClangdExtension} from '../api/vscode-clangd';

import {ClangdExtensionImpl} from './api';
import {ClangdContext} from './clangd-context';

/**
* This method is called when the extension is activated. The extension is
* activated the very first time a command is executed.
*/
export async function activate(context: vscode.ExtensionContext) {
export async function activate(context: vscode.ExtensionContext):
Promise<ClangdExtension> {
const outputChannel = vscode.window.createOutputChannel('clangd');
context.subscriptions.push(outputChannel);

Expand Down Expand Up @@ -67,4 +71,6 @@ export async function activate(context: vscode.ExtensionContext) {
}
}, 5000);
}

return new ClangdExtensionImpl(clangdContext.client);
}

0 comments on commit 290f1bb

Please sign in to comment.