+++ /dev/null
-out
-node_modules
-.vscode-test
+++ /dev/null
-// 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"
- }
- ]
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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"
-}
+++ /dev/null
-.vscode/**
-.vscode-test/**
-out/test/**
-test/**
-src/**
-**/*.map
-.gitignore
-tsconfig.json
-vsc-extension-quickstart.md
+++ /dev/null
-# 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 <F5>.
-```
-
-# 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
-```
+++ /dev/null
-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.
+++ /dev/null
-# 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 `<F2>`, 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.
+++ /dev/null
-{
- "name": "vscode-clangd",
- "version": "0.0.21",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "@types/events": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
- "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
- "dev": true
- },
- "@types/glob": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
- "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
- "dev": true,
- "requires": {
- "@types/events": "*",
- "@types/minimatch": "*",
- "@types/node": "*"
- }
- },
- "@types/minimatch": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
- "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
- "dev": true
- },
- "@types/mocha": {
- "version": "2.2.48",
- "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz",
- "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==",
- "dev": true
- },
- "@types/node": {
- "version": "6.14.9",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.9.tgz",
- "integrity": "sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w==",
- "dev": true
- },
- "@types/vscode": {
- "version": "1.41.0",
- "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.41.0.tgz",
- "integrity": "sha512-7SfeY5u9jgiELwxyLB3z7l6l/GbN9CqpCQGkcRlB7tKRFBxzbz2PoBfGrLxI1vRfUCIq5+hg5vtDHExwq5j3+A==",
- "dev": true
- },
- "agent-base": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
- "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
- "dev": true,
- "requires": {
- "es6-promisify": "^5.0.0"
- }
- },
- "async": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
- "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
- "dev": true
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "clang-format": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.2.4.tgz",
- "integrity": "sha512-sw+nrGUp3hvmANd1qF8vZPuezSYQAiXgGBiEtkXTtJnnu6b00fCqkkDIsnRKrNgg4nv6NYZE92ejvOMIXZoejw==",
- "dev": true,
- "requires": {
- "async": "^1.5.2",
- "glob": "^7.0.0",
- "resolve": "^1.1.6"
- }
- },
- "commander": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
- "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
- },
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
- "dev": true
- },
- "es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
- "dev": true
- },
- "es6-promisify": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
- "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
- "dev": true,
- "requires": {
- "es6-promise": "^4.0.3"
- }
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "growl": {
- "version": "1.10.5",
- "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
- "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
- "dev": true
- },
- "he": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
- "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
- "dev": true
- },
- "http-proxy-agent": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
- "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
- "dev": true,
- "requires": {
- "agent-base": "4",
- "debug": "3.1.0"
- }
- },
- "https-proxy-agent": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
- "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
- "dev": true,
- "requires": {
- "agent-base": "^4.3.0",
- "debug": "^3.1.0"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
- },
- "jsonc-parser": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.0.tgz",
- "integrity": "sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA=="
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
- "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
- "dev": true
- },
- "mkdirp": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
- "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
- "dev": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "mocha": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
- "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
- "dev": true,
- "requires": {
- "browser-stdout": "1.3.1",
- "commander": "2.15.1",
- "debug": "3.1.0",
- "diff": "3.5.0",
- "escape-string-regexp": "1.0.5",
- "glob": "7.1.2",
- "growl": "1.10.5",
- "he": "1.1.1",
- "minimatch": "3.0.4",
- "mkdirp": "0.5.1",
- "supports-color": "5.4.0"
- },
- "dependencies": {
- "browser-stdout": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
- "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
- "dev": true
- },
- "glob": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- }
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
- },
- "path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
- "dev": true
- },
- "resolve": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
- "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
- "dev": true,
- "requires": {
- "path-parse": "^1.0.6"
- }
- },
- "rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- },
- "dependencies": {
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- }
- }
- },
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
- },
- "supports-color": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
- "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- },
- "dependencies": {
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- }
- }
- },
- "typescript": {
- "version": "3.7.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz",
- "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==",
- "dev": true
- },
- "vscode-jsonrpc": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz",
- "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
- },
- "vscode-languageclient": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.0.tgz",
- "integrity": "sha512-Tcp0VoOaa0YzxL4nEfK9tsmcy76Eo8jNLvFQZwh2c8oMm02luL8uGYPLQNAiZ3XGgegfcwiQFZMqbW7DNV0vxA==",
- "requires": {
- "semver": "^6.3.0",
- "vscode-languageserver-protocol": "^3.15.2"
- }
- },
- "vscode-languageserver": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.0.tgz",
- "integrity": "sha512-Q5kUJegYclTZMnKUaEcxJK41Ozp6qJhhoFJYj0w8y8j9JXdKT479LE945QCKRvSgWfsqTSUmgsozVTUIwQQxHw==",
- "requires": {
- "vscode-languageserver-protocol": "^3.15.2"
- }
- },
- "vscode-languageserver-protocol": {
- "version": "3.15.2",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.2.tgz",
- "integrity": "sha512-GdL05JKOgZ76RDg3suiGCl9enESM7iQgGw4x93ibTh4sldvZmakHmTeZ4iUApPPGKf6O3OVBtrsksBXnHYaxNg==",
- "requires": {
- "vscode-jsonrpc": "^5.0.1",
- "vscode-languageserver-types": "3.15.1"
- }
- },
- "vscode-languageserver-types": {
- "version": "3.15.1",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz",
- "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ=="
- },
- "vscode-test": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.3.0.tgz",
- "integrity": "sha512-LddukcBiSU2FVTDr3c1D8lwkiOvwlJdDL2hqVbn6gIz+rpTqUCkMZSKYm94Y1v0WXlHSDQBsXyY+tchWQgGVsw==",
- "dev": true,
- "requires": {
- "http-proxy-agent": "^2.1.0",
- "https-proxy-agent": "^2.2.4",
- "rimraf": "^2.6.3"
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
- }
- }
-}
+++ /dev/null
-{
- "name": "vscode-clangd",
- "displayName": "vscode-clangd",
- "description": "Clang Language Server",
- "version": "0.0.22",
- "publisher": "llvm-vs-code-extensions",
- "homepage": "https://clangd.llvm.org/",
- "icon": "icon.png",
- "engines": {
- "vscode": "^1.41.0"
- },
- "categories": [
- "Programming Languages",
- "Linters",
- "Snippets"
- ],
- "keywords": [
- "C",
- "C++",
- "LSP",
- "Clangd",
- "LLVM"
- ],
- "activationEvents": [
- "onLanguage:c",
- "onLanguage:cpp",
- "onLanguage:cuda",
- "onLanguage:objective-c",
- "onLanguage:objective-cpp",
- "onCommand:clangd-vscode.activate"
- ],
- "main": "./out/src/extension",
- "scripts": {
- "vscode:prepublish": "tsc -p ./",
- "compile": "tsc -watch -p ./",
- "format": "clang-format --style=LLVM -i --glob=\"{src,test}/*.ts\"",
- "test": "tsc -p ./ && node ./out/test/runTest.js",
- "package": "vsce package --baseImagesUrl https://raw.githubusercontent.com/llvm/llvm-project/master/clang-tools-extra/clangd/clients/clangd-vscode/",
- "publish": "vsce publish --baseImagesUrl https://raw.githubusercontent.com/llvm/llvm-project/master/clang-tools-extra/clangd/clients/clangd-vscode/"
- },
- "dependencies": {
- "jsonc-parser": "^2.1.0",
- "vscode-languageclient": "^6.1.0",
- "vscode-languageserver": "^6.1.0",
- "vscode-languageserver-types": "^3.15.1"
- },
- "devDependencies": {
- "@types/glob": "^7.1.1",
- "@types/mocha": "^2.2.32",
- "@types/node": "^6.0.40",
- "@types/vscode": "^1.41.0",
- "glob": "^7.1.4",
- "clang-format": "1.2.4",
- "mocha": "^5.2.0",
- "typescript": "^3.5.1",
- "vscode-test": "^1.3.0"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/llvm/llvm-project.git",
- "directory": "clang-tools/extra/clangd/clients/clangd-vscode"
- },
- "contributes": {
- "languages": [
- {
- "id": "cpp",
- "filenamePatterns": [
- "**/include/c++/**",
- "**/MSVC/*/include/**"
- ],
- "firstLine": "^/[/*].*-\\*-\\s*C\\+\\+\\s*-\\*-.*"
- },
- {
- "id": "cuda",
- "extensions": [
- ".cu",
- ".cuh"
- ]
- }
- ],
- "configuration": {
- "type": "object",
- "title": "clangd configuration",
- "properties": {
- "clangd.path": {
- "type": "string",
- "default": "clangd",
- "description": "The path to clangd executable, e.g.: /usr/bin/clangd"
- },
- "clangd.arguments": {
- "type": "array",
- "default": [],
- "items": {
- "type": "string"
- },
- "description": "Arguments for clangd server"
- },
- "clangd.syncFileEvents": {
- "type": "boolean",
- "default": true,
- "description": "Whether or not to send file events to clangd (File created, changed or deleted). This can be disabled for performance consideration."
- },
- "clangd.trace": {
- "type": "string",
- "description": "Names a file that clangd should log a performance trace to, in chrome trace-viewer JSON format."
- },
- "clangd.semanticHighlighting": {
- "type": "boolean",
- "default": "true",
- "description": "Enable semantic highlighting in clangd"
- }
- }
- },
- "commands": [
- {
- "command": "clangd-vscode.switchheadersource",
- "title": "Switch between Source/Header"
- },
- {
- "command": "clangd-vscode.activate",
- "title": "Manually activate clangd extension"
- }
- ],
- "keybindings": [
- {
- "command": "clangd-vscode.switchheadersource",
- "key": "Alt+o",
- "mac": "Alt+cmd+o",
- "when": "editorTextFocus"
- }
- ]
- }
-}
+++ /dev/null
-import * as vscode from 'vscode';
-import * as vscodelc from 'vscode-languageclient';
-import * as semanticHighlighting from './semantic-highlighting';
-
-/**
- * Get an option from workspace configuration.
- * @param option name of the option (e.g. for clangd.path should be path)
- * @param defaultValue default value to return if option is not set
- */
-function getConfig<T>(option: string, defaultValue?: any): T {
- const config = vscode.workspace.getConfiguration('clangd');
- return config.get<T>(option, defaultValue);
-}
-
-namespace SwitchSourceHeaderRequest {
-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);
-
- 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<boolean>('syncFileEvents', true);
-
- const clangd: vscodelc.Executable = {
- 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 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<boolean>('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 () => {}));
-}
+++ /dev/null
-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<SemanticHighlightingParams, void>(
- '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<string>('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<string, Map<number, SemanticHighlightingLine>> = 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<string, TokenColorRule> = 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<TokenColorRule[]> {
- const extension =
- vscode.extensions.all.find((extension: vscode.Extension<any>) => {
- 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<string>): Promise<TokenColorRule[]> {
- 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<string> {
- return new Promise((resolve, reject) => {
- fs.readFile(path, 'utf8', (err, data) => {
- if (err) {
- return reject(err);
- }
- return resolve(data);
- });
- });
-}
+++ /dev/null
-{
- // 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"
- }
- }
- ]
-}
+++ /dev/null
-{
- // Some comment
- "tokenColors": [
- {
- "scope": "a",
- "settings": {
- "foreground": "#ff0000"
- }
- },
- {
- "scope": "c",
- "settings": {
- "foreground": "#bcd"
- }
- }
- ]
-}
+++ /dev/null
-/** 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
+++ /dev/null
-import * as glob from 'glob';
-import * as Mocha from 'mocha';
-import * as path from 'path';
-
-export function run(): Promise<void> {
- // 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);
- }
- });
- });
-}
+++ /dev/null
-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();
+++ /dev/null
-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 ]));
- });
-});
+++ /dev/null
-{
- "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"
- ]
-}