nridge created this revision. Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, ilya-biryukov. Herald added a project: clang.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D67537 Files: clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts clang-tools-extra/clangd/clients/clangd-vscode/src/inactive-regions.ts
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/inactive-regions.ts =================================================================== --- /dev/null +++ clang-tools-extra/clangd/clients/clangd-vscode/src/inactive-regions.ts @@ -0,0 +1,83 @@ +import * as vscode from 'vscode'; +import * as vscodelc from 'vscode-languageclient'; +import * as vscodelct from 'vscode-languageserver-types'; + +// Parameters for the inactive regions (server-side) push notification. +// Mirrors the structure in the inactive regions proposal for LSP. +interface InactiveRegionsParams { + // The text document that has to be decorated with the inactive regions + // information. + textDocument: vscodelct.VersionedTextDocumentIdentifier; + // An array of inactive regions. + regions: vscodelc.Range[]; +} + +// Language server push notification providing the inactive regions +// information for a text document. +export const NotificationType = + new vscodelc.NotificationType<InactiveRegionsParams, void>( + 'textDocument/inactiveRegions'); + +export class InactiveRegionsFeature implements vscodelc.StaticFeature { + private decorationType: vscode.TextEditorDecorationType; + private p2c: vscodelc.Protocol2CodeConverter; + private files: Map<string, vscode.Range[]> = new Map(); + private subscriptions: vscode.Disposable[] = []; + + constructor(client: vscodelc.LanguageClient) { + this.p2c = client.protocol2CodeConverter; + } + + fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) { + // Extend the ClientCapabilities type and add inactive regions + // capability to the object. + const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities & + { inactiveRegionsCapabilities?: { inactiveRegions: boolean } } = + capabilities.textDocument; + textDocumentCapabilities.inactiveRegionsCapabilities = { + inactiveRegions: true, + }; + } + initialize(capabilities: vscodelc.ServerCapabilities, + documentSelector: vscodelc.DocumentSelector | undefined) { + this.decorationType = vscode.window.createTextEditorDecorationType({ + isWholeLine: true, + light: { + color: "rgb(100, 100, 100)", + backgroundColor: "rgba(220, 220, 220, 0.3)", + }, + dark: { + color: "rgb(100, 100, 100)", + backgroundColor: "rgba(18, 18, 18, 0.3)", + } + }); + this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors( + (editors) => editors.forEach( + (e) => this.applyHighlights(e.document.uri.toString())))); + } + + handleNotification(params: InactiveRegionsParams) { + const fileUri = params.textDocument.uri; + const ranges = params.regions.map(this.p2c.asRange); + this.files.set(fileUri, ranges); + this.applyHighlights(fileUri); + } + + applyHighlights(fileUri: string) { + if (!this.files.has(fileUri)) { + return; + } + const ranges = this.files.get(fileUri); + vscode.window.visibleTextEditors.forEach((e) => { + if (e.document.uri.toString() !== fileUri) + return; + e.setDecorations(this.decorationType, ranges); + }); + } + + // Disposes of all disposable resources used by this object. + public dispose() { + this.subscriptions.forEach((d) => d.dispose()); + this.subscriptions = []; + } +} \ No newline at end of file Index: clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts =================================================================== --- clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts +++ clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import * as vscodelc from 'vscode-languageclient'; import * as semanticHighlighting from './semantic-highlighting'; +import * as inactiveRegions from './inactive-regions'; /** * Method to get workspace configuration option @@ -13,15 +14,15 @@ } namespace SwitchSourceHeaderRequest { -export const type = - new vscodelc.RequestType<vscodelc.TextDocumentIdentifier, string|undefined, - void, void>('textDocument/switchSourceHeader'); + export const type = + new vscodelc.RequestType<vscodelc.TextDocumentIdentifier, string | undefined, + void, void>('textDocument/switchSourceHeader'); } class FileStatus { private statuses = new Map<string, any>(); private readonly statusBarItem = - vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10); + vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10); onFileUpdated(fileStatus: any) { const filePath = vscode.Uri.parse(fileStatus.uri); @@ -58,7 +59,7 @@ // prompt up the failure to users. logFailedRequest(rpcReply: vscodelc.RPCMessageType, error: any) { if (error instanceof vscodelc.ResponseError && - rpcReply.method === "workspace/executeCommand") + rpcReply.method === "workspace/executeCommand") vscode.window.showErrorMessage(error.message); // Call default implementation. super.logFailedRequest(rpcReply, error); @@ -73,13 +74,13 @@ const syncFileEvents = getConfig<boolean>('syncFileEvents', true); const clangd: vscodelc.Executable = { - command : getConfig<string>('path'), - args : getConfig<string[]>('arguments') + command: getConfig<string>('path'), + args: getConfig<string[]>('arguments') }; const traceFile = getConfig<string>('trace'); if (!!traceFile) { - const trace = {CLANGD_TRACE : traceFile}; - clangd.options = {env : {...process.env, ...trace}}; + const trace = { CLANGD_TRACE: traceFile }; + clangd.options = { env: { ...process.env, ...trace } }; } const serverOptions: vscodelc.ServerOptions = clangd; @@ -89,73 +90,80 @@ // However, VSCode does not have CUDA as a supported language yet, so we // cannot add a corresponding activationEvent for CUDA files and clangd will // *not* load itself automatically on '.cu' files. - const cudaFilePattern: string = '**/*.{' + [ 'cu' ].join() + '}'; + const cudaFilePattern: string = '**/*.{' + ['cu'].join() + '}'; const clientOptions: vscodelc.LanguageClientOptions = { - // Register the server for c-family and cuda files. - documentSelector: [ - { scheme: 'file', language: 'c' }, - { scheme: 'file', language: 'cpp' }, - { scheme: 'file', language: 'objective-c'}, - { scheme: 'file', language: 'objective-cpp'}, - { scheme: 'file', pattern: cudaFilePattern }, - ], - synchronize: !syncFileEvents ? undefined : { - // FIXME: send sync file events when clangd provides implemenatations. - }, - initializationOptions: { clangdFileStatus: true }, - // Do not switch to output window when clangd returns output - revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never - }; + // Register the server for c-family and cuda files. + documentSelector: [ + { scheme: 'file', language: 'c' }, + { scheme: 'file', language: 'cpp' }, + { scheme: 'file', language: 'objective-c' }, + { scheme: 'file', language: 'objective-cpp' }, + { scheme: 'file', pattern: cudaFilePattern }, + ], + synchronize: !syncFileEvents ? undefined : { + // FIXME: send sync file events when clangd provides implemenatations. + }, + initializationOptions: { clangdFileStatus: true }, + // Do not switch to output window when clangd returns output + revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never + }; const clangdClient = new ClangdLanguageClient('Clang Language Server', - serverOptions, clientOptions); + serverOptions, clientOptions); const semanticHighlightingFeature = - new semanticHighlighting.SemanticHighlightingFeature(); + new semanticHighlighting.SemanticHighlightingFeature(); + const inactiveRegionsFeature = new inactiveRegions.InactiveRegionsFeature(clangdClient); + context.subscriptions.push( + vscode.Disposable.from(semanticHighlightingFeature)); context.subscriptions.push( - vscode.Disposable.from(semanticHighlightingFeature)); + vscode.Disposable.from(inactiveRegionsFeature)); clangdClient.registerFeature(semanticHighlightingFeature); + clangdClient.registerFeature(inactiveRegionsFeature); console.log('Clang Language Server is now active!'); context.subscriptions.push(clangdClient.start()); context.subscriptions.push(vscode.commands.registerCommand( - 'clangd-vscode.switchheadersource', async () => { - const uri = - vscode.Uri.file(vscode.window.activeTextEditor.document.fileName); - if (!uri) { - return; - } - const docIdentifier = - vscodelc.TextDocumentIdentifier.create(uri.toString()); - const sourceUri = await clangdClient.sendRequest( - SwitchSourceHeaderRequest.type, docIdentifier); - if (!sourceUri) { - return; - } - const doc = await vscode.workspace.openTextDocument( - vscode.Uri.parse(sourceUri)); - vscode.window.showTextDocument(doc); - })); + 'clangd-vscode.switchheadersource', async () => { + const uri = + vscode.Uri.file(vscode.window.activeTextEditor.document.fileName); + if (!uri) { + return; + } + const docIdentifier = + vscodelc.TextDocumentIdentifier.create(uri.toString()); + const sourceUri = await clangdClient.sendRequest( + SwitchSourceHeaderRequest.type, docIdentifier); + if (!sourceUri) { + return; + } + const doc = await vscode.workspace.openTextDocument( + vscode.Uri.parse(sourceUri)); + vscode.window.showTextDocument(doc); + })); const status = new FileStatus(); context.subscriptions.push(vscode.Disposable.from(status)); context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor( - () => { status.updateStatus(); })); - context.subscriptions.push(clangdClient.onDidChangeState(({newState}) => { + () => { status.updateStatus(); })); + context.subscriptions.push(clangdClient.onDidChangeState(({ newState }) => { if (newState == vscodelc.State.Running) { // clangd starts or restarts after crash. clangdClient.onNotification( - 'textDocument/clangd.fileStatus', - (fileStatus) => { status.onFileUpdated(fileStatus); }); + 'textDocument/clangd.fileStatus', + (fileStatus) => { status.onFileUpdated(fileStatus); }); clangdClient.onNotification( - semanticHighlighting.NotificationType, - semanticHighlightingFeature.handleNotification.bind( - semanticHighlightingFeature)); + semanticHighlighting.NotificationType, + semanticHighlightingFeature.handleNotification.bind( + semanticHighlightingFeature)); + clangdClient.onNotification(inactiveRegions.NotificationType, + inactiveRegionsFeature.handleNotification.bind(inactiveRegionsFeature)); } else if (newState == vscodelc.State.Stopped) { // Clear all cached statuses when clangd crashes. status.clear(); semanticHighlightingFeature.dispose(); + inactiveRegionsFeature.dispose(); } })); // An empty place holder for the activate command, otherwise we'll get an // "command is not registered" error. context.subscriptions.push(vscode.commands.registerCommand( - 'clangd-vscode.activate', async () => {})); + 'clangd-vscode.activate', async () => { })); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits