diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore b/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -out -node_modules -.vscode-test diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json b/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/launch.json +++ /dev/null @@ -1,28 +0,0 @@ -// A launch configuration that compiles extension and opens it inside a new window. -{ - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], - "preLaunchTask": "npm" - }, - { - "name": "Launch Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ], - "preLaunchTask": "npm" - } - ] -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json b/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true // set this to false to include "out" folder in search results - } -} \ No newline at end of file diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json b/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscode/tasks.json +++ /dev/null @@ -1,32 +0,0 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -// Task runner calls custom npm script to compile the extension. -{ - "version": "2.0.0", - - // Run NPM. - "command": "npm", - - // This command is a shell script. - "type": "shell", - - // show the output window only if unrecognized errors occur. - "presentation": { - "reveal": "silent", - }, - - // Run custom "compile" script as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // tsc compiler is kept alive and runs in the background. - "isBackground": true, - - // Find compilation problems in the output through tsc in watch mode. - "problemMatcher": "$tsc-watch" -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore b/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/.vscodeignore +++ /dev/null @@ -1,9 +0,0 @@ -.vscode/** -.vscode-test/** -out/test/** -test/** -src/** -**/*.map -.gitignore -tsconfig.json -vsc-extension-quickstart.md diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/DEVELOPING.md b/clang-tools-extra/clangd/clients/clangd-vscode/DEVELOPING.md deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/DEVELOPING.md +++ /dev/null @@ -1,53 +0,0 @@ -# Development - -A guide of developing `vscode-clangd` extension. - -## Requirements - -* VS Code -* node.js and npm - -## Steps - -1. Make sure you disable the installed `vscode-clangd` extension in VS Code. -2. Make sure you have clangd in `/usr/bin/clangd` or edit `src/extension.ts` to -point to the binary. -3. To start a development instance of VS code extended with this, run: - -```bash - $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/ - $ npm install - $ code . - # When VSCode starts, press . -``` - -# Contributing - -Please follow the existing code style when contributing to the extension, we -recommend to run `npm run format` before sending a patch. - -# Publish to VS Code Marketplace - -New changes to `clangd-vscode` are not released until a new version is published -to the marketplace. - -## Requirements - -* Make sure install the `vsce` command (`npm install -g vsce`) -* `llvm-vs-code-extensions` account -* Bump the version in `package.json`, and commit the change to upstream - -The extension is published under `llvm-vs-code-extensions` account, which is -maintained by clangd developers. If you want to make a new release, please -contact clangd-dev@lists.llvm.org. - -## Steps - -```bash - $ cd /path/to/clang-tools-extra/clangd/clients/clangd-vscode/ - # For the first time, you need to login into the account. vsce will ask you - for the Personal Access Token and will remember it for future commands. - $ vsce login llvm-vs-code-extensions - # Publish the extension to the VSCode marketplace. - $ npm run publish -``` diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE b/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2019 The LLVM Developers - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/README.md b/clang-tools-extra/clangd/clients/clangd-vscode/README.md deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# vscode-clangd - -Provides C/C++ language IDE features for VS Code using [clangd](https://clang.llvm.org/extra/clangd.html): - - - code completion - - compile errors and warnings - - go-to-definition and cross references - - include management - - code formatting - - simple refactorings - -## Setup - -### `clangd` server - -`clangd` is a language server that must be installed separately, see -[getting started](https://clang.llvm.org/extra/clangd/Installation.html#installing-clangd). -The vscode-clangd extension will look for `clangd` on your PATH (you can change -this in the settings). - -### Project setup - -clangd is based on the clang C++ compiler, and understands even complex C++ -code. However, you must tell clangd how your project is built (compile flags). -[A `compile_commands.json` file](http://clang.llvm.org/docs/JSONCompilationDatabase.html) -can usually be generated by your build system -(e.g. by setting `-DCMAKE_EXPORT_COMPILE_COMMANDS=1` when building with CMake, -or with -[many other tools](https://sarcasm.github.io/notes/dev/compilation-database.html)). - -It should live at the top of your source tree: symlink or copy it there. - -## Features - -### Code completion - -Suggestions will appear as you type names, or after `.` or `->`. -Because clangd uses a full C++ parser, code completion has access to precise -type information. - -![Code completion](doc-assets/complete.png) - -### Errors, warnings, and clang-tidy - -Code errors are shown as you type (both as red squiggle underlines, and in the -"Problems" panel). These are the same as produced by the clang compiler, and -suggested fixes can automatically be applied. - -![Error with fix](doc-assets/diagnostics.png) - -Most clang-tidy checks are supported (these can be enabled using a [.clang-tidy -file](https://clang.llvm.org/extra/clang-tidy/)). - -### Cross-references - -Go-to-definition and find-references work across your code, using a project-wide -index. - -![Cross-reference list](doc-assets/xrefs.png) - -Press `Ctrl-P #` to quickly navigate to a symbol by name. - -### Include management - -Code completion works across your codebase and adds `#include` directives where -needed. The `•` shows includes that will be inserted. - -clangd can also suggest inserting missing #includes, where they cause errors. - -![Fix inserts include](doc-assets/include.png) - -### Formatting - -clangd uses the `clang-format` engine. You can format a file or the selection. -When "Format on Type" is enabled in the settings, pressing enter will cause -clangd to format the old line and semantically reindent. - -![Format-on-type](doc-assets/format.png) - -The style used for formatting (and certain other operations) is controlled by -the .clang-format file is controlled by the project's -[.clang-format file](https://clang.llvm.org/docs/ClangFormatStyleOptions.html). - -### Refactoring - -clangd supports some local refactorings. When you select an expression or -declaration, the lightbulb menu appears and you can choose a code action. - -![Extract variable code action](doc-assets/extract.png) - -Current refactorings include: - - extract variable/function - - expand `auto` types and macros - - use raw strings - - rename (bound to ``, rather than a contextual code action) - -## Bugs/contributing - -clangd and vscode-clangd are part of the [LLVM project](https://llvm.org). - -If you'd like to help out, reach out to clangd-dev@lists.llvm.org. - -If you've found a bug, please file at https://github.com/clangd/clangd/issues. diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/complete.png b/clang-tools-extra/clangd/clients/clangd-vscode/doc-assets/complete.png deleted file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@(option: string, defaultValue?: any): T { - const config = vscode.workspace.getConfiguration('clangd'); - return config.get(option, defaultValue); -} - -namespace SwitchSourceHeaderRequest { -export const type = - new vscodelc.RequestType('textDocument/switchSourceHeader'); -} - -class FileStatus { - private statuses = new Map(); - private readonly statusBarItem = - vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10); - - onFileUpdated(fileStatus: any) { - const filePath = vscode.Uri.parse(fileStatus.uri); - this.statuses.set(filePath.fsPath, fileStatus); - this.updateStatus(); - } - - updateStatus() { - const path = vscode.window.activeTextEditor.document.fileName; - const status = this.statuses.get(path); - if (!status) { - this.statusBarItem.hide(); - return; - } - this.statusBarItem.text = `clangd: ` + status.state; - this.statusBarItem.show(); - } - - clear() { - this.statuses.clear(); - this.statusBarItem.hide(); - } - - dispose() { this.statusBarItem.dispose(); } -} - -class ClangdLanguageClient extends vscodelc.LanguageClient { - // Override the default implementation for failed requests. The default - // behavior is just to log failures in the output panel, however output panel - // is designed for extension debugging purpose, normal users will not open it, - // thus when the failure occurs, normal users doesn't know that. - // - // For user-interactive operations (e.g. applyFixIt, applyTweaks), we will - // prompt up the failure to users. - logFailedRequest(rpcReply: vscodelc.RPCMessageType, error: any) { - if (error instanceof vscodelc.ResponseError && - rpcReply.method === "workspace/executeCommand") - vscode.window.showErrorMessage(error.message); - // Call default implementation. - super.logFailedRequest(rpcReply, error); - } -} - -class EnableEditsNearCursorFeature implements vscodelc.StaticFeature { - initialize() {} - fillClientCapabilities(capabilities: vscodelc.ClientCapabilities): void { - const extendedCompletionCapabilities: any = - capabilities.textDocument.completion; - extendedCompletionCapabilities.editsNearCursor = true; - } -} - -/** - * This method is called when the extension is activated. The extension is - * activated the very first time a command is executed. - */ -export function activate(context: vscode.ExtensionContext) { - const syncFileEvents = getConfig('syncFileEvents', true); - - const clangd: vscodelc.Executable = { - command : getConfig('path'), - args : getConfig('arguments') - }; - const traceFile = getConfig('trace'); - if (!!traceFile) { - const trace = {CLANGD_TRACE : traceFile}; - clangd.options = {env : {...process.env, ...trace}}; - } - const serverOptions: vscodelc.ServerOptions = clangd; - - const clientOptions: vscodelc.LanguageClientOptions = { - // Register the server for c-family and cuda files. - documentSelector: [ - { scheme: 'file', language: 'c' }, - { scheme: 'file', language: 'cpp' }, - // CUDA is not supported by vscode, but our extension does supports it. - { scheme: 'file', language: 'cuda' }, - { scheme: 'file', language: 'objective-c'}, - { scheme: 'file', language: 'objective-cpp'} - ], - synchronize: !syncFileEvents ? undefined : { - // FIXME: send sync file events when clangd provides implementations. - }, - initializationOptions: { clangdFileStatus: true }, - // Do not switch to output window when clangd returns output. - revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never, - - // We hack up the completion items a bit to prevent VSCode from re-ranking them - // and throwing away all our delicious signals like type information. - // - // VSCode sorts by (fuzzymatch(prefix, item.filterText), item.sortText) - // By adding the prefix to the beginning of the filterText, we get a perfect - // fuzzymatch score for every item. - // The sortText (which reflects clangd ranking) breaks the tie. - // This also prevents VSCode from filtering out any results due to the - // differences in how fuzzy filtering is applies, e.g. enable dot-to-arrow - // fixes in completion. - // - // We also have to mark the list as incomplete to force retrieving new rankings. - // See https://github.com/microsoft/language-server-protocol/issues/898 - middleware: { - provideCompletionItem: async (document, position, context, token, next) => { - let list = await next(document, position, context, token); - let items = (Array.isArray(list) ? list : list.items).map(item => { - // Gets the prefix used by VSCode when doing fuzzymatch. - let prefix = document.getText(new vscode.Range(item.range.start, position)) - if (prefix) - item.filterText = prefix + "_" + item.filterText; - return item; - }) - return new vscode.CompletionList(items, /*isIncomplete=*/true); - } - }, - }; - - const clangdClient = new ClangdLanguageClient('Clang Language Server', - serverOptions, clientOptions); - if (getConfig('semanticHighlighting')) { - const semanticHighlightingFeature = - new semanticHighlighting.SemanticHighlightingFeature(clangdClient, - context); - context.subscriptions.push( - vscode.Disposable.from(semanticHighlightingFeature)); - clangdClient.registerFeature(semanticHighlightingFeature); - } - clangdClient.registerFeature(new EnableEditsNearCursorFeature); - 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); - })); - 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}) => { - if (newState == vscodelc.State.Running) { - // clangd starts or restarts after crash. - clangdClient.onNotification( - 'textDocument/clangd.fileStatus', - (fileStatus) => { status.onFileUpdated(fileStatus); }); - } else if (newState == vscodelc.State.Stopped) { - // Clear all cached statuses when clangd crashes. - status.clear(); - } - })); - // 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 () => {})); -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts b/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts +++ /dev/null @@ -1,399 +0,0 @@ -import * as fs from 'fs'; -import * as jsonc from "jsonc-parser"; -import * as path from 'path'; -import * as vscode from 'vscode'; -import * as vscodelc from 'vscode-languageclient'; -import * as vscodelct from 'vscode-languageserver-types'; - -// Parameters for the semantic highlighting (server-side) push notification. -// Mirrors the structure in the semantic highlighting proposal for LSP. -interface SemanticHighlightingParams { - // The text document that has to be decorated with the semantic highlighting - // information. - textDocument: vscodelct.VersionedTextDocumentIdentifier; - // An array of semantic highlighting information. - lines: SemanticHighlightingInformation[]; -} -// Contains the highlighting information for a specified line. Mirrors the -// structure in the semantic highlighting proposal for LSP. -interface SemanticHighlightingInformation { - // The zero-based line position in the text document. - line: number; - // A base64 encoded string representing every single highlighted characters - // with its start position, length and the "lookup table" index of of the - // semantic highlighting Text Mate scopes. - tokens?: string; -} - -// A SemanticHighlightingToken decoded from the base64 data sent by clangd. -interface SemanticHighlightingToken { - // Start column for this token. - character: number; - // Length of the token. - length: number; - // The TextMate scope index to the clangd scope lookup table. - scopeIndex: number; -} -// A line of decoded highlightings from the data clangd sent. -export interface SemanticHighlightingLine { - // The zero-based line position in the text document. - line: number; - // All SemanticHighlightingTokens on the line. - tokens: SemanticHighlightingToken[]; -} - -// Language server push notification providing the semantic highlighting -// information for a text document. -const NotificationType = - new vscodelc.NotificationType( - 'textDocument/semanticHighlighting'); - -// The feature that should be registered in the vscode lsp for enabling -// experimental semantic highlighting. -export class SemanticHighlightingFeature implements vscodelc.StaticFeature { - // The TextMate scope lookup table. A token with scope index i has the scopes - // on index i in the lookup table. - scopeLookupTable: string[][]; - // The object that applies the highlightings clangd sends. - highlighter: Highlighter; - // Any disposables that should be cleaned up when clangd crashes. - private subscriptions: vscode.Disposable[] = []; - constructor(client: vscodelc.BaseLanguageClient, - context: vscode.ExtensionContext) { - context.subscriptions.push(client.onDidChangeState(({newState}) => { - if (newState == vscodelc.State.Running) { - // Register handler for semantic highlighting notification. - client.onNotification(NotificationType, - this.handleNotification.bind(this)); - } else if (newState == vscodelc.State.Stopped) { - // Dispose resources when clangd crashes. - this.dispose(); - } - })); - } - fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) { - // Extend the ClientCapabilities type and add semantic highlighting - // capability to the object. - const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities& - {semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} = - capabilities.textDocument; - textDocumentCapabilities.semanticHighlightingCapabilities = { - semanticHighlighting : true, - }; - } - - async loadCurrentTheme() { - const themeRuleMatcher = new ThemeRuleMatcher( - await loadTheme(vscode.workspace.getConfiguration('workbench') - .get('colorTheme'))); - this.highlighter.initialize(themeRuleMatcher); - } - - initialize(capabilities: vscodelc.ServerCapabilities, - documentSelector: vscodelc.DocumentSelector|undefined) { - // The semantic highlighting capability information is in the capabilities - // object but to access the data we must first extend the ServerCapabilities - // type. - const serverCapabilities: vscodelc.ServerCapabilities& - {semanticHighlighting?: {scopes : string[][]}} = capabilities; - if (!serverCapabilities.semanticHighlighting) - return; - this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes; - // Important that highlighter is created before the theme is loading as - // otherwise it could try to update the themeRuleMatcher without the - // highlighter being created. - this.highlighter = new Highlighter(this.scopeLookupTable); - this.subscriptions.push(vscode.Disposable.from(this.highlighter)); - // Adds a listener to reload the theme when it changes. - this.subscriptions.push( - vscode.workspace.onDidChangeConfiguration((conf) => { - if (!conf.affectsConfiguration('workbench.colorTheme')) - return; - this.loadCurrentTheme(); - })); - this.loadCurrentTheme(); - // Event handling for handling with TextDocuments/Editors lifetimes. - this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors( - (editors: vscode.TextEditor[]) => editors.forEach( - (e) => this.highlighter.applyHighlights(e.document.uri)))); - this.subscriptions.push(vscode.workspace.onDidCloseTextDocument( - (doc) => this.highlighter.removeFileHighlightings(doc.uri))); - } - - handleNotification(params: SemanticHighlightingParams) { - const lines: SemanticHighlightingLine[] = params.lines.map( - (line) => ({line : line.line, tokens : decodeTokens(line.tokens)})); - this.highlighter.highlight(vscode.Uri.parse(params.textDocument.uri), - lines); - } - // Disposes of all disposable resources used by this object. - public dispose() { - this.subscriptions.forEach((d) => d.dispose()); - this.subscriptions = []; - } -} - -// Converts a string of base64 encoded tokens into the corresponding array of -// HighlightingTokens. -export function decodeTokens(tokens: string): SemanticHighlightingToken[] { - const scopeMask = 0xFFFF; - const lenShift = 0x10; - const uint32Size = 4; - const buf = Buffer.from(tokens, 'base64'); - const retTokens = []; - for (let i = 0, end = buf.length / uint32Size; i < end; i += 2) { - const start = buf.readUInt32BE(i * uint32Size); - const lenKind = buf.readUInt32BE((i + 1) * uint32Size); - const scopeIndex = lenKind & scopeMask; - const len = lenKind >>> lenShift; - retTokens.push({character : start, scopeIndex : scopeIndex, length : len}); - } - - return retTokens; -} - -// The main class responsible for processing of highlightings that clangd -// sends. -export class Highlighter { - // Maps uris with currently open TextDocuments to the current highlightings. - private files: Map> = new Map(); - // DecorationTypes for the current theme that are used when highlighting. A - // SemanticHighlightingToken with scopeIndex i should have the decoration at - // index i in this list. - private decorationTypes: vscode.TextEditorDecorationType[] = []; - // The clangd TextMate scope lookup table. - private scopeLookupTable: string[][]; - constructor(scopeLookupTable: string[][]) { - this.scopeLookupTable = scopeLookupTable; - } - public dispose() { - this.files.clear(); - this.decorationTypes.forEach((t) => t.dispose()); - // Dispose must not be not called multiple times if initialize is - // called again. - this.decorationTypes = []; - } - // This function must be called at least once or no highlightings will be - // done. Sets the theme that is used when highlighting. Also triggers a - // recolorization for all current highlighters. Should be called whenever the - // theme changes and has been loaded. Should also be called when the first - // theme is loaded. - public initialize(themeRuleMatcher: ThemeRuleMatcher) { - this.decorationTypes.forEach((t) => t.dispose()); - this.decorationTypes = this.scopeLookupTable.map((scopes) => { - const options: vscode.DecorationRenderOptions = { - // If there exists no rule for this scope the matcher returns an empty - // color. That's ok because vscode does not do anything when applying - // empty decorations. - color : themeRuleMatcher.getBestThemeRule(scopes[0]).foreground, - // If the rangeBehavior is set to Open in any direction the - // highlighting becomes weird in certain cases. - rangeBehavior : vscode.DecorationRangeBehavior.ClosedClosed, - }; - return vscode.window.createTextEditorDecorationType(options); - }); - this.getVisibleTextEditorUris().forEach((fileUri) => - this.applyHighlights(fileUri)); - } - - // Adds incremental highlightings to the current highlightings for the file - // with fileUri. Also applies the highlightings to any associated - // TextEditor(s). - public highlight(fileUri: vscode.Uri, - highlightingLines: SemanticHighlightingLine[]) { - const fileUriStr = fileUri.toString(); - if (!this.files.has(fileUriStr)) { - this.files.set(fileUriStr, new Map()); - } - const fileHighlightings = this.files.get(fileUriStr); - highlightingLines.forEach((line) => fileHighlightings.set(line.line, line)); - this.applyHighlights(fileUri); - } - - // Applies all the highlightings currently stored for a file with fileUri. - public applyHighlights(fileUri: vscode.Uri) { - const fileUriStr = fileUri.toString(); - if (!this.files.has(fileUriStr)) - // There are no highlightings for this file, must return early or will get - // out of bounds when applying the decorations below. - return; - if (!this.decorationTypes.length) - // Can't apply any decorations when there is no theme loaded. - return; - // This must always do a full re-highlighting due to the fact that - // TextEditorDecorationType are very expensive to create (which makes - // incremental updates infeasible). For this reason one - // TextEditorDecorationType is used per scope. - const ranges = this.getDecorationRanges(fileUri); - vscode.window.visibleTextEditors.forEach((e) => { - if (e.document.uri.toString() !== fileUriStr) - return; - this.decorationTypes.forEach((d, i) => e.setDecorations(d, ranges[i])); - }); - } - - // Called when a text document is closed. Removes any highlighting entries for - // the text document that was closed. - public removeFileHighlightings(fileUri: vscode.Uri) { - // If there exists no entry the call to delete just returns false. - this.files.delete(fileUri.toString()); - } - - // Gets the uris as strings for the currently visible text editors. - protected getVisibleTextEditorUris(): vscode.Uri[] { - return vscode.window.visibleTextEditors.map((e) => e.document.uri); - } - - // Returns the ranges that should be used when decorating. Index i in the - // range array has the decoration type at index i of this.decorationTypes. - protected getDecorationRanges(fileUri: vscode.Uri): vscode.Range[][] { - const fileUriStr = fileUri.toString(); - if (!this.files.has(fileUriStr)) - // this.files should always have an entry for fileUri if we are here. But - // if there isn't one we don't want to crash the extension. This is also - // useful for tests. - return []; - const lines: SemanticHighlightingLine[] = - Array.from(this.files.get(fileUriStr).values()); - const decorations: vscode.Range[][] = this.decorationTypes.map(() => []); - lines.forEach((line) => { - line.tokens.forEach((token) => { - decorations[token.scopeIndex].push(new vscode.Range( - new vscode.Position(line.line, token.character), - new vscode.Position(line.line, token.character + token.length))); - }); - }); - return decorations; - } -} - -// A rule for how to color TextMate scopes. -interface TokenColorRule { - // A TextMate scope that specifies the context of the token, e.g. - // "entity.name.function.cpp". - scope: string; - // foreground is the color tokens of this scope should have. - foreground: string; -} - -export class ThemeRuleMatcher { - // The rules for the theme. - private themeRules: TokenColorRule[]; - // A cache for the getBestThemeRule function. - private bestRuleCache: Map = new Map(); - constructor(rules: TokenColorRule[]) { this.themeRules = rules; } - // Returns the best rule for a scope. - getBestThemeRule(scope: string): TokenColorRule { - if (this.bestRuleCache.has(scope)) - return this.bestRuleCache.get(scope); - let bestRule: TokenColorRule = {scope : '', foreground : ''}; - this.themeRules.forEach((rule) => { - // The best rule for a scope is the rule that is the longest prefix of the - // scope (unless a perfect match exists in which case the perfect match is - // the best). If a rule is not a prefix and we tried to match with longest - // common prefix instead variables would be highlighted as `less` - // variables when using Light+ (as variable.other would be matched against - // variable.other.less in this case). Doing common prefix matching also - // means we could match variable.cpp to variable.css if variable.css - // occurs before variable in themeRules. - // FIXME: This is not defined in the TextMate standard (it is explicitly - // undefined, https://macromates.com/manual/en/scope_selectors). Might - // want to rank some other way. - if (scope.startsWith(rule.scope) && - rule.scope.length > bestRule.scope.length) - // This rule matches and is more specific than the old rule. - bestRule = rule; - }); - this.bestRuleCache.set(scope, bestRule); - return bestRule; - } -} - -// Get all token color rules provided by the theme. -function loadTheme(themeName: string): Promise { - const extension = - vscode.extensions.all.find((extension: vscode.Extension) => { - const contribs = extension.packageJSON.contributes; - if (!contribs || !contribs.themes) - return false; - return contribs.themes.some((theme: any) => theme.id === themeName || - theme.label === themeName); - }); - - if (!extension) { - return Promise.reject('Could not find a theme with name: ' + themeName); - } - - const themeInfo = extension.packageJSON.contributes.themes.find( - (theme: any) => theme.id === themeName || theme.label === themeName); - return parseThemeFile(path.join(extension.extensionPath, themeInfo.path)); -} - -/** - * Parse the TextMate theme at fullPath. If there are multiple TextMate scopes - * of the same name in the include chain only the earliest entry of the scope is - * saved. - * @param fullPath The absolute path to the theme. - * @param seenScopes A set containing the name of the scopes that have already - * been set. - */ -export async function parseThemeFile( - fullPath: string, seenScopes?: Set): Promise { - if (!seenScopes) - seenScopes = new Set(); - // FIXME: Add support for themes written as .tmTheme. - if (path.extname(fullPath) === '.tmTheme') - return []; - try { - const contents = await readFileText(fullPath); - const parsed = jsonc.parse(contents); - const rules: TokenColorRule[] = []; - // To make sure it does not crash if tokenColors is undefined. - if (!parsed.tokenColors) - parsed.tokenColors = []; - parsed.tokenColors.forEach((rule: any) => { - if (!rule.scope || !rule.settings || !rule.settings.foreground) - return; - const textColor = rule.settings.foreground; - // Scopes that were found further up the TextMate chain should not be - // overwritten. - const addColor = (scope: string) => { - if (seenScopes.has(scope)) - return; - rules.push({scope, foreground : textColor}); - seenScopes.add(scope); - }; - if (rule.scope instanceof Array) { - return rule.scope.forEach((s: string) => addColor(s)); - } - addColor(rule.scope); - }); - - if (parsed.include) - // Get all includes and merge into a flat list of parsed json. - return [ - ...(await parseThemeFile( - path.join(path.dirname(fullPath), parsed.include), seenScopes)), - ...rules - ]; - return rules; - } catch (err) { - // If there is an error opening a file, the TextMate files that were - // correctly found and parsed further up the chain should be returned. - // Otherwise there will be no highlightings at all. - console.warn('Could not open file: ' + fullPath + ', error: ', err); - } - - return []; -} - -function readFileText(path: string): Promise { - return new Promise((resolve, reject) => { - fs.readFile(path, 'utf8', (err, data) => { - if (err) { - return reject(err); - } - return resolve(data); - }); - }); -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc b/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/includeTheme.jsonc +++ /dev/null @@ -1,28 +0,0 @@ -{ - // Some comment - "include": "simpleTheme.jsonc", - "name": "TestTheme", - "type": "dark", - "colors": { - "dropdown.background": "#fff" - }, - "tokenColors": [ - { - "settings": { - "foreground": "#fff" - } - }, - { - "scope": "a", - "settings": { - "foreground": "#fff" - } - }, - { - "scope": ["a", "b"], - "settings": { - "foreground": "#000" - } - } - ] -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc b/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/assets/simpleTheme.jsonc +++ /dev/null @@ -1,17 +0,0 @@ -{ - // Some comment - "tokenColors": [ - { - "scope": "a", - "settings": { - "foreground": "#ff0000" - } - }, - { - "scope": "c", - "settings": { - "foreground": "#bcd" - } - } - ] -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/extension.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** The module 'assert' provides assertion methods from node */ -import * as assert from 'assert'; - -import * as vscode from 'vscode'; -import * as myExtension from '../src/extension'; - -// TODO: add tests -suite("Extension Tests", () => { - // Defines a Mocha unit test - test("Something 1", () => { - assert.equal(-1, [ 1, 2, 3 ].indexOf(5)); - assert.equal(-1, [ 1, 2, 3 ].indexOf(0)); - }); -}); \ No newline at end of file diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as glob from 'glob'; -import * as Mocha from 'mocha'; -import * as path from 'path'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ui : 'tdd'}); - mocha.useColors(true); - - const testsRoot = path.resolve(__dirname, '..'); - - return new Promise((c, e) => { - glob('**/**.test.js', {cwd : testsRoot}, (err, files) => { - if (err) { - return e(err); - } - - // Add files to the test suite - files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - e(err); - } - }); - }); -} diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/runTest.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/runTest.ts deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/runTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as path from 'path'; - -import {runTests} from 'vscode-test'; - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../'); - - // The path to the extension test script - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './index'); - - // Download VS Code, unzip it and run the integration test - await runTests({extensionDevelopmentPath, extensionTestsPath}); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -main(); diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts b/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; - -import * as semanticHighlighting from '../src/semantic-highlighting'; - -suite('SemanticHighlighting Tests', () => { - test('Parses arrays of textmate themes.', async () => { - const themePath = - path.join(__dirname, '../../test/assets/includeTheme.jsonc'); - const scopeColorRules = - await semanticHighlighting.parseThemeFile(themePath); - const getScopeRule = (scope: string) => - scopeColorRules.find((v) => v.scope === scope); - assert.equal(scopeColorRules.length, 3); - assert.deepEqual(getScopeRule('a'), {scope : 'a', foreground : '#fff'}); - assert.deepEqual(getScopeRule('b'), {scope : 'b', foreground : '#000'}); - assert.deepEqual(getScopeRule('c'), {scope : 'c', foreground : '#bcd'}); - }); - test('Decodes tokens correctly', () => { - const testCases: string[] = [ - 'AAAAAAABAAA=', 'AAAAAAADAAkAAAAEAAEAAA==', - 'AAAAAAADAAkAAAAEAAEAAAAAAAoAAQAA' - ]; - const expected = [ - [ {character : 0, scopeIndex : 0, length : 1} ], - [ - {character : 0, scopeIndex : 9, length : 3}, - {character : 4, scopeIndex : 0, length : 1} - ], - [ - {character : 0, scopeIndex : 9, length : 3}, - {character : 4, scopeIndex : 0, length : 1}, - {character : 10, scopeIndex : 0, length : 1} - ] - ]; - testCases.forEach( - (testCase, i) => assert.deepEqual( - semanticHighlighting.decodeTokens(testCase), expected[i])); - }); - test('ScopeRules overrides for more specific themes', () => { - const rules = [ - {scope : 'variable.other.css', foreground : '1'}, - {scope : 'variable.other', foreground : '2'}, - {scope : 'storage', foreground : '3'}, - {scope : 'storage.static', foreground : '4'}, - {scope : 'storage', foreground : '5'}, - {scope : 'variable.other.parameter', foreground : '6'}, - ]; - const tm = new semanticHighlighting.ThemeRuleMatcher(rules); - assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope, - 'variable.other'); - assert.deepEqual(tm.getBestThemeRule('storage.static').scope, - 'storage.static'); - assert.deepEqual( - tm.getBestThemeRule('storage'), - rules[2]); // Match the first element if there are duplicates. - assert.deepEqual(tm.getBestThemeRule('variable.other.parameter').scope, - 'variable.other.parameter'); - assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope, - 'variable.other.parameter'); - }); - test('Colorizer groups decorations correctly', async () => { - const scopeTable = [ - [ 'variable' ], [ 'entity.type.function' ], - [ 'entity.type.function.method' ] - ]; - // Create the scope source ranges the highlightings should be highlighted - // at. Assumes the scopes used are the ones in the "scopeTable" variable. - const createHighlightingScopeRanges = - (highlightingLines: - semanticHighlighting.SemanticHighlightingLine[]) => { - // Initialize the scope ranges list to the correct size. Otherwise - // scopes that don't have any highlightings are missed. - let scopeRanges: vscode.Range[][] = scopeTable.map(() => []); - highlightingLines.forEach((line) => { - line.tokens.forEach((token) => { - scopeRanges[token.scopeIndex].push(new vscode.Range( - new vscode.Position(line.line, token.character), - new vscode.Position(line.line, - token.character + token.length))); - }); - }); - return scopeRanges; - }; - - const fileUri1 = vscode.Uri.parse('file:///file1'); - const fileUri2 = vscode.Uri.parse('file:///file2'); - const fileUri1Str = fileUri1.toString(); - const fileUri2Str = fileUri2.toString(); - - class MockHighlighter extends semanticHighlighting.Highlighter { - applicationUriHistory: string[] = []; - // Override to make the highlighting calls accessible to the test. Also - // makes the test not depend on visible text editors. - applyHighlights(fileUri: vscode.Uri) { - this.applicationUriHistory.push(fileUri.toString()); - } - // Override to make it accessible from the test. - getDecorationRanges(fileUri: vscode.Uri) { - return super.getDecorationRanges(fileUri); - } - // Override to make tests not depend on visible text editors. - getVisibleTextEditorUris() { return [ fileUri1, fileUri2 ]; } - } - const highlighter = new MockHighlighter(scopeTable); - const tm = new semanticHighlighting.ThemeRuleMatcher([ - {scope : 'variable', foreground : '1'}, - {scope : 'entity.type', foreground : '2'}, - ]); - // Recolorizes when initialized. - highlighter.highlight(fileUri1, []); - assert.deepEqual(highlighter.applicationUriHistory, [ fileUri1Str ]); - highlighter.initialize(tm); - assert.deepEqual(highlighter.applicationUriHistory, - [ fileUri1Str, fileUri1Str, fileUri2Str ]); - // Groups decorations into the scopes used. - let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [ - { - line : 1, - tokens : [ - {character : 1, length : 2, scopeIndex : 1}, - {character : 10, length : 2, scopeIndex : 2}, - ] - }, - { - line : 2, - tokens : [ - {character : 3, length : 2, scopeIndex : 1}, - {character : 6, length : 2, scopeIndex : 1}, - {character : 8, length : 2, scopeIndex : 2}, - ] - }, - ]; - - highlighter.highlight(fileUri1, highlightingsInLine); - assert.deepEqual(highlighter.applicationUriHistory, - [ fileUri1Str, fileUri1Str, fileUri2Str, fileUri1Str ]); - assert.deepEqual(highlighter.getDecorationRanges(fileUri1), - createHighlightingScopeRanges(highlightingsInLine)); - // Keeps state separate between files. - const highlightingsInLine1: - semanticHighlighting.SemanticHighlightingLine = { - line : 1, - tokens : [ - {character : 2, length : 1, scopeIndex : 0}, - ] - }; - highlighter.highlight(fileUri2, [ highlightingsInLine1 ]); - assert.deepEqual( - highlighter.applicationUriHistory, - [ fileUri1Str, fileUri1Str, fileUri2Str, fileUri1Str, fileUri2Str ]); - assert.deepEqual(highlighter.getDecorationRanges(fileUri2), - createHighlightingScopeRanges([ highlightingsInLine1 ])); - // Does full colorizations. - highlighter.highlight(fileUri1, [ highlightingsInLine1 ]); - assert.deepEqual(highlighter.applicationUriHistory, [ - fileUri1Str, fileUri1Str, fileUri2Str, fileUri1Str, fileUri2Str, - fileUri1Str - ]); - // After the incremental update to line 1, the old highlightings at line 1 - // will no longer exist in the array. - assert.deepEqual( - highlighter.getDecorationRanges(fileUri1), - createHighlightingScopeRanges( - [ highlightingsInLine1, ...highlightingsInLine.slice(1) ])); - // Closing a text document removes all highlightings for the file and no - // other files. - highlighter.removeFileHighlightings(fileUri1); - assert.deepEqual(highlighter.getDecorationRanges(fileUri1), []); - assert.deepEqual(highlighter.getDecorationRanges(fileUri2), - createHighlightingScopeRanges([ highlightingsInLine1 ])); - }); -}); diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json b/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json deleted file mode 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6", - "es2015.core", - "es2015.collection", - "es2015.generator", - "es2015.iterable", - "es2015.promise", - "es2015.symbol", - "es2016.array.include" - ], - "sourceMap": true, - "rootDir": ".", - "alwaysStrict": true, - "noEmitOnError": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "noImplicitThis": true - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] -}