Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ed087134c | ||
|
|
902355e021 | ||
|
|
32e98912df | ||
|
|
6bc49d595e | ||
|
|
6b3c0f1b10 | ||
|
|
35501431f8 | ||
|
|
27a3c9958d | ||
|
|
5b3d4ebf44 | ||
|
|
cfc064efcd | ||
|
|
4f7a64a1a2 | ||
|
|
c84cb36004 | ||
|
|
0502351002 | ||
|
|
5de420ee70 | ||
|
|
6a73275924 | ||
|
|
d12591062e | ||
|
|
3926110b33 | ||
|
|
f5975e6534 | ||
|
|
b55e2c7ac5 | ||
|
|
73fda38d71 | ||
|
|
9211292b60 | ||
|
|
f63a8da581 | ||
|
|
fd314b1b04 | ||
|
|
ea52c76595 | ||
|
|
7659e2826b | ||
|
|
8e898151f6 | ||
|
|
b2b0ad37af | ||
|
|
cee6ebe1d9 | ||
|
|
566e657fad | ||
|
|
db1f631396 | ||
|
|
426c08293d | ||
|
|
631a4452d0 | ||
|
|
9b29698b0e | ||
|
|
b5c94e9e1f | ||
|
|
384cd35d6b | ||
|
|
2d4df9149f | ||
|
|
d3c2ccbb93 | ||
|
|
c637221b92 | ||
|
|
814f01b263 | ||
|
|
b763aa57d3 | ||
|
|
54b1e69975 | ||
|
|
dacfe08033 | ||
|
|
f5aa7dc33e | ||
|
|
90c6e9876a | ||
|
|
9fa950db6a | ||
|
|
8ea627e085 | ||
|
|
536d38e3bf | ||
|
|
c10c626869 | ||
|
|
24d37bc233 | ||
|
|
158719cf46 | ||
|
|
b6327ed6c3 | ||
|
|
c60a2c6752 | ||
|
|
1f7c27d7f9 | ||
|
|
1d82458a3a | ||
|
|
25d122c3f7 | ||
|
|
627acc535e | ||
|
|
515d858b4d | ||
|
|
7ec15af47c | ||
|
|
cac58e9f88 | ||
|
|
0c28725628 | ||
|
|
084a8e708c | ||
|
|
045d50bb90 | ||
|
|
68eda19665 | ||
|
|
ae564c8428 | ||
|
|
5241ce28e0 | ||
|
|
febb880e32 | ||
|
|
d1c344b944 | ||
|
|
a19d1c325e | ||
|
|
82225338c4 | ||
|
|
fa72ab582d | ||
|
|
0b3e43c93f | ||
|
|
8b332a7795 | ||
|
|
39ab866a10 | ||
|
|
d4cdfe6994 | ||
|
|
4e20f27127 | ||
|
|
4e2f1b8ba5 | ||
|
|
0cffa4e27a | ||
|
|
b67e701fc9 | ||
|
|
77f3747630 | ||
|
|
dc8813f449 | ||
|
|
e0543a64c1 | ||
|
|
e5b118c707 | ||
|
|
f465766d1e | ||
|
|
7f4fc339c7 | ||
|
|
788cee3ecf | ||
|
|
05939c19a9 | ||
|
|
110e683790 | ||
|
|
6a88c9917b | ||
|
|
2ac33971ed | ||
|
|
a5905276ce | ||
|
|
d6726e5d42 | ||
|
|
aa6873b84e | ||
|
|
e3ddec66ee | ||
|
|
26d83d136e | ||
|
|
6f4439ca88 | ||
|
|
3fbeba779c | ||
|
|
cfc908a1ac | ||
|
|
f3a02fde4e | ||
|
|
e863e88e95 | ||
|
|
bc70ea8c79 | ||
|
|
bbfea25a1d | ||
|
|
968d6c5919 | ||
|
|
33d23b3a5e | ||
|
|
4bf3691f7f | ||
|
|
bf9d69a8ad | ||
|
|
9a78289fec | ||
|
|
7960904575 | ||
|
|
dd590ea1f5 | ||
|
|
5d1e503480 | ||
|
|
3b15f515d1 | ||
|
|
d7a3384a07 | ||
|
|
4cdcd72990 | ||
|
|
740705973e | ||
|
|
3a78e96785 | ||
|
|
39b89bdb5b | ||
|
|
d4d68cb808 | ||
|
|
d3e8958b29 | ||
|
|
0e3fea978a | ||
|
|
a39b1a5d6c | ||
|
|
f15994a58c | ||
|
|
009c77d45f | ||
|
|
94e213449f | ||
|
|
7ae6818bfb | ||
|
|
03a6c04629 | ||
|
|
8526bc90cb | ||
|
|
105760833d | ||
|
|
239e4015d6 | ||
|
|
7e7b38acd7 | ||
|
|
260dc5d840 | ||
|
|
99b290513b | ||
|
|
76b3d9ca28 | ||
|
|
806dc8ac43 | ||
|
|
03cf4d7aaf | ||
|
|
569a7cb53d | ||
|
|
6de2250fef | ||
|
|
ae861b3605 | ||
|
|
2aeadbd395 | ||
|
|
0b500cefb7 | ||
|
|
2e8cd7f406 | ||
|
|
8c8c2c22e3 | ||
|
|
bdc8322da3 | ||
|
|
eeb2ba207c | ||
|
|
f848bf392a | ||
|
|
f72a3ded96 | ||
|
|
31b993941b | ||
|
|
59b0b3f924 | ||
|
|
5b90fc6bd3 | ||
|
|
a4e9df0e6e | ||
|
|
3ef0b7597f | ||
|
|
74c9b0b967 | ||
|
|
3b5a8466d7 | ||
|
|
fbf8ed4e35 | ||
|
|
c978eb0755 | ||
|
|
0f67f54b42 | ||
|
|
b770030ec2 | ||
|
|
8129ce337e | ||
|
|
93a88c948a | ||
|
|
34d8874754 | ||
|
|
0773ec8c41 | ||
|
|
9f842ac0d9 | ||
|
|
e8d0ded816 | ||
|
|
f5bdac9889 | ||
|
|
eb976d5ca5 | ||
|
|
d5a902e144 | ||
|
|
b0c2d54144 | ||
|
|
bcdabc9c36 | ||
|
|
e054287c48 | ||
|
|
dcf480990b | ||
|
|
02a3152f0f | ||
|
|
77806f657f | ||
|
|
7e5f22f862 | ||
|
|
0f8e7b2d7b | ||
|
|
088276b4af | ||
|
|
a7cefc9d4d | ||
|
|
30d8a1daa4 | ||
|
|
148ae1d325 | ||
|
|
968ce8acba | ||
|
|
ff6e13e829 | ||
|
|
c18592b5a3 | ||
|
|
fee924b374 | ||
|
|
6724e13c63 | ||
|
|
798e90574c | ||
|
|
1eb064e020 | ||
|
|
717de54b06 | ||
|
|
51cd214f1e | ||
|
|
4ca9ad8b3a | ||
|
|
8aadd40a58 | ||
|
|
7088f546aa | ||
|
|
64ca48b50e | ||
|
|
0c61ee96b7 | ||
|
|
e020801dac | ||
|
|
270a4f7d38 | ||
|
|
342de46452 | ||
|
|
cd0dde9e27 | ||
|
|
79f8262d26 | ||
|
|
24b69c7873 | ||
|
|
260124b39b | ||
|
|
2426a66be4 | ||
|
|
6f5c9e362b | ||
|
|
868799af10 | ||
|
|
01d013723f | ||
|
|
1a8e84bca3 | ||
|
|
3db3c8da9a | ||
|
|
670a105c1f | ||
|
|
5445eff250 | ||
|
|
95dd5386ed | ||
|
|
55120359a4 | ||
|
|
bb2d23c694 | ||
|
|
15ac01d70c | ||
|
|
0c77b9e6cf | ||
|
|
c39579010b | ||
|
|
e928bfb0a9 | ||
|
|
1d47bc4160 | ||
|
|
3d7937feeb | ||
|
|
98260f96ea | ||
|
|
8d96465cb6 | ||
|
|
ece90711fb | ||
|
|
361ca45b50 | ||
|
|
28e8f1f2ed | ||
|
|
d27e609d92 | ||
|
|
fdcbfee87c | ||
|
|
bda5bbf89c | ||
|
|
50ddd670c7 | ||
|
|
cc81b4bb8f | ||
|
|
a0f6eb61ad | ||
|
|
10a06af93d | ||
|
|
b28ab0a874 | ||
|
|
f1ca548849 | ||
|
|
f860223723 | ||
|
|
e2aaababc4 | ||
|
|
49aa55261f | ||
|
|
035d0284d9 | ||
|
|
f216e0262a | ||
|
|
373e9be4cb | ||
|
|
7a20270b10 | ||
|
|
41a4e14e4c | ||
|
|
13b78f2129 | ||
|
|
bf6b4aa54e | ||
|
|
f978719dea | ||
|
|
2713e70563 | ||
|
|
af516b9515 | ||
|
|
243f21380d | ||
|
|
6fc9f7b682 |
@@ -34,6 +34,6 @@ about: 'Issues pertaining to IntelliSense, autocomplete, code editing, etc. '
|
||||
|
||||
**Additional context**
|
||||
<!--
|
||||
*Call Stacks: For bugs like crashes, deadlocks, infinite loops, etc. that we are not able to repro and for which the call stack may be useful, please attach a debugger and/or create a dmp and provide the call stacks. Starting with 0.17.3, Windows binaries have symbols available in VS Code by setting your "symbolSearchPath" to "http://msdl.microsoft.com/download/symbols".*
|
||||
Add any other context about the problem here including log messages in your Output window ("C_Cpp.loggingLevel": "Debug" in settings.json).
|
||||
* Call Stacks: For bugs like crashes, deadlocks, infinite loops, etc. that we are not able to repro and for which the call stack may be useful, please attach a debugger and/or create a dmp and provide the call stacks. Windows binaries have symbols available in VS Code by setting your "symbolSearchPath" to "https://msdl.microsoft.com/download/symbols".
|
||||
* Add any other context about the problem here including log messages in your Output window ("C_Cpp.loggingLevel": "Debug" in settings.json).
|
||||
-->
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# ignore cache files for sample projects
|
||||
.vscode/ipch
|
||||
browse*.db*
|
||||
*.obj
|
||||
*.pdb
|
||||
*.exe
|
||||
*.ilk
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- "8"
|
||||
|
||||
before_install:
|
||||
# Do not modify. Required for GUI based tests: See https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
|
||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then
|
||||
export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
|
||||
sh -e /etc/init.d/xvfb start;
|
||||
sleep 3;
|
||||
fi
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main'
|
||||
key_url: 'https://packages.microsoft.com/keys/microsoft.asc'
|
||||
packages:
|
||||
- gdb
|
||||
- g++-4.9
|
||||
|
||||
|
||||
script:
|
||||
# Download debugAdapters from an existing extension version. See TravisCI settings to set CPPTOOL_VERSION
|
||||
- mkdir -p ~/.vscode/extensions/ms-vscode.cpptools-$CPPTOOL_VERSION
|
||||
- wget https://github.com/Microsoft/vscode-cpptools/releases/download/$CPPTOOL_VERSION/cpptools.vsix -O ~/cpptools.vsix
|
||||
- unzip ~/cpptools.vsix "extension/debugAdapters/*" -d ~/.
|
||||
- mv ~/extension/debugAdapters ~/.vscode/extensions/ms-vscode.cpptools-$CPPTOOL_VERSION/debugAdapters
|
||||
# Build and then run tests
|
||||
- cd Extension
|
||||
- npm install
|
||||
- npm run compile
|
||||
- npm run tslint
|
||||
# pr-check needs to run before test. test modifies package.json.
|
||||
- npm run pr-check
|
||||
- npm run unitTests
|
||||
# TODO: Merge tests into one group due to Gulp 4.0
|
||||
- npm run integrationTests
|
||||
# Dump integrationTest.log output
|
||||
- find ~ -name "integrationTests.log" -type f -exec cat {} \;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef BOX_H
|
||||
#define BOX_H
|
||||
|
||||
/**
|
||||
* Definition of a box object with three dimensions.
|
||||
*/
|
||||
struct box
|
||||
{
|
||||
int length;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int volume()
|
||||
{
|
||||
return length * width * height;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
# Box Sample
|
||||
This sample is a simple C++ program that computes and outputs the volume of a box.
|
||||
|
||||
We use this example in our blog posts to illustrate new extension features.
|
||||
|
||||
## Build and Debug Active File
|
||||
Available as of March 2019, "Build and Debug Active File" automatically configures the build tasks and kicks off a build and debug session. There are
|
||||
three ways to get started with this feature.
|
||||
|
||||
### Command
|
||||
While editing a file in your workspace folder, you can open the command palette and select the `C/C++: Build and Debug Active File` command.
|
||||
This option will generate a tasks.json file for you, build your active source file, and then launch the debugger.
|
||||
|
||||

|
||||
|
||||
### Context Menu
|
||||
While editing a file in a workspace folder, you can right click in the editor field and select the "Build and Debug Active File" context menu option.
|
||||
This option will generate a tasks.json file for you, build your active source file, and then launch the debugger.
|
||||
|
||||

|
||||
|
||||
### F5
|
||||
Another way to begin building and debugging your active file is to execute the command by pressing <kbd>F5</kbd>. This method will configure
|
||||
both a tasks.json and launch.json file for you, build your active source file, and then launch the debugger.
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <iostream>
|
||||
#include "Objects/box.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Calculate and print the volume of a box.
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
box package{ 10, 10, 10 };
|
||||
cout << "Package length: " << package.length << endl;
|
||||
cout << "Package width: " << package.width << endl;
|
||||
cout << "Package height: " << package.height << endl;
|
||||
cout << "Package volume: " << package.volume() << endl;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -1,2 +0,0 @@
|
||||
main.exe
|
||||
main.exe.dSYM
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(lldb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/main.exe", // this is executable to launch the debugger with
|
||||
"args": ["YourNameHere"],
|
||||
"stopAtEntry": true, // if true then stop at the main entry (function)
|
||||
"cwd": "${workspaceRoot}",
|
||||
"environment": [],
|
||||
"externalConsole": true,
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "clang++",
|
||||
"command": "clang++ --debug -o main.exe main.cpp",
|
||||
// "--debug" enables debugging symbols
|
||||
// "-o main.exe" specifies the output executable
|
||||
// "main.cpp" is the source file to compile
|
||||
"type": "shell",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
# README
|
||||
This is a sample debuggable C++ project. It uses the vendor provided version of clang installed. `tasks.json` and `launch.json` have been edited to demonstrate how to create a configuration for a C++ project that builds with clang.
|
||||
|
||||
There's a sample build task in `.vscode/tasks.json`; you can also see the build configurations by using the menu option `Configure` -> `Configure Tasks` or by clicking the gear icon in the Debug Panel.
|
||||
|
||||
To run a build, use the menu option `Tasks` -> `Run Build Task...`.
|
||||
|
||||
There's a sample debug configuration in `.vscode/launch.json`; you can also see the configuration by using the menu option `Debug` -> `Open Configurations`.
|
||||
|
||||
To debug the build, use the menu option `Debug` -> `Start Debugging`. The executable will launch and stop in the main function.
|
||||
@@ -1,17 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void greet(const string& person) {
|
||||
cout << "Hello, " << person << "!" << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if(argc >= 2) {
|
||||
greet(argv[1]);
|
||||
} else {
|
||||
cerr << "insufficient args, usage: " << argv[0] << " personNameHere" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
These steps will allow you to debug the TypeScript code that is part of the Microsoft CppTools extension for Visual Studio Code.
|
||||
|
||||
Prerequisite steps:
|
||||
* Clone [this](https://github.com/Microsoft/vscode-cpptools) repository.
|
||||
* Clone the release branch of [this](https://github.com/Microsoft/vscode-cpptools) repository.
|
||||
* git clone -b release https://github.com/Microsoft/vscode-cpptools
|
||||
* Install [npm](https://nodejs.org).
|
||||
* From a command line, run the following commands from the **Extension** folder in the root of the repository:
|
||||
* `npm install` will install the dependencies needed to build the extension.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
## Table of Contents
|
||||
* Setup: [Debugging Setup](#debugging-setup)
|
||||
* Setup: [What is the .vscode/ipch folder?](#what-is-the-vscodeipch-folder)
|
||||
* Setup: [How do I disable the IntelliSense cache (ipch)?](#how-do-i-disable-the-intellisense-cache-ipch)
|
||||
* Debugger: [Why is debugging not working?](#why-is-debugging-not-working)
|
||||
* Build: [How to enable debug symbols](#how-to-enable-debug-symbols)
|
||||
* Logging: [How to enable logging](#how-to-enable-logging)
|
||||
@@ -15,6 +17,24 @@ The file **launch.json** will now be open for editing with a new configuration.
|
||||
|
||||
See the [**Documentation/Debugger**](https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation/Debugger) folder in this repository for more in-depth documentation on how to configure the debugger.
|
||||
|
||||
## What is the .vscode/ipch folder?
|
||||
|
||||
The language server caches information about included header files to improve the performance of IntelliSense. When you edit C/C++ files in your workspace folder, the language server will store cache files in the `.vscode/ipch` folder by default. VS Code per-workspace storage folders were not selected for the following reasons:
|
||||
* The workspace storage location provided by VS Code is somewhat obscure and we had reservations about writing GB's worth of files in this location where users may not see them or know where to find them.
|
||||
* Parity with Visual Studio. This is how Visual Studio works and they receive little to no feedback/complaints on the location.
|
||||
|
||||
With this in mind we knew that we wouldn't be able to please everyone, so we provided settings to allow you to customize this the way that works best for your situation. We also figured that putting the files in the workspace folder would bring the issue to your attention quickly so that you can take action if you don't like the default behavior.
|
||||
|
||||
#### `"C_Cpp.intelliSenseCachePath": <string>`
|
||||
This setting allows you to set workspace or global overrides for the cache path. For example, if you want to share a single cache location for all workspace folders, you just open the VS Code settings, and add a "User" setting for "IntelliSense Cache Path".
|
||||
|
||||
#### `"C_Cpp.intelliSenseCacheSize": <number>`
|
||||
This setting allows you to set a limit on the amount of caching the extension does. This is an approximation, but the extension will make a best effort to keep the cache size as close to the limit you set as possible. If you are sharing the cache location across workspaces as explained above, you can still increase/decrease the limit, but you should make sure that you add a "User" setting for "IntelliSense Cache Size".
|
||||
|
||||
## How do I disable the IntelliSense cache (ipch)?
|
||||
|
||||
If you do not want to use the IntelliSense caching feature to improve the performance of IntelliSense, you can disable the feature by setting the "IntelliSense Cache Size" setting to 0. (or `"C_Cpp.intelliSenseCacheSize": 0"` in the JSON settings editor)
|
||||
|
||||
## Why is debugging not working?
|
||||
|
||||
### My breakpoints aren't being hit
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Frequently asked questions
|
||||
|
||||
* [Why are my files corrupted on format?](#why-are-my-files-corrupted-on-format)
|
||||
* [How do I get IntelliSense to work correctly?](#how-do-i-get-intellisense-to-work-correctly)
|
||||
* [Why do I see red squiggles under Standard Library types?](#why-do-i-see-red-squiggles-under-standard-library-types)
|
||||
* [How do I get the new IntelliSense to work with MinGW on Windows?](#how-do-i-get-the-new-intellisense-to-work-with-mingw-on-windows)
|
||||
@@ -7,6 +8,10 @@
|
||||
* [What is the difference between `"includePath"` and `"browse.path"` in **c_cpp_properties.json**?](#what-is-the-difference-between-includepath-and-browsepath-in-c_cpp_propertiesjson)
|
||||
* [How do I re-create the IntelliSense database?](#how-do-i-re-create-the-intellisense-database)
|
||||
|
||||
## Why are my files corrupted on format?
|
||||
|
||||
This is likely due to the fact that you either have a multi-root workspace where one folder is a child of the other, or you are using symlinks to open your file. Reduce the folders in the workspace to one and remove the symlink. This should fix your problem.
|
||||
|
||||
## How do I get IntelliSense to work correctly?
|
||||
|
||||
There are two IntelliSense engines present in the extension: the "fuzzy" engine (or Tag Parser), and the new "Default" engine. If you are using version 0.11.0 or higher of the cpptools extension, then you can preview our new IntelliSense engine which has more accurate auto-complete suggestions and tooltips. To use the new engine, you need to ensure that `"C_Cpp.intelliSenseEngine"` is set to `"Default"` in your settings. Since the engine is still in preview it is not on by default for everyone yet.
|
||||
@@ -31,7 +36,7 @@ If you want IntelliSense to operate on your files even when all #include directi
|
||||
The most common reason for this is missing include paths and defines. The easiest way to fix this on each platform is as follows:
|
||||
|
||||
**Linux/Mac**
|
||||
* Set `"intelliSenseMode": "clang-x64"` and `"compilerPath"` in **c_cpp_properties.json** to the path to your compiler.
|
||||
* Set `"intelliSenseMode": "clang-x64"` or `"intelliSenseMode": "gcc-x64"` and `"compilerPath"` in **c_cpp_properties.json** to the path to your compiler.
|
||||
|
||||
**Windows**
|
||||
* If you are using a Microsoft compiler from Visual Studio, set `"intelliSenseMode": "msvc-x64"`, but don't add the `"compilerPath"` property to **c_cpp_properties.json**.
|
||||
|
||||
@@ -0,0 +1,511 @@
|
||||
|
||||
# VS Code C/C++ Extension - Enhanced Colorization
|
||||
|
||||
The VS Code C/C++ extension now supports semantic colorization, when IntelliSense is enabled. Enhanced colorization can be enabled using the enhancedColorization setting:
|
||||
|
||||
```
|
||||
"C_Cpp.enhancedColorization": "Enabled"
|
||||
```
|
||||
|
||||
# Theming
|
||||
|
||||
Colors can be associated using the existing support for theming and color customization in VS Code. Documentation on Theming in VS Code can be found [here](https://code.visualstudio.com/docs/getstarted/themes)
|
||||
|
||||
Colors are associated with [TextMate scopes](https://macromates.com/manual/en/language_grammars#naming_conventions).
|
||||
|
||||
|
||||
# IntelliSense Tokens and Scopes
|
||||
|
||||
|
||||
| Token | Scope |
|
||||
| ------------- |:-------------:|
|
||||
| Class Template | entity.name.class.template |
|
||||
| Enumerator | variable.other.enummember |
|
||||
| Event (C++/CLI) | variable.other.event |
|
||||
| Function | entity.name.function |
|
||||
| Function Template | entity.name.function.template |
|
||||
| Generic Type (C++/CLI) | entity.name.class.generic |
|
||||
| Global Variable | variable.other.global |
|
||||
| Label | entity.name.label |
|
||||
| Local Variable | variable.other.local |
|
||||
| Macro | entity.name.function.preprocessor |
|
||||
| Member Field | variable.other.member |
|
||||
| Member Function | entity.name.function.member |
|
||||
| Member Operator | keyword.operator.member |
|
||||
| Namespace | entity.name.type.namespace |
|
||||
| New / Delete | keyword.operator.new |
|
||||
| Operator Function | entity.name.function.operator |
|
||||
| Parameter | variable.parameter |
|
||||
| Property (C++/CLI) | variable.other.property |
|
||||
| Reference Type (C++/CLI) | entity.name.class.reference |
|
||||
| Static Member Field | variable.other.member.static |
|
||||
| Static Member Function | entity.name.function.member.static |
|
||||
| Type | entity.name.type |
|
||||
| User-Defined Literal - Number | entity.name.user-defined-literal.number |
|
||||
| User-Defined Literal - Raw | entity.name.user-defined-literal |
|
||||
| User-Defined Literal - String | entity.name.user-defined-literal.string |
|
||||
| Value Type (C++/CLI) | entity.name.class.value |
|
||||
|
||||
Many of the tokens recognized by IntelliSense do not directly map to existing scopes in the VS Code's default C/C++ TextMate grammar, so are likely not colored by existing VS Code themes.
|
||||
|
||||
# Customizing Colors in Settings
|
||||
|
||||
Colors can also be overridden globally, in settings:
|
||||
```
|
||||
"editor.tokenColorCustomizations": {
|
||||
"textMateRules": [
|
||||
{
|
||||
"scope": "entity.name.type",
|
||||
"settings": {
|
||||
"foreground": "#FF0000",
|
||||
"fontStyle": "italic bold underline"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Or, overridden on a per-theme basis:
|
||||
```
|
||||
"editor.tokenColorCustomizations": {
|
||||
"[Visual Studio Dark]": {
|
||||
"textMateRules": [
|
||||
{
|
||||
"scope": "entity.name.type",
|
||||
"settings": {
|
||||
"foreground": "#FF0000",
|
||||
"fontStyle": "italic bold underline"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Use the following to augment the Visual Studio Dark theme to match what Visual Studio would display for C++ files.
|
||||
|
||||
```
|
||||
"editor.tokenColorCustomizations": {
|
||||
"[Visual Studio Dark]": {
|
||||
"textMateRules": [
|
||||
{
|
||||
"scope": "comment",
|
||||
"settings": {
|
||||
"foreground": "#57A64A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control",
|
||||
"settings": {
|
||||
"foreground": "#569CD6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.directive",
|
||||
"settings": {
|
||||
"foreground": "#9B9B9B"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.operator",
|
||||
"settings": {
|
||||
"foreground": "#B4B4B4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.numeric",
|
||||
"settings": {
|
||||
"foreground": "#B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "string.quoted",
|
||||
"settings": {
|
||||
"foreground": "#D69D85"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "comment.xml.doc",
|
||||
"settings": {
|
||||
"foreground": "#57A64A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "comment.xml.doc.tag",
|
||||
"settings": {
|
||||
"foreground": "#57A64A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.preprocessor",
|
||||
"settings": {
|
||||
"foreground": "#BD63C5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.enummember",
|
||||
"settings": {
|
||||
"foreground": "#B8D7A3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.global",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.local",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.parameter",
|
||||
"settings": {
|
||||
"foreground": "#7F7F7F"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.type",
|
||||
"settings": {
|
||||
"foreground": "#4EC9B0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.reference",
|
||||
"settings": {
|
||||
"foreground": "#4EC9B0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.value",
|
||||
"settings": {
|
||||
"foreground": "#4EC9B0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.member",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.member",
|
||||
"settings": {
|
||||
"foreground": "#DADADA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.member.static",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.member.static",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.event",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.template",
|
||||
"settings": {
|
||||
"foreground": "#4EC9B0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.generic",
|
||||
"settings": {
|
||||
"foreground": "#4EC9B0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.template",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.type.namespace",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.label",
|
||||
"settings": {
|
||||
"foreground": "#C8C8C8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.user-defined-literal",
|
||||
"settings": {
|
||||
"foreground": "#DADADA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.user-defined-literal.string",
|
||||
"settings": {
|
||||
"foreground": "#D69D85"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.user-defined-literal.number",
|
||||
"settings": {
|
||||
"foreground": "#B5CEA8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.operator",
|
||||
"settings": {
|
||||
"foreground": "#B4B4B4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.operator.member",
|
||||
"settings": {
|
||||
"foreground": "#B4B4B4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.operator.new",
|
||||
"settings": {
|
||||
"foreground": "#569CD6"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use the following to augment the Visual Studio Light theme to match what Visual Studio would display for C++ files.
|
||||
|
||||
````
|
||||
"editor.tokenColorCustomizations": {
|
||||
"[Visual Studio Light]": {
|
||||
"textMateRules": [
|
||||
{
|
||||
"scope": "comment",
|
||||
"settings": {
|
||||
"foreground": "#008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control",
|
||||
"settings": {
|
||||
"foreground": "#0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.directive",
|
||||
"settings": {
|
||||
"foreground": "#808080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.operator",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "constant.numeric",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "string.quoted",
|
||||
"settings": {
|
||||
"foreground": "#A31515"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "comment.xml.doc",
|
||||
"settings": {
|
||||
"foreground": "#006400"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "comment.xml.doc.tag",
|
||||
"settings": {
|
||||
"foreground": "#A9A9A9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.preprocessor",
|
||||
"settings": {
|
||||
"foreground": "#6F0026"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.enummember",
|
||||
"settings": {
|
||||
"foreground": "#2F4F4F"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.global",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.local",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.parameter",
|
||||
"settings": {
|
||||
"foreground": "#808080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.type",
|
||||
"settings": {
|
||||
"foreground": "#2B91AF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.reference",
|
||||
"settings": {
|
||||
"foreground": "#2B91AF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.value",
|
||||
"settings": {
|
||||
"foreground": "#2B91AF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.member",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.member",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.member.static",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.member.static",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "variable.other.event",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.template",
|
||||
"settings": {
|
||||
"foreground": "#2B91AF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.class.generic",
|
||||
"settings": {
|
||||
"foreground": "#2B91AF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.template",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.type.namespace",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.label",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.user-defined-literal",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.user-defined-literal.string",
|
||||
"settings": {
|
||||
"foreground": "#A31515"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.user-defined-literal.number",
|
||||
"settings": {
|
||||
"foreground": "#000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.operator",
|
||||
"settings": {
|
||||
"foreground": "#008080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.operator.member",
|
||||
"settings": {
|
||||
"foreground": "#008080"
|
||||
}
|
||||
},
|
||||
{
|
||||
"scope": "keyword.operator.new",
|
||||
"settings": {
|
||||
"foreground": "#0000FF"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
````
|
||||
@@ -3,6 +3,7 @@ node_modules
|
||||
|
||||
# ignore compliled typescript
|
||||
out
|
||||
dist
|
||||
|
||||
# ignore downloaded extension files and folders
|
||||
server
|
||||
@@ -18,4 +19,3 @@ install.lock
|
||||
|
||||
# ignore vscode test
|
||||
.vscode-test/
|
||||
browse*db*
|
||||
Vendored
+5
-4
@@ -13,9 +13,9 @@
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "TypeScript Compile",
|
||||
"preLaunchTask": "Compile Dev",
|
||||
},
|
||||
{
|
||||
"name": "Launch Tests",
|
||||
@@ -47,13 +47,14 @@
|
||||
"args": [
|
||||
"${workspaceFolder}/test/integrationTests/testAssets/SimpleCppProject",
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests"
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests/languageServer"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/test/**/*.js"
|
||||
]
|
||||
],
|
||||
"preLaunchTask": "Pretest"
|
||||
},
|
||||
]
|
||||
}
|
||||
Vendored
+27
@@ -53,6 +53,33 @@
|
||||
"dependsOn": [
|
||||
"TypeScript Compile"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Compile Dev",
|
||||
"group": "build",
|
||||
"isBackground": false,
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"compileDev"
|
||||
],
|
||||
"problemMatcher": "$tsc-watch"
|
||||
},
|
||||
{
|
||||
"label": "Pretest",
|
||||
"group": "build",
|
||||
"isBackground": false,
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"pretest"
|
||||
],
|
||||
"dependsOn": [
|
||||
"TypeScript Compile"
|
||||
],
|
||||
"problemMatcher": "$tsc-watch"
|
||||
}
|
||||
]
|
||||
}
|
||||
+30
-9
@@ -1,15 +1,36 @@
|
||||
obj/**
|
||||
|
||||
# ignore vscode settings for extension development
|
||||
.vscode/**
|
||||
typings/**
|
||||
out/test/**
|
||||
|
||||
# ignore binaries
|
||||
obj/**
|
||||
|
||||
# ignore source files
|
||||
tools/**
|
||||
notices/**
|
||||
test/**
|
||||
src/**
|
||||
**/*.map
|
||||
.gitignore
|
||||
|
||||
# ignore .js files that are webpacked or only used for development
|
||||
out/src/**
|
||||
out/tools/**
|
||||
|
||||
# ignore ts files in ui
|
||||
ui/*.ts
|
||||
|
||||
# ignore Azure-Pipelines files
|
||||
jobs/**
|
||||
|
||||
# ignore development files
|
||||
tsconfig.json
|
||||
test.tsconfig.json
|
||||
tslint.json
|
||||
webpack.config.js
|
||||
tscCompileList.txt
|
||||
gulpfile.js
|
||||
.gitattributes
|
||||
.gitignore
|
||||
CMakeLists.txt
|
||||
debugAdapters/install.lock*
|
||||
out/src/Debugger/copyScript.js
|
||||
tools/**
|
||||
out/tools/**
|
||||
notices/**
|
||||
typings/**
|
||||
**/*.map
|
||||
+149
-1
@@ -1,6 +1,154 @@
|
||||
# C/C++ for Visual Studio Code Change Log
|
||||
|
||||
## Version 0.21.0 January 23, 2019
|
||||
## Version 0.24.0: July 3, 2019
|
||||
### New Features
|
||||
* Semantic colorization [Documentation](https://github.com/microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/colorization.md) [#230](https://github.com/microsoft/vscode-cpptools/issues/230)
|
||||
* Add `Rescan Workspace` command. [microsoft/vscode-cpptools-api#11](https://github.com/microsoft/vscode-cpptools-api/issues/11)
|
||||
|
||||
### Enhancements
|
||||
* Configuration UI editor improvements:
|
||||
* Add list of detected compiler paths. [PR #3708](https://github.com/microsoft/vscode-cpptools/pull/3708)
|
||||
* Enable selecting/editing of other configurations and add "Advanced Settings" section. [PR #3732](https://github.com/microsoft/vscode-cpptools/pull/3732)
|
||||
* Enable `envFile` for `cppdbg`. [PR #3723](https://github.com/microsoft/vscode-cpptools/pull/3723)
|
||||
* Change the default path value of `C_Cpp.intelliSenseCachePath`. [#3347](https://github.com/microsoft/vscode-cpptools/issues/3347) [#3664](https://github.com/microsoft/vscode-cpptools/issues/3664)
|
||||
* Change `C_Cpp.clang_format_path` to `machine` scope. [#3774](https://github.com/microsoft/vscode-cpptools/issues/3774)
|
||||
* Add validation to the advanced configuration UI settings. [PR #3838](https://github.com/microsoft/vscode-cpptools/pull/3838)
|
||||
* Add `Current Configuration` to `C/C++: Log Diagnostics`. [PR #3866](https://github.com/microsoft/vscode-cpptools/pull/3866)
|
||||
|
||||
### Bug Fixes
|
||||
* Fix for gdb `follow-fork-mode` `child` not working. [#2738](https://github.com/microsoft/vscode-cpptools/issues/2738)
|
||||
* Fix IntelliSense process crash on hover with certain arrays. [#3081](https://github.com/Microsoft/vscode-cpptools/issues/3081)
|
||||
* Fix IntelliSense-based `Go to Definition` for goto labels. [#3111](https://github.com/microsoft/vscode-cpptools/issues/3111)
|
||||
* Fix IntelliSense behaving incorrectly when files are opened with different casing on Windows. [#3229](https://github.com/microsoft/vscode-cpptools/issues/3229)
|
||||
* Fix user defined literals crashing IntelliSense in clang/gcc mode. [#3481](https://github.com/microsoft/vscode-cpptools/issues/3481)
|
||||
* Improve `sourceFileMap` to be more dynamic. [#3504](https://github.com/microsoft/vscode-cpptools/issues/3504)
|
||||
* Fix IntelliSense-based hover document comments being shown for invalid declarations not used by the current translation unit. [#3596](https://github.com/microsoft/vscode-cpptools/issues/3596)
|
||||
* Fix `Go to Definition` when is `void` missing in the parameter list of a function definition a .c file. [#3609](https://github.com/microsoft/vscode-cpptools/issues/3609)
|
||||
* Fix configuration validation of compiler path and IntelliSense mode compatibility for `clang-cl.exe` compiler. [#3637](https://github.com/microsoft/vscode-cpptools/issues/3637)
|
||||
* Fix resolving `${workspaceFolderBasename}` and add `${workspaceStorage}`. [#3642](https://github.com/microsoft/vscode-cpptools/issues/3642)
|
||||
* Fix IntelliSense-based `Go to Definition` performance issue due to extra database iteration. [#3655](https://github.com/microsoft/vscode-cpptools/issues/3655)
|
||||
* Fix `SourceRequest` causing debugging to stop with `NotImplementedException`. [#3662](https://github.com/microsoft/vscode-cpptools/issues/3662)
|
||||
* Fix typo in `intelliSenseMode` description.
|
||||
* Karsten Thoms (@kthoms) [PR #3682](https://github.com/microsoft/vscode-cpptools/pull/3682)
|
||||
* Fix invalid warning with typedef enums in .c files. [#3685](https://github.com/microsoft/vscode-cpptools/issues/3685)
|
||||
* Fix incorrect `keyword` completion occurring for pragma `#keyword`. [#3690](https://github.com/microsoft/vscode-cpptools/issues/3690)
|
||||
* Fix problem matcher to show fatal errors from GCC [#3712](https://github.com/microsoft/vscode-cpptools/issues/3712)
|
||||
* Fix multi-root folders with the same name sharing the same browse database. [PR #3715](https://github.com/microsoft/vscode-cpptools/pull/3715)
|
||||
* Fix `remoteProcessPicker` on Windows. [#3758](https://github.com/microsoft/vscode-cpptools/issues/3758)
|
||||
* Fix crash when tag parsing Objective-C code. [#3776](https://github.com/microsoft/vscode-cpptools/issues/3776)
|
||||
* Fix duplicate slashes getting added to `c_cpp_properties.json`. [PR #3778](https://github.com/microsoft/vscode-cpptools/pull/3778)
|
||||
* Fix `envFile` variable substitution. [#3836](https://github.com/microsoft/vscode-cpptools/issues/3836)
|
||||
* Fix missing headers popup. [PR #3840](https://github.com/microsoft/vscode-cpptools/pull/3840)
|
||||
* Fix multiple anonymous unions not showing correctly in Locals while debugging. [MIEngine#820](https://github.com/microsoft/MIEngine/issues/820)
|
||||
* Fix pause not working when using `DebugServer`/`MIDebuggerServerAddress` on Linux and macOS. [MIEngine#844](https://github.com/microsoft/MIEngine/issues/844)
|
||||
* Improvements to CPU and memory usage when editing.
|
||||
|
||||
## Version 0.23.1: May 13, 2019
|
||||
### Bug Fixes
|
||||
* Fix `launch.json` creation when `intelliSenseEngine` is `"Disabled"`. [#3583](https://github.com/microsoft/vscode-cpptools/issues/3583)
|
||||
* Fix C/C++ commands not working if the language service isn't activated. [#3615](https://github.com/microsoft/vscode-cpptools/issues/3615)
|
||||
* Fix missing extension `"Details"` page. [#3621](https://github.com/microsoft/vscode-cpptools/issues/3621)
|
||||
* Fix some random crashes related to IntelliSense inactive region processing.
|
||||
|
||||
## Version 0.23.0: May 6, 2019
|
||||
### New Features
|
||||
* Add a configuration UI editor to edit IntelliSense settings defined in the underlying `c_cpp_properties.json` file. [PR #3479](https://github.com/Microsoft/vscode-cpptools/pull/3479), [PR #3487](https://github.com/Microsoft/vscode-cpptools/pull/3487), [PR #3519](https://github.com/Microsoft/vscode-cpptools/pull/3519), [#3524](https://github.com/Microsoft/vscode-cpptools/issues/3524), [PR #3563](https://github.com/Microsoft/vscode-cpptools/pull/3563), [#3526](https://github.com/Microsoft/vscode-cpptools/issues/3526)
|
||||
* Add a new command `C/C++: Edit configurations (UI)` to open the UI editor.
|
||||
* Replace the `C/C++: Edit configurations...` command with `C/C++: Edit configurations (JSON)` to open `c_cpp_properties.json`.
|
||||
* The default whether to open the UI editor or JSON file is based on the `workbench.settings.editor` setting.
|
||||
* Add command `C/C++: Log Diagnostics` to log language service diagnostics. [PR #3489](https://github.com/Microsoft/vscode-cpptools/pull/3489)
|
||||
* Add support for `.env` files for `cppvsdbg`. [#3490](https://github.com/Microsoft/vscode-cpptools/issues/3490)
|
||||
|
||||
### Other Changes
|
||||
* Enable flag `/permissive-` as an argument to `compilerPath` with `cl.exe`. [#1589](https://github.com/Microsoft/vscode-cpptools/issues/1589), [#3446](https://github.com/Microsoft/vscode-cpptools/issues/3446)
|
||||
* Configuration squiggles for `c_cpp_properties.json` now validates if the setting values of `compilerPath` and `intelliSenseMode` match on Windows. [#2983](https://github.com/Microsoft/vscode-cpptools/issues/2983)
|
||||
* Enable `-fms-extensions` to be used as an argument to `compilerPath` on Linux/Mac. [#3063](https://github.com/Microsoft/vscode-cpptools/issues/3063)
|
||||
* Change the default value of `C_Cpp.intelliSenseEngineFallback` setting to `Disabled`. [#3165](https://github.com/Microsoft/vscode-cpptools/issues/3165)
|
||||
* Add squiggle when `compilerPath` uses spaces and arguments without `"`. [#3357](https://github.com/Microsoft/vscode-cpptools/issues/3357)
|
||||
* Change the `Disabled` value for `C_Cpp.errorSquiggles` to stop showing missing header squiggles. [#3361](https://github.com/Microsoft/vscode-cpptools/issues/3361)
|
||||
* Add `enableConfigurationSquiggles` setting to allow squiggles to be disabled for `c_cpp_properties.json`. [#3403](https://github.com/Microsoft/vscode-cpptools/issues/3403)
|
||||
* Switch to using the `installExtension` command for offline/insider vsix installing (to reduce install failures). [#3408](https://github.com/Microsoft/vscode-cpptools/issues/3408)
|
||||
* Add a better example to the description of `C_Cpp.clang_format_style` and `C_Cpp.clang_format_fallback_style`. [#3419](https://github.com/Microsoft/vscode-cpptools/issues/3419)
|
||||
* Add a new (default) value of `EnabledIfIncludesResolve` to `C_Cpp.errorSquiggles`, which only shows error squiggles if include headers are successfully resolved. [PR #3421](https://github.com/Microsoft/vscode-cpptools/pull/3421)
|
||||
* Disable debug heap by default with cppvsdbg. [#3484](https://github.com/Microsoft/vscode-cpptools/issues/3484)
|
||||
* Reported by Djoulihen (@Djoulihen)
|
||||
* Enable configuration squiggles for paths delimited by semicolons. [PR #3517](https://github.com/Microsoft/vscode-cpptools/pull/3517)
|
||||
* Don't show release notes if the extension has never been installed before. [#3533](https://github.com/Microsoft/vscode-cpptools/issues/3533)
|
||||
* Remove IntelliSense fallback code actions.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix browsing for functions with BOOST_FOREACH. [#953](https://github.com/Microsoft/vscode-cpptools/issues/953)
|
||||
* Fix code action sometimes not appearing over a squiggled identifier. [#1436](https://github.com/microsoft/vscode-cpptools/issues/1436)
|
||||
* Work around issue with VS Code not treating `.C` files as C++ files [Microsoft/vscode#59369](https://github.com/Microsoft/vscode/issues/59369) -- `.C` files become associated by name in `files.associations`. [#2558](https://github.com/Microsoft/vscode-cpptools/issues/2558)
|
||||
* Fix various IntelliSense parsing bugs. [#2824](https://github.com/Microsoft/vscode-cpptools/issues/2824), [#3110](https://github.com/Microsoft/vscode-cpptools/issues/3110), [#3168](https://github.com/Microsoft/vscode-cpptools/issues/3168)
|
||||
* Preserve newlines in documentation comments. [#2937](https://github.com/Microsoft/vscode-cpptools/issues/2937)
|
||||
* Fix documentation comments above multi-line templates (and some other issues). [#3162](https://github.com/Microsoft/vscode-cpptools/issues/3162)
|
||||
* Fix "Extension causes high cpu load" due to module loading. [#3213](https://github.com/Microsoft/vscode-cpptools/issues/3213)
|
||||
* Fix auto-removal of compiler-provided paths in `includePath` when they end with a directory separator on Windows. [#3245](https://github.com/Microsoft/vscode-cpptools/issues/3245)
|
||||
* Fix duplicate compiler build tasks appearing when `compilerPath` has arguments. [PR #3360](https://github.com/Microsoft/vscode-cpptools/pull/3360)
|
||||
* Fix environment variables not resolving with `C_Cpp.intelliSenseCachePath`. [#3367](https://github.com/Microsoft/vscode-cpptools/issues/3367)
|
||||
* Fix the formatting of snippets text. [#3376](https://github.com/Microsoft/vscode-cpptools/issues/3376)
|
||||
* Fix the default `AccessModifierOffset` used when formatting. [#3376](https://github.com/Microsoft/vscode-cpptools/issues/3376)
|
||||
* Fix null reference during initialization when using custom configuration providers. [PR #3377](https://github.com/Microsoft/vscode-cpptools/pull/3377)
|
||||
* Fix symbol parsing when `__MINGW_ATTRIB_*` is used. [#3390](https://github.com/Microsoft/vscode-cpptools/issues/3390)
|
||||
* Fix `compile_commands.json` configuration prompt being disabled per user instead of per folder. [PR #3399](https://github.com/Microsoft/vscode-cpptools/pull/3399)
|
||||
* Fix `.cmd` and `.bat` files not working for `compilerPath` on Windows. [#3428](https://github.com/Microsoft/vscode-cpptools/issues/3428)
|
||||
* Fix `compilerPath` with arguments that are surrounded by quotes. [#3428](https://github.com/Microsoft/vscode-cpptools/issues/3428)
|
||||
* Fix documentation comments interpreting special characters as markdown. [#3441](https://github.com/Microsoft/vscode-cpptools/issues/3441)
|
||||
* Fix hover using the configuration of the active document instead of the hovered document. [#3452](https://github.com/Microsoft/vscode-cpptools/issues/3452)
|
||||
* Fix `c_cpp_properties.json` squiggles when the configuration name has regex characters. [PR #3478](https://github.com/Microsoft/vscode-cpptools/pull/3478)
|
||||
* Use the `editor.tabSize` setting instead of `2` when creating build tasks. [PR #3486](https://github.com/Microsoft/vscode-cpptools/pull/3486)
|
||||
* Fix some potential crashes on hover. [#3509](https://github.com/Microsoft/vscode-cpptools/issues/3509)
|
||||
* Fix for `NullReferenceException` occurring when `"args"` is not specified in `launch.json`. [#3532](https://github.com/Microsoft/vscode-cpptools/issues/3532)
|
||||
* Fix `Go to Definition` giving no results when IntelliSense doesn't find the symbol. [#3549](https://github.com/Microsoft/vscode-cpptools/issues/3549)
|
||||
* Fix configuration squiggles with trailing backslashes. [PR #3573](https://github.com/Microsoft/vscode-cpptools/pull/3573)
|
||||
* Fix `includePath` code actions, configuration prompts, and the `C/C++: Change configuration provider...` command. [PR #3576](https://github.com/Microsoft/vscode-cpptools/pull/3576)
|
||||
* Fix randomly occurring crash (that could occur when opening files while IntelliSense squiggles are pending).
|
||||
* Fix crash on hover (that could occur when document comments have blank lines).
|
||||
* Fix icon of parameters in completion results.
|
||||
|
||||
## Version 0.22.1: March 21, 2019
|
||||
* Fix `tasks.json` with single-line comments being overwritten when `Build and Debug Active File` is used. [#3327](https://github.com/Microsoft/vscode-cpptools/issues/3327)
|
||||
* Fix an invalid `compilerPath` property getting added to `tasks.json` after doing `Configure Task` with a C/C++ compiler.
|
||||
* Add IntelliSense caching for macOS 10.13 or later (0.22.0 only supported Windows and Linux).
|
||||
|
||||
## Version 0.22.0: March 19, 2019
|
||||
### Major Changes
|
||||
* Add warning squiggles for invalid properties and paths in `c_cpp_properties.json`. [#2799](https://github.com/Microsoft/vscode-cpptools/issues/2799), [PR #3283](https://github.com/Microsoft/vscode-cpptools/pull/3283)
|
||||
* Add C/C++ compiler build tasks for compiling the active source file, with support for `F5` debugging and the `Build and Debug Active File` context menu command. [PR #3118](https://github.com/Microsoft/vscode-cpptools/pull/3118), [PR #3244](https://github.com/Microsoft/vscode-cpptools/pull/3244)
|
||||
* Add AutoPCH support to reduce IntelliSense parsing time, with `C_Cpp.intelliSenseCachePath` and `C_Cpp.intelliSenseCacheSize` settings. It isn't enabled for Mac yet. [PR #3184](https://github.com/Microsoft/vscode-cpptools/pull/3184)
|
||||
|
||||
### Minor Changes
|
||||
* Fix IntelliSense not working on Windows when the username has a space in it and file `C:\Users\<firstname>` exists. [#1377](https://github.com/Microsoft/vscode-cpptools/issues/1377), [#2114](https://github.com/Microsoft/vscode-cpptools/issues/2114), [#2176](https://github.com/Microsoft/vscode-cpptools/issues/2176), [#3052](https://github.com/Microsoft/vscode-cpptools/issues/3052), [#3139](https://github.com/Microsoft/vscode-cpptools/issues/3139)
|
||||
* Enable `${command:cpptools.activeConfigName}` in tasks. [#1524](https://github.com/Microsoft/vscode-cpptools/issues/1524)
|
||||
* Fix bugs with squiggles and IntelliSense updating after edits. [#1779](https://github.com/Microsoft/vscode-cpptools/issues/1779), [#3124](https://github.com/Microsoft/vscode-cpptools/issues/3124), [#3260](https://github.com/Microsoft/vscode-cpptools/issues/3260)
|
||||
* Fix formatting (and other non-IntelliSense operations) being blocked by IntelliSense processing. [#1928](https://github.com/Microsoft/vscode-cpptools/issues/1928)
|
||||
* Fix completion when the start of an identifier matches a keyword. [#1986](https://github.com/Microsoft/vscode-cpptools/issues/1986)
|
||||
* Fix auto-removal of compiler-provided paths in `includePath`. [#2177](https://github.com/Microsoft/vscode-cpptools/issues/2177)
|
||||
* Fix crash on Windows when 8.3 filenames are used. [#2453](https://github.com/Microsoft/vscode-cpptools/issues/2453), [#3104](https://github.com/Microsoft/vscode-cpptools/issues/3104)
|
||||
* Add support for `Scope::Member` scoped symbol searches. [#2484](https://github.com/Microsoft/vscode-cpptools/issues/2484)
|
||||
* Fix signature help active parameter selection when parameter names are missing or subsets of each other. [#2952](https://github.com/Microsoft/vscode-cpptools/issues/2952)
|
||||
* Fix `--enable-pretty-printing` with `gdb` when complex objects are used as keys in maps. [#3024](https://github.com/Microsoft/vscode-cpptools/issues/3024)
|
||||
* Fix IntelliSense-based `Go to Definition` for `noexcept` methods. [#3060](https://github.com/Microsoft/vscode-cpptools/issues/3060)
|
||||
* Render macro hover expansions as C/C++. [#3075](https://github.com/Microsoft/vscode-cpptools/issues/3075)
|
||||
* Enable completion after `struct` when manually invoked. [#3080](https://github.com/Microsoft/vscode-cpptools/issues/3080)
|
||||
* Add `C_Cpp.suggestSnippets` setting to disable language server snippets. [#3083](https://github.com/Microsoft/vscode-cpptools/issues/3083)
|
||||
* Show a prompt for changing `C_Cpp.updateChannel` to `Insiders`. [#3089](https://github.com/Microsoft/vscode-cpptools/issues/3089)
|
||||
* lh123 (@lh123) [PR #3221](https://github.com/Microsoft/vscode-cpptools/pull/3221)
|
||||
* Fix `compilerPath` not getting priority over the `compile_commands.json` compiler. [#3102](https://github.com/Microsoft/vscode-cpptools/issues/3102)
|
||||
* Fix Linux `compile_commands.json` compiler querying with relative paths. [#3112](https://github.com/Microsoft/vscode-cpptools/issues/3112)
|
||||
* Allow `*` in `includePath` to apply to `browse.path` when `browse.path` is not specified. [#3121](https://github.com/Microsoft/vscode-cpptools/issues/3121)
|
||||
* Tucker Kern (@mill1000) [PR #3122](https://github.com/Microsoft/vscode-cpptools/pull/3122)
|
||||
* Disable `(` and `<` completion commit characters. [#3127](https://github.com/Microsoft/vscode-cpptools/issues/3127)
|
||||
* Add Chinese translations for command titles. [PR #3128](https://github.com/Microsoft/vscode-cpptools/pull/3128)
|
||||
* Fix remote process picker bug. [#2585](https://github.com/Microsoft/vscode-cpptools/issues/2585), [#3150](https://github.com/Microsoft/vscode-cpptools/issues/3150)
|
||||
* Fix command not found and empty `c_cpp_properties.json` if activation is too slow. [#3160](https://github.com/Microsoft/vscode-cpptools/issues/3160), [#3176](https://github.com/Microsoft/vscode-cpptools/issues/3176)
|
||||
* Fix `cppvsdbg` debugger showing `"An unspecified error has occurred."` for structured binding variables. [#3197](https://github.com/Microsoft/vscode-cpptools/issues/3197)
|
||||
* Fix bugs with the Insider reload prompt appearing when it shouldn't. [#3206](https://github.com/Microsoft/vscode-cpptools/issues/3206)
|
||||
* Fix variable expansion (e.g. `${env.HOME}`) not working when `${default}` is used in `c_cpp_properties.json`. [#3309](https://github.com/Microsoft/vscode-cpptools/issues/3309)
|
||||
* Fix other unreported IntelliSense engine bugs.
|
||||
|
||||
## Version 0.21.0: January 23, 2019
|
||||
### New Features
|
||||
* Add documentation comments for hover, completion, and signature help. [#399](https://github.com/Microsoft/vscode-cpptools/issues/399)
|
||||
* Add completion committing for methods after `(`. [#1184](https://github.com/Microsoft/vscode-cpptools/issues/1184)
|
||||
|
||||
+13
-1
@@ -1,4 +1,9 @@
|
||||
# C/C++ for Visual Studio Code
|
||||
|
||||
### [Repository](https://github.com/microsoft/vscode-cpptools) | [Issues](https://github.com/microsoft/vscode-cpptools/issues) | [Documentation](https://github.com/microsoft/vscode-cpptools/tree/master/Documentation) | [Code Samples](https://github.com/microsoft/vscode-cpptools/tree/master/Code%20Samples) | [Offline Installers](https://github.com/microsoft/vscode-cpptools/releases)
|
||||
|
||||
[](https://aka.ms/vsls)
|
||||
|
||||
This preview release of the extension adds language support for C/C++ to Visual Studio Code including:
|
||||
* Language service
|
||||
* Code Formatting (clang-format)
|
||||
@@ -23,5 +28,12 @@ This preview release of the extension adds language support for C/C++ to Visual
|
||||
|
||||
You can find more detailed information about C/C++ support for Visual Studio Code at our [GitHub page](https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation) and our [VS Code documentation page](https://code.visualstudio.com/docs/languages/cpp).
|
||||
|
||||
## Installation
|
||||
The extension has OS-specific binary dependencies, so installation via the Marketplace requires an Internet connection so that these additional dependencies can be downloaded. If you are working on a computer that does not have access to the Internet or is behind a strict firewall, you may need to use our OS-specific packages and install them by invoking VS Code's `"Install from VSIX..."` command. These "offline' packages are available at: https://github.com/Microsoft/vscode-cpptools/releases.
|
||||
* `cpptools-linux.vsix` - for 64-bit Linux
|
||||
* `cpptools-linux32.vsix` - for 32-bit Linux
|
||||
* `cpptools-osx.vsix` - for macOS
|
||||
* `cpptools-win32.vsix` - for 64-bit & 32-bit Windows
|
||||
|
||||
## Contact Us
|
||||
If you run into any issues or have suggestions for us, please file [issues and suggestions on GitHub](https://github.com/Microsoft/vscode-cpptools/issues). If you haven’t already provided us feedback, please take this [quick survey](https://www.research.net/r/VBVV6C6) to help shape this extension for your needs.
|
||||
If you run into any issues or have suggestions for us, please file [issues and suggestions on GitHub](https://github.com/Microsoft/vscode-cpptools/issues). If you haven’t already provided us feedback, please take this [quick survey](https://www.research.net/r/VBVV6C6) and let us know what you think!
|
||||
|
||||
@@ -205,8 +205,15 @@
|
||||
<tr>
|
||||
<td>
|
||||
<div>
|
||||
<h2 class="caption">January 2019 Update</h2>
|
||||
<div>Thank you for installing the C/C++ extension. In the January update, we added documentation comments for hover, completion, and signature help.<br/>
|
||||
<h2 class="caption">June 2019 Update</h2>
|
||||
<div>Thank you for installing the C/C++ extension! We're excited to announce the following feature in the June update:<br/>
|
||||
<h3 style="font-weight: 600">Enhanced Colorization</h3>
|
||||
The extension now supports semantic colorization.
|
||||
Enhanced colorization adds colors for tokens identified semantically by IntelliSense.
|
||||
Colors can be configured by themes or customized in settings.
|
||||
More information can be found <a href="https://github.com/microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/colorization.md">here</a>.
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
Additional features and bug fixes are detailed in the <a href="https://github.com/Microsoft/vscode-cpptools/releases">full release notes</a>.</div>
|
||||
</div>
|
||||
@@ -231,10 +238,9 @@
|
||||
<td>
|
||||
<div>
|
||||
<h3 class="caption">Blog Posts</h3>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/12/05/visual-studio-code-cpp-extension-october-2018-update-and-a-simplified-insiders-program/">October 2018 Update</a></div>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/08/23/visual-studio-code-c-c-extension-august-2018-update/">August 2018 Update</a></div>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/07/25/visual-studio-code-cc-extension-july-2018-update-and-intellisense-auto-configuration-for-cmake/">July 2018 Update</a></div>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2016/03/31/cc-extension-for-visual-studio-code/">C/C++ Extension anouncement</a></div>
|
||||
<div><a href="https://devblogs.microsoft.com/cppblog/vscode-cpp-may-2019-update/">May 2019 Update</a></div>
|
||||
<div><a href="https://devblogs.microsoft.com/cppblog/visual-studio-code-c-c-extension-march-2019-update/">March 2019 Update</a></div>
|
||||
<div><a href="https://devblogs.microsoft.com/cppblog/vs-code-cpp-extension-january-2019-update/">January 2019 Update</a></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
+2310
-1431
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,7 @@
|
||||
}
|
||||
},
|
||||
"intelliSenseMode": {
|
||||
"description": "If set, it overrides the default mode used by the IntelliSense engine. Windows defaults to msvc-x64, Linux defaults to gcc-x64, and Mac default to clang-x64.",
|
||||
"description": "If set, it overrides the default mode used by the IntelliSense engine. Windows defaults to msvc-x64, Linux defaults to gcc-x64, and Mac defaults to clang-x64.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"msvc-x64",
|
||||
@@ -112,9 +112,11 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
@@ -140,6 +142,11 @@
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"description": "Version of the configuration file. This property is managed by the extension. Please do not change it."
|
||||
},
|
||||
"enableConfigurationSquiggles": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Controls whether the extension will report errors detected in c_cpp_properties.json."
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
@@ -151,10 +158,14 @@
|
||||
},
|
||||
"version": {
|
||||
"$ref": "#/definitions/version"
|
||||
},
|
||||
"enableConfigurationSquiggles": {
|
||||
"$ref": "#/definitions/enableConfigurationSquiggles"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"configurations",
|
||||
"version"
|
||||
]
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
"intelliSenseEngine_default_percentage": 100,
|
||||
"defaultIntelliSenseEngine": 100,
|
||||
"recursiveIncludes": 100,
|
||||
"gotoDefIntelliSense": 100
|
||||
"gotoDefIntelliSense": 100,
|
||||
"enhancedColorization": 100
|
||||
}
|
||||
@@ -29,28 +29,9 @@ gulp.task('unitTests', (done) => {
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('integrationTests', (done) => {
|
||||
env.set({
|
||||
CODE_TESTS_PATH: "./out/test/integrationTests",
|
||||
CODE_TESTS_WORKSPACE: "./test/integrationTests/testAssets/SimpleCppProject"
|
||||
});
|
||||
|
||||
return gulp.src('./test/runVsCodeTestsWithAbsolutePaths.js', {read: false})
|
||||
.pipe(mocha({ ui: "tdd" }))
|
||||
.once('error', err => {
|
||||
done();
|
||||
process.exit(1);
|
||||
})
|
||||
.once('end', () => {
|
||||
done();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
/// Misc Tasks
|
||||
const allTypeScript = [
|
||||
'src/**/*.ts',
|
||||
'tools/**/*.ts',
|
||||
'!**/*.d.ts',
|
||||
'!**/typings**'
|
||||
];
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
parameters:
|
||||
name: ''
|
||||
pool: ''
|
||||
|
||||
jobs:
|
||||
- job: Windows
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
displayName: 'Use Node 8.x'
|
||||
inputs:
|
||||
versionSpec: 8.x
|
||||
|
||||
- script: npm install
|
||||
displayName: "Install Dependencies"
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
|
||||
- script: npm run compile
|
||||
displayName: "Compile Sources"
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
|
||||
- script: npm run pr-check
|
||||
displayName: 'Validate Extension/package.json'
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
|
||||
- script: npm run tslint
|
||||
displayName: 'Run Linter'
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
|
||||
- script: npm run pretest
|
||||
displayName: "Compile Test Sources"
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
|
||||
- script: 'npm run unitTests'
|
||||
displayName: 'Run unit tests'
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
|
||||
- script: 'node node_modules/vscode/bin/test'
|
||||
displayName: 'Run languageServer integration tests'
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
env:
|
||||
CODE_TESTS_PATH: '$(Build.SourcesDirectory)\Extension\out\test\integrationTests\languageServer'
|
||||
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)\Extension'
|
||||
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)\Extension\test\integrationTests\testAssets\SimpleCppProject'
|
||||
CODE_DISABLE_EXTENSIONS: 1
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
continueOnError: true
|
||||
@@ -0,0 +1,57 @@
|
||||
parameters:
|
||||
name: ''
|
||||
pool: ''
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
pool: ${{ parameters.pool }}
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
displayName: 'Use Node 8.x'
|
||||
inputs:
|
||||
versionSpec: 8.x
|
||||
|
||||
- script: npm install
|
||||
displayName: "Install Dependencies"
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
|
||||
- script: npm run compile
|
||||
displayName: "Compile Sources"
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
|
||||
- script: npm run pr-check
|
||||
displayName: 'Validate Extension/package.json'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
|
||||
- script: npm run tslint
|
||||
displayName: 'Run Linter'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
/usr/bin/Xvfb :10 -ac >> /tmp/Xvfb.out 2>&1 &
|
||||
disown -ar
|
||||
displayName: 'Start xvfb'
|
||||
|
||||
- script: npm run pretest
|
||||
displayName: "Compile Test Sources"
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
|
||||
- script: 'npm run unitTests'
|
||||
displayName: 'Run unit tests'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
|
||||
- script: 'node node_modules/vscode/bin/test'
|
||||
displayName: 'Run languageServer integration tests'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
env:
|
||||
DISPLAY: :10
|
||||
CODE_TESTS_PATH: '$(Build.SourcesDirectory)/Extension/out/test/integrationTests/languageServer'
|
||||
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)/Extension'
|
||||
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)/Extension/test/integrationTests/testAssets/SimpleCppProject'
|
||||
CODE_DISABLE_EXTENSIONS: 1
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
continueOnError: true
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "C",
|
||||
"scopeName": "source.c",
|
||||
"version": "0",
|
||||
"information_for_contributors": [
|
||||
],
|
||||
"patterns": [
|
||||
],
|
||||
"repository": {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "C++",
|
||||
"scopeName": "source.cpp",
|
||||
"version": "0",
|
||||
"information_for_contributors": [
|
||||
],
|
||||
"patterns": [
|
||||
],
|
||||
"repository": {
|
||||
}
|
||||
}
|
||||
Generated
+2884
-3325
File diff suppressed because it is too large
Load Diff
+160
-68
@@ -2,7 +2,7 @@
|
||||
"name": "cpptools",
|
||||
"displayName": "C/C++",
|
||||
"description": "C/C++ IntelliSense, debugging, and code browsing.",
|
||||
"version": "0.21.0",
|
||||
"version": "0.24.0",
|
||||
"publisher": "ms-vscode",
|
||||
"preview": true,
|
||||
"icon": "LanguageCCPP_color_128x.png",
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"engines": {
|
||||
"vscode": "^1.26.0"
|
||||
"vscode": "^1.30.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/vscode-cpptools/issues",
|
||||
@@ -41,18 +41,19 @@
|
||||
"activationEvents": [
|
||||
"*"
|
||||
],
|
||||
"main": "./out/src/main",
|
||||
"main": "./dist/main",
|
||||
"contributes": {
|
||||
"problemMatchers": [
|
||||
{
|
||||
"name": "gcc",
|
||||
"source": "gcc",
|
||||
"owner": "cpptools",
|
||||
"fileLocation": [
|
||||
"relative",
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"pattern": {
|
||||
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
|
||||
"regexp": "^(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
@@ -72,18 +73,18 @@
|
||||
],
|
||||
"default": null,
|
||||
"description": "The full path of the clang-format executable.",
|
||||
"scope": "resource"
|
||||
"scope": "machine"
|
||||
},
|
||||
"C_Cpp.clang_format_style": {
|
||||
"type": "string",
|
||||
"default": "file",
|
||||
"description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use \"{key: value, ...}\" to set specific parameters, e.g.: \"{ BasedOnStyle: LLVM, IndentWidth: 8 }\"",
|
||||
"description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4 }",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.clang_format_fallbackStyle": {
|
||||
"type": "string",
|
||||
"default": "Visual Studio",
|
||||
"description": "Name of the predefined style used as a fallback in case clang-format is invoked with style \"file\" but the .clang-format file is not found. Possible values are Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit, none, or use \"{key: value, ...}\" to set specific parameters, e.g.: \"{ BasedOnStyle: LLVM, IndentWidth: 8 }\"",
|
||||
"description": "Name of the predefined style used as a fallback in case clang-format is invoked with style \"file\" but the .clang-format file is not found. Possible values are Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit, none, or use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4 }",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.clang_format_sortIncludes": {
|
||||
@@ -117,7 +118,7 @@
|
||||
"Enabled",
|
||||
"Disabled"
|
||||
],
|
||||
"default": "Enabled",
|
||||
"default": "Disabled",
|
||||
"description": "Controls whether the IntelliSense engine will automatically switch to the Tag Parser for translation units containing #include errors.",
|
||||
"scope": "resource"
|
||||
},
|
||||
@@ -135,16 +136,17 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Enabled",
|
||||
"Disabled"
|
||||
"Disabled",
|
||||
"EnabledIfIncludesResolve"
|
||||
],
|
||||
"default": "Enabled",
|
||||
"description": "Controls whether suspected compile errors detected by the IntelliSense engine will be reported back to the editor. Warnings about #includes that could not be located will always be reported to the editor. This setting is ignored by the Tag Parser engine.",
|
||||
"default": "EnabledIfIncludesResolve",
|
||||
"description": "Controls whether suspected compile errors detected by the IntelliSense engine will be reported back to the editor. This setting is ignored by the Tag Parser engine.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.dimInactiveRegions": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Controls whether inactive preprocessor blocks are colored differently than active code. This setting is ignored by the Tag Parser engine.",
|
||||
"description": "Controls whether inactive preprocessor blocks are colored differently than active code. This setting has no effect if IntelliSense is disabled or if using the Default High Contrast theme.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.inactiveRegionOpacity": {
|
||||
@@ -289,6 +291,19 @@
|
||||
"description": "Determines whether pop up notifications will be shown when a configuration provider extension is unable to provide a configuration for a source file.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.intelliSenseCachePath": {
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"description": "Defines the folder path for cached precompiled headers used by IntelliSense. The default cache path is \"%LocalAppData%/Microsoft/vscode-cpptools\" on Windows and \"~/.vscode-cpptools\" on Linux and Mac. The default path will be used if no path is specified or if a specified path is invalid.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.intelliSenseCacheSize": {
|
||||
"type": "number",
|
||||
"default": 5120,
|
||||
"description": "Maximum size of the per-workspace hard drive space in megabytes for cached precompiled headers; the actual usage may fluctuate around this value. The default size is 5120 MB. Precompiled header caching is disabled when the size is 0.",
|
||||
"scope": "resource",
|
||||
"minimum": 0
|
||||
},
|
||||
"C_Cpp.default.includePath": {
|
||||
"type": [
|
||||
"array",
|
||||
@@ -457,6 +472,15 @@
|
||||
"description": "The value to use for the system include path. If set, it overrides the system include path acquired via \"compilerPath\" and \"compileCommands\" settings.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.default.enableConfigurationSquiggles": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
],
|
||||
"default": null,
|
||||
"description": "Controls whether the extension will report errors detected in c_cpp_properties.json.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.updateChannel": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -466,6 +490,22 @@
|
||||
"default": "Default",
|
||||
"description": "Set to \"Insiders\" to automatically download and install the latest Insiders builds of the extension, which include upcoming features and bug fixes.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.suggestSnippets": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "If true, snippets are provided by the language server.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.enhancedColorization": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Enabled",
|
||||
"Disabled"
|
||||
],
|
||||
"default": "Enabled",
|
||||
"description": "If enabled, code is colorized based on IntelliSense. This setting has no effect if IntelliSense is disabled or if using the Default High Contrast theme.",
|
||||
"scope": "resource"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -481,8 +521,13 @@
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ConfigurationEdit",
|
||||
"title": "%c_cpp.command.configurationEdit.title%",
|
||||
"command": "C_Cpp.ConfigurationEditJSON",
|
||||
"title": "%c_cpp.command.configurationEditJSON.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ConfigurationEditUI",
|
||||
"title": "%c_cpp.command.configurationEditUI.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
@@ -506,8 +551,13 @@
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ToggleErrorSquiggles",
|
||||
"title": "%c_cpp.command.toggleErrorSquiggles.title%",
|
||||
"command": "C_Cpp.EnableErrorSquiggles",
|
||||
"title": "%c_cpp.command.enableErrorSquiggles.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.DisableErrorSquiggles",
|
||||
"title": "%c_cpp.command.disableErrorSquiggles.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
@@ -549,6 +599,21 @@
|
||||
"command": "C_Cpp.TakeSurvey",
|
||||
"title": "%c_cpp.command.takeSurvey.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.BuildAndDebugActiveFile",
|
||||
"title": "%c_cpp.command.buildAndDebugActiveFile.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.LogDiagnostics",
|
||||
"title": "%c_cpp.command.logDiagnostics.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.RescanWorkspace",
|
||||
"title": "%c_cpp.command.rescanWorkspace.title%",
|
||||
"category": "C/C++"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
@@ -603,7 +668,6 @@
|
||||
"cpp"
|
||||
]
|
||||
},
|
||||
"adapterExecutableCommand": "extension.cppdbgAdapterExecutableCommand",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"variables": {
|
||||
"pickProcess": "extension.pickNativeProcess",
|
||||
@@ -733,6 +797,11 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"envFile": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a file containing environment variable definitions. This file has key value pairs separated by an equals sign per line. E.g. KEY=VALUE",
|
||||
"default": "${workspaceFolder}/.env"
|
||||
},
|
||||
"additionalSOLibSearchPath": {
|
||||
"type": "string",
|
||||
"description": "Semicolon separated list of directories to use to search for .so files. Example: \"c:\\dir1;c:\\dir2\".",
|
||||
@@ -954,12 +1023,12 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": "${command:pickProcess}"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
@@ -1100,7 +1169,6 @@
|
||||
"cpp"
|
||||
]
|
||||
},
|
||||
"adapterExecutableCommand": "extension.cppvsdbgAdapterExecutableCommand",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"variables": {
|
||||
"pickProcess": "extension.pickNativeProcess"
|
||||
@@ -1154,6 +1222,11 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"envFile": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a file containing environment variable definitions. This file has key value pairs separated by an equals sign per line. E.g. KEY=VALUE",
|
||||
"default": "${workspaceFolder}/.env"
|
||||
},
|
||||
"symbolSearchPath": {
|
||||
"type": "string",
|
||||
"description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".",
|
||||
@@ -1186,6 +1259,11 @@
|
||||
"<source-path>": "<target-path>"
|
||||
}
|
||||
},
|
||||
"enableDebugHeap": {
|
||||
"type": "boolean",
|
||||
"description": "If false, the process will be launched with debug heap disabled. This sets the environment variable '_NO_DEBUG_HEAP' to '1'.",
|
||||
"default": false
|
||||
},
|
||||
"logging": {
|
||||
"type": "object",
|
||||
"description": "Optional flags to determine what types of messages should be logged to the Debug Console.",
|
||||
@@ -1236,12 +1314,12 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": "${command:pickProcess}"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
@@ -1321,42 +1399,52 @@
|
||||
{
|
||||
"when": "editorLangId == c",
|
||||
"command": "C_Cpp.SwitchHeaderSource",
|
||||
"group": "other@1"
|
||||
"group": "other1_navigation@1"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == cpp",
|
||||
"command": "C_Cpp.SwitchHeaderSource",
|
||||
"group": "other@1"
|
||||
"group": "other1_navigation@1"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == c",
|
||||
"command": "C_Cpp.Navigate",
|
||||
"group": "other@2"
|
||||
"group": "other1_navigation@2"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == cpp",
|
||||
"command": "C_Cpp.Navigate",
|
||||
"group": "other@2"
|
||||
"group": "other1_navigation@2"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == c",
|
||||
"command": "workbench.action.gotoSymbol",
|
||||
"group": "other@3"
|
||||
"group": "other1_navigation@3"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == cpp",
|
||||
"command": "workbench.action.gotoSymbol",
|
||||
"group": "other@3"
|
||||
"group": "other1_navigation@3"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == c",
|
||||
"command": "workbench.action.showAllSymbols",
|
||||
"group": "other@4"
|
||||
"group": "other1_navigation@4"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == cpp",
|
||||
"command": "workbench.action.showAllSymbols",
|
||||
"group": "other@4"
|
||||
"group": "other1_navigation@4"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == cpp",
|
||||
"command": "C_Cpp.BuildAndDebugActiveFile",
|
||||
"group": "other2_debug@1"
|
||||
},
|
||||
{
|
||||
"when": "editorLangId == c",
|
||||
"command": "C_Cpp.BuildAndDebugActiveFile",
|
||||
"group": "other2_debug@1"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1371,53 +1459,57 @@
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "npm run vscode:prepublish",
|
||||
"compileDev": "npm run prepublishjs && webpack --mode development",
|
||||
"generateOptionsSchema": "gulp generateOptionsSchema",
|
||||
"integrationTests": "gulp integrationTests",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install",
|
||||
"pretest": "tsc -p ./",
|
||||
"prepublishjs": "node ./tools/prepublish.js",
|
||||
"pretest": "tsc -p test.tsconfig.json",
|
||||
"pr-check": "gulp pr-check",
|
||||
"test": "gulp allTests",
|
||||
"tslint": "gulp tslint",
|
||||
"unitTests": "gulp unitTests",
|
||||
"vscode:prepublish": "node ./src/Support/prepublish.js",
|
||||
"watch": "tsc -watch -p ./"
|
||||
"vscode:prepublish": "npm run prepublishjs && webpack --mode production",
|
||||
"watch": "webpack --watch --mode development"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^2.2.43",
|
||||
"@types/node": "^8.0.46",
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^12.0.10",
|
||||
"async-child-process": "^1.1.1",
|
||||
"child-process": "^1.0.2",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-env": "0.4.0",
|
||||
"gulp-mocha": "5.0.0",
|
||||
"gulp-tslint": "8.1.2",
|
||||
"mocha": "^4.0.1",
|
||||
"tslint": "5.8.0",
|
||||
"tslint-microsoft-contrib": "5.0.1",
|
||||
"tslint-no-unused-expression-chai": "0.0.3",
|
||||
"typescript": "^2.5.3",
|
||||
"vrsource-tslint-rules": "^5.8.2",
|
||||
"vscode": "^1.1.18"
|
||||
"await-notify": "^1.0.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-env": "^0.4.0",
|
||||
"gulp-mocha": "^6.0.0",
|
||||
"gulp-tslint": "^8.1.4",
|
||||
"ts-loader": "^6.0.4",
|
||||
"tslint": "^5.18.0",
|
||||
"tslint-microsoft-contrib": "^6.2.0",
|
||||
"tslint-no-unused-expression-chai": "^0.1.4",
|
||||
"typescript": "^3.5.2",
|
||||
"vrsource-tslint-rules": "^6.0.0",
|
||||
"vscode": "^1.1.35",
|
||||
"webpack": "^4.35.2",
|
||||
"webpack-cli": "^3.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"http-proxy-agent": "~2.1.0",
|
||||
"https-proxy-agent": "~2.2.0",
|
||||
"jsonc-parser": "^1.0.0",
|
||||
"minimatch": "~3.0.4",
|
||||
"mkdirp": "~0.5.1",
|
||||
"tmp": "~0.0.33",
|
||||
"vscode-cpptools": "2.1.1",
|
||||
"vscode-debugadapter": "~1.24.0",
|
||||
"vscode-debugprotocol": "~1.24.0",
|
||||
"vscode-extension-telemetry": "~0.1.0",
|
||||
"vscode-languageclient": "5.1.1",
|
||||
"yauzl": "~2.10.0"
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
"https-proxy-agent": "^2.2.1",
|
||||
"jsonc-parser": "^2.1.0",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"plist": "^2.0.1",
|
||||
"tmp": "^0.1.0",
|
||||
"vscode-cpptools": "^2.1.2",
|
||||
"vscode-debugadapter": "^1.34.0",
|
||||
"vscode-debugprotocol": "^1.34.0",
|
||||
"vscode-extension-telemetry": "^0.1.1",
|
||||
"vscode-languageclient": "^5.2.1",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
"runtimeDependencies": [
|
||||
{
|
||||
"description": "C/C++ language components (Linux / x86_64)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2037608",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092533",
|
||||
"platforms": [
|
||||
"linux"
|
||||
],
|
||||
@@ -1431,7 +1523,7 @@
|
||||
},
|
||||
{
|
||||
"description": "C/C++ language components (Linux / x86)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2037526",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092603",
|
||||
"platforms": [
|
||||
"linux"
|
||||
],
|
||||
@@ -1447,7 +1539,7 @@
|
||||
},
|
||||
{
|
||||
"description": "C/C++ language components (OS X)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2037527",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092602",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
@@ -1458,7 +1550,7 @@
|
||||
},
|
||||
{
|
||||
"description": "C/C++ language components (Windows)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2037609",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092532",
|
||||
"platforms": [
|
||||
"win32"
|
||||
],
|
||||
@@ -1572,11 +1664,11 @@
|
||||
},
|
||||
{
|
||||
"description": "Visual Studio Windows Debugger",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=872985",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2082216",
|
||||
"platforms": [
|
||||
"win32"
|
||||
],
|
||||
"binaries": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
{
|
||||
"c_cpp.command.configurationSelect.title": "Scegli una configurazione...",
|
||||
"c_cpp.command.configurationProviderSelect.title": "Cambia provider configurazioni...",
|
||||
"c_cpp.command.configurationEdit.title": "Modifica configurazioni...",
|
||||
"c_cpp.command.configurationEditJSON.title": "Modifica configurazioni (JSON)",
|
||||
"c_cpp.command.configurationEditUI.title": "Modifica configurazioni (UI)",
|
||||
"c_cpp.command.goToDeclaration.title": "Vai a dichiarazione",
|
||||
"c_cpp.command.peekDeclaration.title": "Visualizza dichiarazione",
|
||||
"c_cpp.command.switchHeaderSource.title": "Visualizza Header/Sorgente",
|
||||
"c_cpp.command.switchHeaderSource.title": "Visualizza header/sorgente",
|
||||
"c_cpp.command.navigate.title": "Naviga...",
|
||||
"c_cpp.command.toggleErrorSquiggles.title": "Attiva/Disattiva sottolineamento errori",
|
||||
"c_cpp.command.enableErrorSquiggles.title": "Attiva sottolineamento errori",
|
||||
"c_cpp.command.disableErrorSquiggles.title": "Disattiva sottolineamento errori",
|
||||
"c_cpp.command.toggleIncludeFallback.title": "Attiva/Disattiva motore di fallback IntelliSense negli errori di inclusione",
|
||||
"c_cpp.command.toggleDimInactiveRegions.title": "Attiva/Disattiva colorazione regioni inattive",
|
||||
"c_cpp.command.showReleaseNotes.title": "Mostra note di rilascio",
|
||||
@@ -14,5 +16,8 @@
|
||||
"c_cpp.command.pauseParsing.title": "Metti in pausa l'analisi del codice",
|
||||
"c_cpp.command.resumeParsing.title": "Riprendi l'analisi del codice",
|
||||
"c_cpp.command.showParsingCommands.title": "Mostra comandi per l'analisi del codice",
|
||||
"c_cpp.command.takeSurvey.title": "Partecipa al Sondaggio"
|
||||
"c_cpp.command.takeSurvey.title": "Partecipa al sondaggio",
|
||||
"c_cpp.command.buildAndDebugActiveFile.title": "Compila ed esegui il debug del file attivo",
|
||||
"c_cpp.command.logDiagnostics.title": "Registra diagnostica",
|
||||
"c_cpp.command.rescanWorkspace.title": "Ripetere l'analisi dell'area di lavoro"
|
||||
}
|
||||
+19
-14
@@ -1,18 +1,23 @@
|
||||
{
|
||||
"c_cpp.command.configurationSelect.title": "Select a configuration...",
|
||||
"c_cpp.command.configurationProviderSelect.title": "Change configuration provider...",
|
||||
"c_cpp.command.configurationEdit.title": "Edit configurations...",
|
||||
"c_cpp.command.goToDeclaration.title": "Go to declaration",
|
||||
"c_cpp.command.peekDeclaration.title": "Peek declaration",
|
||||
"c_cpp.command.configurationSelect.title": "Select a Configuration...",
|
||||
"c_cpp.command.configurationProviderSelect.title": "Change Configuration Provider...",
|
||||
"c_cpp.command.configurationEditJSON.title": "Edit Configurations (JSON)",
|
||||
"c_cpp.command.configurationEditUI.title": "Edit Configurations (UI)",
|
||||
"c_cpp.command.goToDeclaration.title": "Go to Declaration",
|
||||
"c_cpp.command.peekDeclaration.title": "Peek Declaration",
|
||||
"c_cpp.command.switchHeaderSource.title": "Switch Header/Source",
|
||||
"c_cpp.command.navigate.title": "Navigate...",
|
||||
"c_cpp.command.toggleErrorSquiggles.title": "Toggle error squiggles",
|
||||
"c_cpp.command.toggleIncludeFallback.title": "Toggle IntelliSense engine fallback on include errors",
|
||||
"c_cpp.command.toggleDimInactiveRegions.title": "Toggle inactive region colorization",
|
||||
"c_cpp.command.showReleaseNotes.title": "Show release notes",
|
||||
"c_cpp.command.resetDatabase.title": "Reset IntelliSense database",
|
||||
"c_cpp.command.pauseParsing.title": "Pause parsing",
|
||||
"c_cpp.command.resumeParsing.title": "Resume parsing",
|
||||
"c_cpp.command.showParsingCommands.title": "Show parsing commands",
|
||||
"c_cpp.command.takeSurvey.title": "Take survey"
|
||||
"c_cpp.command.enableErrorSquiggles.title": "Enable Error Squiggles",
|
||||
"c_cpp.command.disableErrorSquiggles.title": "Disable Error Squiggles",
|
||||
"c_cpp.command.toggleIncludeFallback.title": "Toggle IntelliSense Engine Fallback on Include Errors",
|
||||
"c_cpp.command.toggleDimInactiveRegions.title": "Toggle Inactive Region Colorization",
|
||||
"c_cpp.command.showReleaseNotes.title": "Show Release Notes",
|
||||
"c_cpp.command.resetDatabase.title": "Reset IntelliSense Database",
|
||||
"c_cpp.command.pauseParsing.title": "Pause Parsing",
|
||||
"c_cpp.command.resumeParsing.title": "Resume Parsing",
|
||||
"c_cpp.command.showParsingCommands.title": "Show Parsing Commands",
|
||||
"c_cpp.command.takeSurvey.title": "Take Survey",
|
||||
"c_cpp.command.buildAndDebugActiveFile.title": "Build and Debug Active File",
|
||||
"c_cpp.command.logDiagnostics.title": "Log Diagnostics",
|
||||
"c_cpp.command.rescanWorkspace.title": "Rescan Workspace"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"c_cpp.command.configurationSelect.title": "选择配置...",
|
||||
"c_cpp.command.configurationProviderSelect.title": "更换配置提供程序...",
|
||||
"c_cpp.command.configurationEditJSON.title": "编辑配置 (JSON)",
|
||||
"c_cpp.command.configurationEditUI.title": "编辑配置 (UI)",
|
||||
"c_cpp.command.goToDeclaration.title": "跳转到声明",
|
||||
"c_cpp.command.peekDeclaration.title": "查看声明",
|
||||
"c_cpp.command.switchHeaderSource.title": "切换头文件/源文件",
|
||||
"c_cpp.command.navigate.title": "导航...",
|
||||
"c_cpp.command.enableErrorSquiggles.title": "启用错误下划线",
|
||||
"c_cpp.command.disableErrorSquiggles.title": "禁用错误下划线",
|
||||
"c_cpp.command.toggleIncludeFallback.title": "切换IntelliSense引擎头文件包含错误回退",
|
||||
"c_cpp.command.toggleDimInactiveRegions.title": "切换非活跃区域着色",
|
||||
"c_cpp.command.showReleaseNotes.title": "查看版本说明",
|
||||
"c_cpp.command.resetDatabase.title": "重置IntelliSense数据",
|
||||
"c_cpp.command.pauseParsing.title": "暂停解析",
|
||||
"c_cpp.command.resumeParsing.title": "继续解析",
|
||||
"c_cpp.command.showParsingCommands.title": "查看解析命令",
|
||||
"c_cpp.command.takeSurvey.title": "调查问卷",
|
||||
"c_cpp.command.buildAndDebugActiveFile.title": "生成和调试当前文件",
|
||||
"c_cpp.command.logDiagnostics.title": "记录诊断",
|
||||
"c_cpp.command.rescanWorkspace.title": "重新扫描工作区"
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
|
||||
export interface Environment {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export class ParsedEnvironmentFile {
|
||||
public Env: Environment[];
|
||||
public Warning: string | null;
|
||||
|
||||
private constructor(env: Environment[], warning: string | null) {
|
||||
this.Env = env;
|
||||
this.Warning = warning;
|
||||
}
|
||||
|
||||
public static CreateFromFile(envFile: string, initialEnv: Environment[] | undefined): ParsedEnvironmentFile {
|
||||
let content: string = fs.readFileSync(envFile, "utf8");
|
||||
return this.CreateFromContent(content, envFile, initialEnv);
|
||||
}
|
||||
|
||||
public static CreateFromContent(content: string, envFile: string, initialEnv: Environment[] | undefined): ParsedEnvironmentFile {
|
||||
|
||||
// Remove UTF-8 BOM if present
|
||||
if (content.charAt(0) === '\uFEFF') {
|
||||
content = content.substr(1);
|
||||
}
|
||||
|
||||
let parseErrors: string[] = [];
|
||||
let env: Map<string, any> = new Map();
|
||||
|
||||
if (initialEnv) {
|
||||
// Convert array to map to prevent duplicate keys being created.
|
||||
// If a duplicate key is found, replace it.
|
||||
initialEnv.forEach((e) => {
|
||||
env.set(e.name, e.value);
|
||||
});
|
||||
}
|
||||
|
||||
content.split("\n").forEach(line => {
|
||||
// Split the line between key and value
|
||||
const r: RegExpMatchArray = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
|
||||
|
||||
if (r !== null) {
|
||||
const key: string = r[1];
|
||||
let value: string = r[2] || "";
|
||||
if ((value.length > 0) && (value.charAt(0) === '"') && (value.charAt(value.length - 1) === '"')) {
|
||||
value = value.replace(/\\n/gm, "\n");
|
||||
}
|
||||
|
||||
value = value.replace(/(^['"]|['"]$)/g, "");
|
||||
|
||||
env.set(key, value);
|
||||
} else {
|
||||
// Blank lines and lines starting with # are no parse errors
|
||||
const comments: RegExp = new RegExp(/^\s*(#|$)/);
|
||||
if (!comments.test(line)) {
|
||||
parseErrors.push(line);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// show error message if single lines cannot get parsed
|
||||
let warning: string = null;
|
||||
if (parseErrors.length !== 0) {
|
||||
warning = "Ignoring non-parseable lines in envFile " + envFile + ": ";
|
||||
parseErrors.forEach(function (value, idx, array): void {
|
||||
warning += "\"" + value + "\"" + ((idx !== array.length - 1) ? ", " : ".");
|
||||
});
|
||||
}
|
||||
|
||||
// Convert env map back to array.
|
||||
const arrayEnv: Environment[] = [];
|
||||
for (let key of env.keys()) {
|
||||
arrayEnv.push({name: key, value: env.get(key)});
|
||||
}
|
||||
|
||||
return new ParsedEnvironmentFile(arrayEnv, warning);
|
||||
}
|
||||
}
|
||||
@@ -103,14 +103,29 @@ export class RemoteAttachPicker {
|
||||
});
|
||||
}
|
||||
|
||||
private getRemoteOSAndProcesses(pipeCmd: string): Promise<AttachItem[]> {
|
||||
// Commands to get OS and processes
|
||||
const command: string = `sh -c 'uname && if [ $(uname) = "Linux" ] ; then ${PsProcessParser.psLinuxCommand} ; elif [ $(uname) = "Darwin" ] ; ` +
|
||||
`then ${PsProcessParser.psDarwinCommand}; fi'`;
|
||||
// Creates a string to run on the host machine which will execute a shell script on the remote machine to retrieve OS and processes
|
||||
private getRemoteProcessCommand(): string {
|
||||
let innerQuote: string = `'`;
|
||||
let outerQuote: string = `"`;
|
||||
|
||||
return execChildProcess(`${pipeCmd} '${command}'`, null, this._channel).then(output => {
|
||||
// Must use single quotes around the whole command and double quotes for the argument to `sh -c` because Linux evaluates $() inside of double quotes.
|
||||
// Having double quotes for the outerQuote will have $(uname) replaced before it is sent to the remote machine.
|
||||
if (os.platform() !== "win32") {
|
||||
innerQuote = `"`;
|
||||
outerQuote = `'`;
|
||||
}
|
||||
|
||||
return `${outerQuote}sh -c ${innerQuote}uname && if [ $(uname) = \\\"Linux\\\" ] ; then ${PsProcessParser.psLinuxCommand} ; elif [ $(uname) = \\\"Darwin\\\" ] ; ` +
|
||||
`then ${PsProcessParser.psDarwinCommand}; fi${innerQuote}${outerQuote}`;
|
||||
}
|
||||
|
||||
private getRemoteOSAndProcesses(pipeCmd: string): Promise<AttachItem[]> {
|
||||
// Do not add any quoting in execCommand.
|
||||
const execCommand: string = `${pipeCmd} ${this.getRemoteProcessCommand()}`;
|
||||
|
||||
return execChildProcess(execCommand, null, this._channel).then(output => {
|
||||
// OS will be on first line
|
||||
// Processess will follow if listed
|
||||
// Processes will follow if listed
|
||||
let lines: string[] = output.split(/\r?\n/);
|
||||
|
||||
if (lines.length === 0) {
|
||||
|
||||
@@ -7,11 +7,83 @@ import * as debugUtils from './utils';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { getBuildTasks, BuildTaskDefinition } from '../LanguageServer/extension';
|
||||
import * as util from '../common';
|
||||
import * as fs from 'fs';
|
||||
import * as Telemetry from '../telemetry';
|
||||
import { buildAndDebugActiveFileStr } from './extension';
|
||||
import * as logger from '../logger';
|
||||
|
||||
import { IConfiguration, IConfigurationSnippet, DebuggerType, MIConfigurations, WindowsConfigurations, WSLConfigurations, PipeTransportConfigurations } from './configurations';
|
||||
import { parse } from 'jsonc-parser';
|
||||
import { PlatformInformation } from '../platform';
|
||||
import { Environment, ParsedEnvironmentFile } from './ParsedEnvironmentFile';
|
||||
|
||||
abstract class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
function isDebugLaunchStr(str: string): boolean {
|
||||
return str === "(gdb) Launch" || str === "(lldb) Launch" || str === "(Windows) Launch";
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves configurations from a provider and displays them in a quickpick menu to be selected.
|
||||
* Ensures that the selected configuration's preLaunchTask (if existent) is populated in the user's task.json.
|
||||
* Automatically starts debugging for "Build and Debug" configurations.
|
||||
*/
|
||||
export class QuickPickConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
private underlyingProvider: vscode.DebugConfigurationProvider;
|
||||
|
||||
public constructor(provider: CppConfigurationProvider) {
|
||||
this.underlyingProvider = provider;
|
||||
}
|
||||
|
||||
async provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration[]> {
|
||||
const configs: vscode.DebugConfiguration[] = await this.underlyingProvider.provideDebugConfigurations(folder, token);
|
||||
const defaultConfig: vscode.DebugConfiguration = configs.find(config => { return isDebugLaunchStr(config.name); });
|
||||
console.assert(defaultConfig);
|
||||
const editor: vscode.TextEditor = vscode.window.activeTextEditor;
|
||||
if (!editor || !util.fileIsCOrCppSource(editor.document.fileName) || configs.length <= 1) {
|
||||
return [defaultConfig];
|
||||
}
|
||||
interface MenuItem extends vscode.QuickPickItem {
|
||||
configuration: vscode.DebugConfiguration;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = configs.map<MenuItem>(config => {
|
||||
let menuItem: MenuItem = {label: config.name, configuration: config};
|
||||
// Rename the menu item for the default configuration as its name is non-descriptive.
|
||||
if (isDebugLaunchStr(menuItem.label)) {
|
||||
menuItem.label = "Default Configuration";
|
||||
}
|
||||
return menuItem;
|
||||
});
|
||||
|
||||
const selection: MenuItem = await vscode.window.showQuickPick(items, {placeHolder: "Select a configuration"});
|
||||
if (!selection) {
|
||||
throw new Error(); // User canceled it.
|
||||
}
|
||||
if (selection.label.startsWith("cl.exe")) {
|
||||
if (!process.env.DevEnvDir || process.env.DevEnvDir.length === 0) {
|
||||
vscode.window.showErrorMessage('cl.exe build and debug is only usable when VS Code is run from the Developer Command Prompt for VS.');
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
if (selection.label.indexOf(buildAndDebugActiveFileStr()) !== -1 && selection.configuration.preLaunchTask) {
|
||||
try {
|
||||
await util.ensureBuildTaskExists(selection.configuration.preLaunchTask);
|
||||
await vscode.debug.startDebugging(folder, selection.configuration);
|
||||
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "true" });
|
||||
} catch (e) {
|
||||
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" });
|
||||
}
|
||||
}
|
||||
return [selection.configuration];
|
||||
}
|
||||
|
||||
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
|
||||
return this.underlyingProvider.resolveDebugConfiguration(folder, config, token);
|
||||
}
|
||||
}
|
||||
|
||||
class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
|
||||
private type: DebuggerType;
|
||||
private provider: IConfigurationAssetProvider;
|
||||
|
||||
@@ -23,8 +95,85 @@ abstract class CppConfigurationProvider implements vscode.DebugConfigurationProv
|
||||
/**
|
||||
* Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder.
|
||||
*/
|
||||
provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration[]> {
|
||||
return this.provider.getInitialConfigurations(this.type);
|
||||
async provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration[]> {
|
||||
let buildTasks: vscode.Task[] = await getBuildTasks(true);
|
||||
if (buildTasks.length === 0) {
|
||||
return Promise.resolve(this.provider.getInitialConfigurations(this.type));
|
||||
}
|
||||
const defaultConfig: vscode.DebugConfiguration = this.provider.getInitialConfigurations(this.type).find(config => {
|
||||
return isDebugLaunchStr(config.name);
|
||||
});
|
||||
console.assert(defaultConfig, "Could not find default debug configuration.");
|
||||
|
||||
const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation();
|
||||
const platform: string = platformInfo.platform;
|
||||
|
||||
// Filter out build tasks that don't match the currently selectede debug configuration type.
|
||||
buildTasks = buildTasks.filter((task: vscode.Task) => {
|
||||
if (defaultConfig.name === "(Windows) Launch") {
|
||||
if (task.name.startsWith("cl.exe")) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!task.name.startsWith("cl.exe")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Generate new configurations for each build task.
|
||||
// Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve.
|
||||
let configs: vscode.DebugConfiguration[] = await Promise.all(buildTasks.map<Promise<vscode.DebugConfiguration>>(async task => {
|
||||
const definition: BuildTaskDefinition = task.definition as BuildTaskDefinition;
|
||||
const compilerName: string = path.basename(definition.compilerPath);
|
||||
|
||||
let newConfig: vscode.DebugConfiguration = Object.assign({}, defaultConfig); // Copy enumerables and properties
|
||||
|
||||
newConfig.name = compilerName + buildAndDebugActiveFileStr();
|
||||
newConfig.preLaunchTask = task.name;
|
||||
newConfig.externalConsole = false;
|
||||
const exeName: string = path.join("${fileDirname}", "${fileBasenameNoExtension}");
|
||||
newConfig.program = platform === "win32" ? exeName + ".exe" : exeName;
|
||||
|
||||
return new Promise<vscode.DebugConfiguration>(resolve => {
|
||||
if (platform === "darwin") {
|
||||
return resolve(newConfig);
|
||||
} else {
|
||||
let debuggerName: string;
|
||||
if (compilerName.startsWith("clang")) {
|
||||
newConfig.MIMode = "lldb";
|
||||
const suffixIndex: number = compilerName.indexOf("-");
|
||||
const suffix: string = suffixIndex === -1 ? "" : compilerName.substr(suffixIndex);
|
||||
debuggerName = "lldb-mi" + suffix;
|
||||
} else if (compilerName === "cl.exe") {
|
||||
newConfig.miDebuggerPath = undefined;
|
||||
newConfig.type = "cppvsdbg";
|
||||
return resolve(newConfig);
|
||||
} else {
|
||||
debuggerName = "gdb";
|
||||
}
|
||||
|
||||
if (platform === "win32") {
|
||||
debuggerName += ".exe";
|
||||
}
|
||||
|
||||
const compilerDirname: string = path.dirname(definition.compilerPath);
|
||||
const debuggerPath: string = path.join(compilerDirname, debuggerName);
|
||||
fs.stat(debuggerPath, (err, stats: fs.Stats) => {
|
||||
if (!err && stats && stats.isFile) {
|
||||
newConfig.miDebuggerPath = debuggerPath;
|
||||
} else {
|
||||
// TODO should probably resolve a missing debugger in a more graceful fashion for win32.
|
||||
newConfig.miDebuggerPath = path.join("/usr", "bin", debuggerName);
|
||||
}
|
||||
return resolve(newConfig);
|
||||
});
|
||||
}
|
||||
});
|
||||
}));
|
||||
configs.push(defaultConfig);
|
||||
return configs;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,12 +181,30 @@ abstract class CppConfigurationProvider implements vscode.DebugConfigurationProv
|
||||
*/
|
||||
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
|
||||
if (config) {
|
||||
// Fail if cppvsdbg type is running on non-Windows
|
||||
if (config.type === 'cppvsdbg' && os.platform() !== 'win32') {
|
||||
vscode.window.showErrorMessage("Debugger of type: 'cppvsdbg' is only available on Windows. Use type: 'cppdbg' on the current OS platform.");
|
||||
return undefined;
|
||||
if (config.type === 'cppvsdbg') {
|
||||
// Fail if cppvsdbg type is running on non-Windows
|
||||
if (os.platform() !== 'win32') {
|
||||
logger.getOutputChannelLogger().showWarningMessage("Debugger of type: 'cppvsdbg' is only available on Windows. Use type: 'cppdbg' on the current OS platform.");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Disable debug heap by default, enable if 'enableDebugHeap' is set.
|
||||
if (!config.enableDebugHeap) {
|
||||
const disableDebugHeapEnvSetting : Environment = {"name" : "_NO_DEBUG_HEAP", "value" : "1"};
|
||||
|
||||
if (config.environment && util.isArray(config.environment)) {
|
||||
config.environment.push(disableDebugHeapEnvSetting);
|
||||
} else {
|
||||
config.environment = [disableDebugHeapEnvSetting];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add environment variables from .env file
|
||||
this.resolveEnvFile(config, folder);
|
||||
|
||||
this.resolveSourceFileMapVariables(config);
|
||||
|
||||
// Modify WSL config for OpenDebugAD7
|
||||
if (os.platform() === 'win32' &&
|
||||
config.pipeTransport &&
|
||||
@@ -64,6 +231,87 @@ abstract class CppConfigurationProvider implements vscode.DebugConfigurationProv
|
||||
// if config or type is not specified, return null to trigger VS Code to open a configuration file https://github.com/Microsoft/vscode/issues/54213
|
||||
return config && config.type ? config : null;
|
||||
}
|
||||
|
||||
private resolveEnvFile(config: vscode.DebugConfiguration, folder: vscode.WorkspaceFolder): void {
|
||||
if (config.envFile) {
|
||||
// replace ${env:???} variables
|
||||
let envFilePath: string = util.resolveVariables(config.envFile, null);
|
||||
|
||||
try {
|
||||
if (folder && folder.uri && folder.uri.fsPath) {
|
||||
// Try to replace ${workspaceFolder} or ${workspaceRoot}
|
||||
envFilePath = envFilePath.replace(/(\${workspaceFolder}|\${workspaceRoot})/g, folder.uri.fsPath);
|
||||
}
|
||||
|
||||
const parsedFile: ParsedEnvironmentFile = ParsedEnvironmentFile.CreateFromFile(envFilePath, config["environment"]);
|
||||
|
||||
// show error message if single lines cannot get parsed
|
||||
if (parsedFile.Warning) {
|
||||
CppConfigurationProvider.showFileWarningAsync(parsedFile.Warning, config.envFile);
|
||||
}
|
||||
|
||||
config.environment = parsedFile.Env;
|
||||
|
||||
delete config.envFile;
|
||||
} catch (e) {
|
||||
throw new Error(`Failed to use envFile. Reason: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resolveSourceFileMapVariables(config: vscode.DebugConfiguration): void {
|
||||
let messages: string[] = [];
|
||||
if (config.sourceFileMap) {
|
||||
for (const sourceFileMapSource of Object.keys(config.sourceFileMap)) {
|
||||
let message: string = "";
|
||||
const sourceFileMapTarget: string = config.sourceFileMap[sourceFileMapSource];
|
||||
|
||||
// TODO: pass config.environment as 'additionalEnvironment' to resolveVariables when it is { key: value } instead of { "key": key, "value": value }
|
||||
const newSourceFileMapSource: string = util.resolveVariables(sourceFileMapSource, null);
|
||||
const newSourceFileMapTarget: string = util.resolveVariables(sourceFileMapTarget, null);
|
||||
|
||||
let source: string = sourceFileMapSource;
|
||||
let target: string = sourceFileMapTarget;
|
||||
|
||||
if (sourceFileMapSource !== newSourceFileMapSource) {
|
||||
message = `\tReplacing sourcePath '${sourceFileMapSource}' with '${newSourceFileMapSource}'.`;
|
||||
delete config.sourceFileMap[sourceFileMapSource];
|
||||
source = newSourceFileMapSource;
|
||||
}
|
||||
|
||||
if (sourceFileMapTarget !== newSourceFileMapTarget) {
|
||||
// Add a space if source was changed, else just tab the target message.
|
||||
message += (message ? ' ' : '\t');
|
||||
message += `Replacing targetPath '${sourceFileMapTarget}' with '${newSourceFileMapTarget}'.`;
|
||||
target = newSourceFileMapTarget;
|
||||
}
|
||||
|
||||
if (message) {
|
||||
config.sourceFileMap[source] = target;
|
||||
messages.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
if (messages.length > 0) {
|
||||
logger.getOutputChannel().appendLine("Resolving variables in sourceFileMap...");
|
||||
messages.forEach((message) => {
|
||||
logger.getOutputChannel().appendLine(message);
|
||||
});
|
||||
logger.showOutputChannel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async showFileWarningAsync(message: string, fileName: string) : Promise<void> {
|
||||
const openItem: vscode.MessageItem = { title: 'Open envFile' };
|
||||
let result: vscode.MessageItem = await vscode.window.showWarningMessage(message, openItem);
|
||||
if (result && result.title === openItem.title) {
|
||||
let doc: vscode.TextDocument = await vscode.workspace.openTextDocument(fileName);
|
||||
if (doc) {
|
||||
vscode.window.showTextDocument(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class CppVsDbgConfigurationProvider extends CppConfigurationProvider {
|
||||
|
||||
@@ -40,7 +40,7 @@ function createLaunchString(name: string, type: string, executable: string): str
|
||||
"stopAtEntry": false,
|
||||
"cwd": "$\{workspaceFolder\}",
|
||||
"environment": [],
|
||||
"externalConsole": true
|
||||
"externalConsole": false
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as vscode from "vscode";
|
||||
import * as util from '../common';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
|
||||
// Registers DebugAdapterDescriptorFactory for `cppdbg` and `cppvsdbg`. If it is not ready, it will prompt a wait for the download dialog.
|
||||
// NOTE: This file is not automatically tested.
|
||||
|
||||
abstract class AbstractDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
|
||||
protected readonly context: vscode.ExtensionContext;
|
||||
|
||||
// This is important for the Mock Debugger since it can not use src/common
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
abstract createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor>;
|
||||
}
|
||||
|
||||
export class CppdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDescriptorFactory {
|
||||
public static DEBUG_TYPE : string = "cppdbg";
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
return util.isExtensionReady().then(ready => {
|
||||
if (ready) {
|
||||
let command: string = path.join(this.context.extensionPath, './debugAdapters/OpenDebugAD7');
|
||||
|
||||
// Windows has the exe in debugAdapters/bin.
|
||||
if (os.platform() === 'win32') {
|
||||
command = path.join(this.context.extensionPath, "./debugAdapters/bin/OpenDebugAD7.exe");
|
||||
}
|
||||
|
||||
return new vscode.DebugAdapterExecutable(command, []);
|
||||
} else {
|
||||
throw new Error(util.extensionNotReadyString);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class CppvsdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDescriptorFactory {
|
||||
public static DEBUG_TYPE : string = "cppvsdbg";
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
if (os.platform() !== 'win32') {
|
||||
vscode.window.showErrorMessage("Debugger type 'cppvsdbg' is not avaliable for non-Windows machines.");
|
||||
return null;
|
||||
} else {
|
||||
return util.isExtensionReady().then(ready => {
|
||||
if (ready) {
|
||||
return new vscode.DebugAdapterExecutable(
|
||||
path.join(this.context.extensionPath, './debugAdapters/vsdbg/bin/vsdbg.exe'),
|
||||
['--interpreter=vscode']
|
||||
);
|
||||
} else {
|
||||
throw new Error(util.extensionNotReadyString);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,14 +7,19 @@ import * as vscode from 'vscode';
|
||||
import * as os from 'os';
|
||||
import { AttachPicker, RemoteAttachPicker, AttachItemsProvider } from './attachToProcess';
|
||||
import { NativeAttachItemsProviderFactory } from './nativeAttach';
|
||||
import { ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider';
|
||||
import { QuickPickConfigurationProvider, ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider';
|
||||
import { CppdbgDebugAdapterDescriptorFactory, CppvsdbgDebugAdapterDescriptorFactory } from './debugAdapterDescriptorFactory';
|
||||
import * as util from '../common';
|
||||
import * as path from 'path';
|
||||
import * as Telemetry from '../telemetry';
|
||||
|
||||
// The extension deactivate method is asynchronous, so we handle the disposables ourselves instead of using extensonContext.subscriptions.
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
export function initialize(): void {
|
||||
export function buildAndDebugActiveFileStr(): string {
|
||||
return " build and debug active file";
|
||||
}
|
||||
|
||||
export function initialize(context: vscode.ExtensionContext): void {
|
||||
// Activate Process Picker Commands
|
||||
let attachItemsProvider: AttachItemsProvider = NativeAttachItemsProviderFactory.Get();
|
||||
let attacher: AttachPicker = new AttachPicker(attachItemsProvider);
|
||||
@@ -26,10 +31,94 @@ export function initialize(): void {
|
||||
let configurationProvider: IConfigurationAssetProvider = ConfigurationAssetProviderFactory.getConfigurationProvider();
|
||||
// On non-windows platforms, the cppvsdbg debugger will not be registered for initial configurations.
|
||||
// This will cause it to not show up on the dropdown list.
|
||||
let vsdbgProvider: CppVsDbgConfigurationProvider = null;
|
||||
if (os.platform() === 'win32') {
|
||||
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppvsdbg', new CppVsDbgConfigurationProvider(configurationProvider)));
|
||||
vsdbgProvider = new CppVsDbgConfigurationProvider(configurationProvider);
|
||||
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppvsdbg', new QuickPickConfigurationProvider(vsdbgProvider)));
|
||||
}
|
||||
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppdbg', new CppDbgConfigurationProvider(configurationProvider)));
|
||||
const provider: CppDbgConfigurationProvider = new CppDbgConfigurationProvider(configurationProvider);
|
||||
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppdbg', new QuickPickConfigurationProvider(provider)));
|
||||
|
||||
disposables.push(vscode.commands.registerTextEditorCommand("C_Cpp.BuildAndDebugActiveFile", async (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => {
|
||||
const folder: vscode.WorkspaceFolder = vscode.workspace.getWorkspaceFolder(textEditor.document.uri);
|
||||
if (!folder) {
|
||||
// Not enabled because we do not react to single-file mode correctly yet.
|
||||
// We get an ENOENT when the user's c_cpp_properties.json is attempted to be parsed.
|
||||
// The DefaultClient will also have its configuration accessed, but since it doesn't exist it errors out.
|
||||
vscode.window.showErrorMessage('This command is not yet available for single-file mode.');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (!util.fileIsCOrCppSource(textEditor.document.uri.fsPath)) {
|
||||
vscode.window.showErrorMessage('Cannot build and debug because the active file is not a C or C++ source file.');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let configs: vscode.DebugConfiguration[] = (await provider.provideDebugConfigurations(folder)).filter(config => {
|
||||
return config.name.indexOf(buildAndDebugActiveFileStr()) !== -1;
|
||||
});
|
||||
|
||||
if (vsdbgProvider) {
|
||||
let vsdbgConfigs: vscode.DebugConfiguration[] = (await vsdbgProvider.provideDebugConfigurations(folder)).filter(config => {
|
||||
return config.name.indexOf(buildAndDebugActiveFileStr()) !== -1;
|
||||
});
|
||||
if (vsdbgConfigs) {
|
||||
configs.push(...vsdbgConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
interface MenuItem extends vscode.QuickPickItem {
|
||||
configuration: vscode.DebugConfiguration;
|
||||
}
|
||||
|
||||
const items: MenuItem[] = configs.map<MenuItem>(config => {
|
||||
return {label: config.name, configuration: config};
|
||||
});
|
||||
|
||||
vscode.window.showQuickPick(items, {placeHolder: (items.length === 0 ? "No compiler found" : "Select a compiler" )}).then(async selection => {
|
||||
if (!selection) {
|
||||
return; // User canceled it.
|
||||
}
|
||||
if (selection.label.startsWith("cl.exe")) {
|
||||
if (!process.env.DevEnvDir || process.env.DevEnvDir.length === 0) {
|
||||
vscode.window.showErrorMessage('cl.exe build and debug is only usable when VS Code is run from the Developer Command Prompt for VS.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (selection.configuration.preLaunchTask) {
|
||||
if (folder) {
|
||||
try {
|
||||
await util.ensureBuildTaskExists(selection.configuration.preLaunchTask);
|
||||
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" });
|
||||
} catch (e) {
|
||||
if (e && e.message === util.failedToParseTasksJson) {
|
||||
vscode.window.showErrorMessage(util.failedToParseTasksJson);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
// TODO uncomment this when single file mode works correctly.
|
||||
// const buildTasks: vscode.Task[] = await getBuildTasks(true);
|
||||
// const task: vscode.Task = buildTasks.find(task => task.name === selection.configuration.preLaunchTask);
|
||||
// await vscode.tasks.executeTask(task);
|
||||
// delete selection.configuration.preLaunchTask;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to use the user's (possibly) modified configuration before using the generated one.
|
||||
try {
|
||||
await vscode.debug.startDebugging(folder, selection.configuration.name);
|
||||
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "true" });
|
||||
} catch (e) {
|
||||
try {
|
||||
vscode.debug.startDebugging(folder, selection.configuration);
|
||||
} catch (e) {
|
||||
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" });
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
configurationProvider.getConfigurationSnippets();
|
||||
|
||||
@@ -38,57 +127,17 @@ export function initialize(): void {
|
||||
language: 'jsonc',
|
||||
pattern: '**/launch.json'
|
||||
}];
|
||||
|
||||
// ConfigurationSnippetProvider needs to be initiallized after configurationProvider calls getConfigurationSnippets.
|
||||
disposables.push(vscode.languages.registerCompletionItemProvider(launchJsonDocumentSelector, new ConfigurationSnippetProvider(configurationProvider)));
|
||||
|
||||
// Activate Adapter Commands
|
||||
registerAdapterExecutableCommands();
|
||||
// Register Debug Adapters
|
||||
disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory(CppvsdbgDebugAdapterDescriptorFactory.DEBUG_TYPE, new CppvsdbgDebugAdapterDescriptorFactory(context)));
|
||||
disposables.push(vscode.debug.registerDebugAdapterDescriptorFactory(CppdbgDebugAdapterDescriptorFactory.DEBUG_TYPE, new CppdbgDebugAdapterDescriptorFactory(context)));
|
||||
|
||||
vscode.Disposable.from(...disposables);
|
||||
}
|
||||
|
||||
export function dispose(): void {
|
||||
disposables.forEach(d => d.dispose());
|
||||
}
|
||||
|
||||
// Registers adapterExecutableCommands for cppdbg and cppvsdbg. If it is not ready, it will prompt waiting for the download.
|
||||
//
|
||||
// Note: util.extensionContext.extensionPath is needed for the commands because VsCode does not support relative paths for adapterExecutableComand
|
||||
function registerAdapterExecutableCommands(): void {
|
||||
disposables.push(vscode.commands.registerCommand('extension.cppdbgAdapterExecutableCommand', () => {
|
||||
return util.isExtensionReady().then(ready => {
|
||||
if (ready) {
|
||||
let command: string = path.join(util.extensionContext.extensionPath, './debugAdapters/OpenDebugAD7');
|
||||
|
||||
// Windows has the exe in debugAdapters/bin.
|
||||
if (os.platform() === 'win32') {
|
||||
command = path.join(util.extensionContext.extensionPath, "./debugAdapters/bin/OpenDebugAD7.exe");
|
||||
}
|
||||
|
||||
return {
|
||||
command: command
|
||||
};
|
||||
} else {
|
||||
throw new Error(util.extensionNotReadyString);
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
disposables.push(vscode.commands.registerCommand('extension.cppvsdbgAdapterExecutableCommand', () => {
|
||||
if (os.platform() !== 'win32') {
|
||||
vscode.window.showErrorMessage("Debugger type 'cppvsdbg' is not avaliable for non-Windows machines.");
|
||||
return null;
|
||||
} else {
|
||||
return util.isExtensionReady().then(ready => {
|
||||
if (ready) {
|
||||
return {
|
||||
command: path.join(util.extensionContext.extensionPath, './debugAdapters/vsdbg/bin/vsdbg.exe'),
|
||||
args: ['--interpreter=vscode']
|
||||
};
|
||||
} else {
|
||||
throw new Error(util.extensionNotReadyString);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -23,15 +23,18 @@ import { createProtocolFilter } from './protocolFilter';
|
||||
import { DataBinding } from './dataBinding';
|
||||
import minimatch = require("minimatch");
|
||||
import * as logger from '../logger';
|
||||
import { updateLanguageConfigurations } from './extension';
|
||||
import { updateLanguageConfigurations, registerCommands } from './extension';
|
||||
import { CancellationTokenSource } from 'vscode';
|
||||
import { SettingsTracker, getTracker } from './settingsTracker';
|
||||
import { getTestHook, TestHook } from '../testHook';
|
||||
import { getCustomConfigProviders, CustomConfigurationProviderCollection, CustomConfigurationProvider1 } from '../LanguageServer/customProviders';
|
||||
import { ABTestSettings, getABTestSettings } from '../abTesting';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import { TokenKind, ColorizationSettings, ColorizationState } from './colorization';
|
||||
|
||||
let ui: UI;
|
||||
let timeStamp: number = 0;
|
||||
const configProviderTimeout: number = 2000;
|
||||
|
||||
interface NavigationPayload {
|
||||
@@ -79,9 +82,11 @@ interface OutputNotificationBody {
|
||||
output: string;
|
||||
}
|
||||
|
||||
interface InactiveRegionParams {
|
||||
interface SemanticColorizationRegionsParams {
|
||||
uri: string;
|
||||
regions: InputRegion[];
|
||||
regions: InputColorizationRegion[];
|
||||
inactiveRegions: InputRegion[];
|
||||
editVersion: number;
|
||||
}
|
||||
|
||||
interface InputRegion {
|
||||
@@ -89,9 +94,9 @@ interface InputRegion {
|
||||
endLine: number;
|
||||
}
|
||||
|
||||
interface DecorationRangesPair {
|
||||
decoration: vscode.TextEditorDecorationType;
|
||||
ranges: vscode.Range[];
|
||||
interface InputColorizationRegion {
|
||||
range: Range;
|
||||
kind: number;
|
||||
}
|
||||
|
||||
// Need to convert vscode.Uri to a string before sending it to the language server.
|
||||
@@ -112,11 +117,57 @@ interface CompileCommandsPaths {
|
||||
paths: string[];
|
||||
}
|
||||
|
||||
interface QueryTranslationUnitSourceParams {
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export enum QueryTranslationUnitSourceConfigDisposition {
|
||||
|
||||
/**
|
||||
* No custom config needed for this file
|
||||
*/
|
||||
ConfigNotNeeded = 0,
|
||||
|
||||
/**
|
||||
* Custom config is needed for this file
|
||||
*/
|
||||
ConfigNeeded = 1,
|
||||
|
||||
/**
|
||||
* Custom config is needed for the ancestor file returned in uri
|
||||
*/
|
||||
AncestorConfigNeeded = 2
|
||||
}
|
||||
|
||||
interface QueryTranslationUnitSourceResult {
|
||||
uri: string;
|
||||
configDisposition: QueryTranslationUnitSourceConfigDisposition;
|
||||
}
|
||||
|
||||
interface GetDiagnosticsResult {
|
||||
diagnostics: string;
|
||||
}
|
||||
|
||||
interface DidChangeVisibleRangesParams {
|
||||
uri: string;
|
||||
ranges: Range[];
|
||||
}
|
||||
|
||||
interface SemanticColorizationRegionsReceiptParams {
|
||||
uri: string;
|
||||
}
|
||||
|
||||
interface ColorThemeChangedParams {
|
||||
name: string;
|
||||
}
|
||||
|
||||
// Requests
|
||||
const NavigationListRequest: RequestType<TextDocumentIdentifier, string, void, void> = new RequestType<TextDocumentIdentifier, string, void, void>('cpptools/requestNavigationList');
|
||||
const GoToDeclarationRequest: RequestType<void, void, void, void> = new RequestType<void, void, void, void>('cpptools/goToDeclaration');
|
||||
const QueryCompilerDefaultsRequest: RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void> = new RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void>('cpptools/queryCompilerDefaults');
|
||||
const QueryTranslationUnitSourceRequest: RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void, void> = new RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void, void>('cpptools/queryTranslationUnitSource');
|
||||
const SwitchHeaderSourceRequest: RequestType<SwitchHeaderSourceParams, string, void, void> = new RequestType<SwitchHeaderSourceParams, string, void, void>('cpptools/didSwitchHeaderSource');
|
||||
const GetDiagnosticsRequest: RequestType<void, GetDiagnosticsResult, void, void> = new RequestType<void, GetDiagnosticsResult, void, void>('cpptools/getDiagnostics');
|
||||
|
||||
// Notifications to the server
|
||||
const DidOpenNotification: NotificationType<DidOpenTextDocumentParams, void> = new NotificationType<DidOpenTextDocumentParams, void>('textDocument/didOpen');
|
||||
@@ -134,6 +185,10 @@ const IntervalTimerNotification: NotificationType<void, void> = new Notification
|
||||
const CustomConfigurationNotification: NotificationType<CustomConfigurationParams, void> = new NotificationType<CustomConfigurationParams, void>('cpptools/didChangeCustomConfiguration');
|
||||
const CustomBrowseConfigurationNotification: NotificationType<CustomBrowseConfigurationParams, void> = new NotificationType<CustomBrowseConfigurationParams, void>('cpptools/didChangeCustomBrowseConfiguration');
|
||||
const ClearCustomConfigurationsNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/clearCustomConfigurations');
|
||||
const RescanFolderNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/rescanFolder');
|
||||
const DidChangeVisibleRangesNotification: NotificationType<DidChangeVisibleRangesParams, void> = new NotificationType<DidChangeVisibleRangesParams, void>('cpptools/didChangeVisibleRanges');
|
||||
const SemanticColorizationRegionsReceiptNotification: NotificationType<SemanticColorizationRegionsReceiptParams, void> = new NotificationType<SemanticColorizationRegionsReceiptParams, void>('cpptools/semanticColorizationRegionsReceipt');
|
||||
const ColorThemeChangedNotification: NotificationType<ColorThemeChangedParams, void> = new NotificationType<ColorThemeChangedParams, void>('cpptools/colorThemeChanged');
|
||||
|
||||
// Notifications from the server
|
||||
const ReloadWindowNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/reloadWindow');
|
||||
@@ -143,37 +198,10 @@ const ReportTagParseStatusNotification: NotificationType<ReportStatusNotificatio
|
||||
const ReportStatusNotification: NotificationType<ReportStatusNotificationBody, void> = new NotificationType<ReportStatusNotificationBody, void>('cpptools/reportStatus');
|
||||
const DebugProtocolNotification: NotificationType<OutputNotificationBody, void> = new NotificationType<OutputNotificationBody, void>('cpptools/debugProtocol');
|
||||
const DebugLogNotification: NotificationType<OutputNotificationBody, void> = new NotificationType<OutputNotificationBody, void>('cpptools/debugLog');
|
||||
const InactiveRegionNotification: NotificationType<InactiveRegionParams, void> = new NotificationType<InactiveRegionParams, void>('cpptools/inactiveRegions');
|
||||
const SemanticColorizationRegionsNotification: NotificationType<SemanticColorizationRegionsParams, void> = new NotificationType<SemanticColorizationRegionsParams, void>('cpptools/semanticColorizationRegions');
|
||||
const CompileCommandsPathsNotification: NotificationType<CompileCommandsPaths, void> = new NotificationType<CompileCommandsPaths, void>('cpptools/compileCommandsPaths');
|
||||
const UpdateClangFormatPathNotification: NotificationType<string, void> = new NotificationType<string, void>('cpptools/updateClangFormatPath');
|
||||
|
||||
class BlockingTask<T> {
|
||||
private dependency: BlockingTask<any>;
|
||||
private done: boolean = false;
|
||||
private promise: Promise<T>;
|
||||
|
||||
constructor(task: () => T, dependency?: BlockingTask<any>) {
|
||||
this.promise = new Promise<T>(async (resolve, reject) => {
|
||||
try {
|
||||
let result: T = await task();
|
||||
resolve(result);
|
||||
this.done = true;
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
this.done = true;
|
||||
}
|
||||
});
|
||||
this.dependency = dependency;
|
||||
}
|
||||
|
||||
public get Done(): boolean {
|
||||
return this.done && (!this.dependency || this.dependency.Done);
|
||||
}
|
||||
|
||||
public then(onSucceeded: (value: T) => any, onRejected: (err) => any): Promise<any> {
|
||||
return this.promise.then(onSucceeded, onRejected);
|
||||
}
|
||||
}
|
||||
const UpdateIntelliSenseCachePathNotification: NotificationType<string, void> = new NotificationType<string, void>('cpptools/updateIntelliSenseCachePath');
|
||||
|
||||
let failureMessageShown: boolean = false;
|
||||
|
||||
@@ -195,13 +223,20 @@ export interface Client {
|
||||
RootUri: vscode.Uri;
|
||||
Name: string;
|
||||
TrackedDocuments: Set<vscode.TextDocument>;
|
||||
onDidChangeSettings(): { [key: string] : string };
|
||||
onDidChangeSettings(event: vscode.ConfigurationChangeEvent): { [key: string] : string };
|
||||
onDidOpenTextDocument(document: vscode.TextDocument): void;
|
||||
onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void;
|
||||
onDidChangeTextDocument(textDocumentChangeEvent: vscode.TextDocumentChangeEvent): void;
|
||||
onDidChangeTextEditorVisibleRanges(textEditorVisibleRangesChangeEvent: vscode.TextEditorVisibleRangesChangeEvent): void;
|
||||
onRegisterCustomConfigurationProvider(provider: CustomConfigurationProvider1): Thenable<void>;
|
||||
updateCustomConfigurations(requestingProvider?: CustomConfigurationProvider1): Thenable<void>;
|
||||
updateCustomBrowseConfiguration(requestingProvider?: CustomConfigurationProvider1): Thenable<void>;
|
||||
provideCustomConfiguration(document: vscode.TextDocument): Promise<void>;
|
||||
logDiagnostics(): Promise<void>;
|
||||
rescanFolder(): Promise<void>;
|
||||
getCurrentConfigName(): Thenable<string>;
|
||||
getCompilerPath(): Thenable<string>;
|
||||
getKnownCompilers(): Thenable<configs.KnownCompiler[]>;
|
||||
takeOwnership(document: vscode.TextDocument): void;
|
||||
queueTask<T>(task: () => Thenable<T>): Thenable<T>;
|
||||
requestWhenReady(request: () => Thenable<any>): Thenable<any>;
|
||||
@@ -220,9 +255,12 @@ export interface Client {
|
||||
handleConfigurationProviderSelectCommand(): void;
|
||||
handleShowParsingCommands(): void;
|
||||
handleConfigurationEditCommand(): void;
|
||||
handleConfigurationEditJSONCommand(): void;
|
||||
handleConfigurationEditUICommand(): void;
|
||||
handleAddToIncludePathCommand(path: string): void;
|
||||
onInterval(): void;
|
||||
dispose(): Thenable<void>;
|
||||
addFileAssociations(fileAssociations: string, is_c: boolean): void;
|
||||
}
|
||||
|
||||
export function createClient(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder): Client {
|
||||
@@ -239,12 +277,16 @@ class DefaultClient implements Client {
|
||||
private configuration: configs.CppProperties;
|
||||
private rootPathFileWatcher: vscode.FileSystemWatcher;
|
||||
private rootFolder: vscode.WorkspaceFolder | undefined;
|
||||
private storagePath: string;
|
||||
private trackedDocuments = new Set<vscode.TextDocument>();
|
||||
private outputChannel: vscode.OutputChannel;
|
||||
private debugChannel: vscode.OutputChannel;
|
||||
private diagnosticsChannel: vscode.OutputChannel;
|
||||
private crashTimes: number[] = [];
|
||||
private isSupported: boolean = true;
|
||||
private inactiveRegionsDecorations = new Map<string, DecorationRangesPair>();
|
||||
private colorizationSettings: ColorizationSettings;
|
||||
private colorizationState = new Map<string, ColorizationState>();
|
||||
private visibleRanges = new Map<string, Range[]>();
|
||||
private settingsTracker: SettingsTracker;
|
||||
private configurationProvider: string;
|
||||
|
||||
@@ -280,7 +322,7 @@ class DefaultClient implements Client {
|
||||
}
|
||||
|
||||
private get AdditionalEnvironment(): { [key: string]: string | string[] } {
|
||||
return { workspaceFolderBasename: this.Name };
|
||||
return { workspaceFolderBasename: this.Name, workspaceStorage: this.storagePath };
|
||||
}
|
||||
|
||||
private getName(workspaceFolder?: vscode.WorkspaceFolder): string {
|
||||
@@ -294,15 +336,33 @@ class DefaultClient implements Client {
|
||||
* @see notifyWhenReady(notify)
|
||||
*/
|
||||
|
||||
private pendingTask: BlockingTask<void>;
|
||||
private pendingTask: util.BlockingTask<any>;
|
||||
|
||||
private getUniqueWorkspaceStorageName(workspaceFolder?: vscode.WorkspaceFolder) : string {
|
||||
let workspaceFolderName: string = this.getName(workspaceFolder);
|
||||
if (!workspaceFolder || workspaceFolder.index < 1) {
|
||||
return workspaceFolderName; // No duplicate names to search for.
|
||||
}
|
||||
for (let i: number = 0; i < workspaceFolder.index; ++i) {
|
||||
if (vscode.workspace.workspaceFolders[i].name === workspaceFolderName) {
|
||||
return path.join(workspaceFolderName, String(workspaceFolder.index)); // Use the index as a subfolder.
|
||||
}
|
||||
}
|
||||
return workspaceFolderName; // No duplicate names found.
|
||||
}
|
||||
|
||||
constructor(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder) {
|
||||
this.rootFolder = workspaceFolder;
|
||||
this.storagePath = util.extensionContext ? util.extensionContext.storagePath :
|
||||
path.join((this.rootFolder ? this.rootFolder.uri.fsPath : ""), "/.vscode");
|
||||
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
|
||||
this.storagePath = path.join(this.storagePath, this.getUniqueWorkspaceStorageName(this.rootFolder));
|
||||
}
|
||||
try {
|
||||
let languageClient: LanguageClient = this.createLanguageClient(allClients, workspaceFolder);
|
||||
let languageClient: LanguageClient = this.createLanguageClient(allClients);
|
||||
languageClient.registerProposedFeatures();
|
||||
languageClient.start(); // This returns Disposable, but doesn't need to be tracked because we call .stop() explicitly in our dispose()
|
||||
util.setProgress(util.getProgressExecutableStarted());
|
||||
this.rootFolder = workspaceFolder;
|
||||
ui = getUI();
|
||||
ui.bind(this);
|
||||
|
||||
@@ -315,12 +375,6 @@ class DefaultClient implements Client {
|
||||
this.configuration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
|
||||
this.disposables.push(this.configuration);
|
||||
|
||||
// The configurations will not be sent to the language server until the default include paths and frameworks have been set.
|
||||
// The event handlers must be set before this happens.
|
||||
languageClient.sendRequest(QueryCompilerDefaultsRequest, {}).then((compilerDefaults: configs.CompilerDefaults) => {
|
||||
this.configuration.CompilerDefaults = compilerDefaults;
|
||||
});
|
||||
|
||||
this.languageClient = languageClient;
|
||||
this.settingsTracker = getTracker(this.RootUri);
|
||||
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
|
||||
@@ -329,6 +383,16 @@ class DefaultClient implements Client {
|
||||
// Listen for messages from the language server.
|
||||
this.registerNotifications();
|
||||
this.registerFileWatcher();
|
||||
|
||||
// The configurations will not be sent to the language server until the default include paths and frameworks have been set.
|
||||
// The event handlers must be set before this happens.
|
||||
return languageClient.sendRequest(QueryCompilerDefaultsRequest, {}).then((compilerDefaults: configs.CompilerDefaults) => {
|
||||
this.configuration.CompilerDefaults = compilerDefaults;
|
||||
|
||||
// Only register the real commands after the extension has finished initializing,
|
||||
// e.g. prevents empty c_cpp_properties.json from generation.
|
||||
registerCommands();
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
this.isSupported = false; // Running on an OS we don't support yet.
|
||||
@@ -350,29 +414,35 @@ class DefaultClient implements Client {
|
||||
vscode.window.showErrorMessage("Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: " + additionalInfo);
|
||||
}
|
||||
}
|
||||
|
||||
this.colorizationSettings = new ColorizationSettings(this.RootUri);
|
||||
}
|
||||
|
||||
private createLanguageClient(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder): LanguageClient {
|
||||
private createLanguageClient(allClients: ClientCollection): LanguageClient {
|
||||
let serverModule: string = getLanguageServerFileName();
|
||||
let exeExists: boolean = fs.existsSync(serverModule);
|
||||
if (!exeExists) {
|
||||
telemetry.logLanguageServerEvent("missingLanguageServerBinary");
|
||||
throw String('Missing binary at ' + serverModule);
|
||||
}
|
||||
let serverName: string = this.getName(workspaceFolder);
|
||||
|
||||
let serverName: string = this.getName(this.rootFolder);
|
||||
let serverOptions: ServerOptions = {
|
||||
run: { command: serverModule },
|
||||
debug: { command: serverModule, args: [ serverName ] }
|
||||
};
|
||||
let settings: CppSettings = new CppSettings(workspaceFolder ? workspaceFolder.uri : null);
|
||||
let other: OtherSettings = new OtherSettings(workspaceFolder ? workspaceFolder.uri : null);
|
||||
|
||||
let storagePath: string = util.extensionContext.storagePath;
|
||||
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
|
||||
storagePath = path.join(storagePath, serverName);
|
||||
let settings: CppSettings = new CppSettings(this.rootFolder ? this.rootFolder.uri : null);
|
||||
let other: OtherSettings = new OtherSettings(this.rootFolder ? this.rootFolder.uri : null);
|
||||
let abTestSettings: ABTestSettings = getABTestSettings();
|
||||
|
||||
let intelliSenseCacheDisabled: boolean = false;
|
||||
if (os.platform() === "darwin") {
|
||||
const releaseParts: string[] = os.release().split(".");
|
||||
if (releaseParts.length >= 1) {
|
||||
// AutoPCH doesn't work for older Mac OS's.
|
||||
intelliSenseCacheDisabled = parseInt(releaseParts[0]) < 17;
|
||||
}
|
||||
}
|
||||
|
||||
let abTestSettings: ABTestSettings = getABTestSettings();
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
documentSelector: [
|
||||
{ scheme: 'file', language: 'cpp' },
|
||||
@@ -382,23 +452,28 @@ class DefaultClient implements Client {
|
||||
// Synchronize the setting section to the server
|
||||
configurationSection: ['C_Cpp', 'files', 'search']
|
||||
},
|
||||
workspaceFolder: workspaceFolder,
|
||||
workspaceFolder: this.rootFolder,
|
||||
initializationOptions: {
|
||||
clang_format_path: util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment),
|
||||
clang_format_style: settings.clangFormatStyle,
|
||||
clang_format_fallbackStyle: settings.clangFormatFallbackStyle,
|
||||
clang_format_sortIncludes: settings.clangFormatSortIncludes,
|
||||
formatting: settings.formatting,
|
||||
extension_path: util.extensionContext.extensionPath,
|
||||
extension_path: util.extensionPath,
|
||||
exclude_files: other.filesExclude,
|
||||
exclude_search: other.searchExclude,
|
||||
storage_path: storagePath,
|
||||
storage_path: this.storagePath,
|
||||
tab_size: other.editorTabSize,
|
||||
intelliSenseEngine: settings.intelliSenseEngine,
|
||||
intelliSenseEngineFallback: settings.intelliSenseEngineFallback,
|
||||
intelliSenseCacheDisabled: intelliSenseCacheDisabled,
|
||||
intelliSenseCachePath : util.resolveCachePath(settings.intelliSenseCachePath, this.AdditionalEnvironment),
|
||||
intelliSenseCacheSize : settings.intelliSenseCacheSize,
|
||||
autocomplete: settings.autoComplete,
|
||||
errorSquiggles: settings.errorSquiggles,
|
||||
dimInactiveRegions: settings.dimInactiveRegions,
|
||||
enhancedColorization: settings.enhancedColorization,
|
||||
suggestSnippets: settings.suggestSnippets,
|
||||
loggingLevel: settings.loggingLevel,
|
||||
workspaceParsingPriority: settings.workspaceParsingPriority,
|
||||
workspaceSymbols: settings.workspaceSymbols,
|
||||
@@ -444,9 +519,44 @@ class DefaultClient implements Client {
|
||||
return new LanguageClient(`cpptools: ${serverName}`, serverOptions, clientOptions);
|
||||
}
|
||||
|
||||
public onDidChangeSettings(): { [key: string] : string } {
|
||||
let changedSettings: { [key: string] : string } = this.settingsTracker.getChangedSettings();
|
||||
public onDidChangeSettings(event: vscode.ConfigurationChangeEvent): { [key: string] : string } {
|
||||
let colorizationNeedsReload: boolean = event.affectsConfiguration("workbench.colorTheme")
|
||||
|| event.affectsConfiguration("editor.tokenColorCustomizations");
|
||||
|
||||
let colorizationNeedsRefresh: boolean = colorizationNeedsReload
|
||||
|| event.affectsConfiguration("C_Cpp.enhancedColorization", this.RootUri)
|
||||
|| event.affectsConfiguration("C_Cpp.dimInactiveRegions", this.RootUri)
|
||||
|| event.affectsConfiguration("C_Cpp.inactiveRegionOpacity", this.RootUri)
|
||||
|| event.affectsConfiguration("C_Cpp.inactiveRegionForegroundColor", this.RootUri)
|
||||
|| event.affectsConfiguration("C_Cpp.inactiveRegionBackgroundColor", this.RootUri);
|
||||
|
||||
let colorThemeChanged: boolean = event.affectsConfiguration("workbench.colorTheme", this.RootUri);
|
||||
if (colorThemeChanged) {
|
||||
let otherSettings: OtherSettings = new OtherSettings(this.RootUri);
|
||||
this.languageClient.sendNotification(ColorThemeChangedNotification, { name: otherSettings.colorTheme } );
|
||||
}
|
||||
|
||||
if (colorizationNeedsReload) {
|
||||
this.colorizationSettings.reload();
|
||||
}
|
||||
if (colorizationNeedsRefresh) {
|
||||
let processedUris: vscode.Uri[] = [];
|
||||
for (let e of vscode.window.visibleTextEditors) {
|
||||
let uri: vscode.Uri = e.document.uri;
|
||||
|
||||
// Make sure we don't process the same file multiple times.
|
||||
// colorizationState.onSettingsChanged ensures all visible text editors for that file get
|
||||
// refreshed, after it creates a set of decorators to be shared by all visible instances of the file.
|
||||
if (!processedUris.find(e => e === uri)) {
|
||||
processedUris.push(uri);
|
||||
let colorizationState: ColorizationState = this.colorizationState.get(uri.toString());
|
||||
if (colorizationState) {
|
||||
colorizationState.onSettingsChanged(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let changedSettings: { [key: string] : string } = this.settingsTracker.getChangedSettings();
|
||||
if (Object.keys(changedSettings).length > 0) {
|
||||
if (changedSettings["commentContinuationPatterns"]) {
|
||||
updateLanguageConfigurations();
|
||||
@@ -455,26 +565,98 @@ class DefaultClient implements Client {
|
||||
let settings: CppSettings = new CppSettings(this.RootUri);
|
||||
this.languageClient.sendNotification(UpdateClangFormatPathNotification, util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment));
|
||||
}
|
||||
if (changedSettings["intelliSenseCachePath"]) {
|
||||
let settings: CppSettings = new CppSettings(this.RootUri);
|
||||
this.languageClient.sendNotification(UpdateIntelliSenseCachePathNotification, util.resolveCachePath(settings.intelliSenseCachePath, this.AdditionalEnvironment));
|
||||
}
|
||||
this.configuration.onDidChangeSettings();
|
||||
telemetry.logLanguageServerEvent("CppSettingsChange", changedSettings, null);
|
||||
}
|
||||
|
||||
return changedSettings;
|
||||
}
|
||||
|
||||
public onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
|
||||
let settings: CppSettings = new CppSettings(this.RootUri);
|
||||
if (settings.dimInactiveRegions) {
|
||||
//Apply text decorations to inactive regions
|
||||
for (let e of editors) {
|
||||
let valuePair: DecorationRangesPair = this.inactiveRegionsDecorations.get(e.document.uri.toString());
|
||||
if (valuePair) {
|
||||
e.setDecorations(valuePair.decoration, valuePair.ranges); // VSCode clears the decorations when the text editor becomes invisible
|
||||
private editVersion: number = 0;
|
||||
|
||||
public onDidChangeTextDocument(textDocumentChangeEvent: vscode.TextDocumentChangeEvent): void {
|
||||
// Increment editVersion for every call to onDidChangeTextDocument, regardless of whether the file is handled
|
||||
this.editVersion++;
|
||||
if (textDocumentChangeEvent.document.uri.scheme === "file") {
|
||||
if (textDocumentChangeEvent.document.languageId === "cpp" || textDocumentChangeEvent.document.languageId === "c") {
|
||||
try {
|
||||
let colorizationState: ColorizationState = this.getColorizationState(textDocumentChangeEvent.document.uri.toString());
|
||||
|
||||
// Adjust colorization ranges after this edit. (i.e. if a line was added, push decorations after it down one line)
|
||||
colorizationState.addEdits(textDocumentChangeEvent.contentChanges, this.editVersion);
|
||||
} catch (e) {
|
||||
// Ensure an exception does not prevent pass-through to native handler, or editVersion could become inconsistent
|
||||
console.log(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public onDidOpenTextDocument(document: vscode.TextDocument): void {
|
||||
if (document.uri.scheme === "file") {
|
||||
this.sendVisibleRanges(document.uri);
|
||||
}
|
||||
}
|
||||
|
||||
public onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
|
||||
let processedUris: vscode.Uri[] = [];
|
||||
editors.forEach(editor => {
|
||||
if (editor.document.uri.scheme === "file") {
|
||||
let colorizationState: ColorizationState = this.colorizationState.get(editor.document.uri.toString());
|
||||
if (colorizationState) {
|
||||
colorizationState.refresh(editor);
|
||||
}
|
||||
if (!processedUris.find(uri => uri === editor.document.uri)) {
|
||||
processedUris.push(editor.document.uri);
|
||||
this.sendVisibleRanges(editor.document.uri);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public sendVisibleRanges(uri: vscode.Uri): void {
|
||||
let ranges: Range[] = [];
|
||||
// Get ranges from all editors matching this URI
|
||||
let editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri === uri);
|
||||
for (let e of editors) {
|
||||
e.visibleRanges.forEach(range => ranges.push(Range.create(range.start.line, range.start.character, range.end.line, range.end.character)));
|
||||
}
|
||||
|
||||
// Only send ranges if they have actually changed.
|
||||
let isSame: boolean = false;
|
||||
let savedRanges: Range[] = this.visibleRanges.get(uri.toString());
|
||||
if (savedRanges) {
|
||||
if (ranges.length === savedRanges.length) {
|
||||
isSame = true;
|
||||
for (let i: number = 0; i < ranges.length; i++) {
|
||||
if (ranges[i] !== savedRanges[i]) {
|
||||
isSame = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isSame = ranges.length === 0;
|
||||
}
|
||||
if (!isSame) {
|
||||
this.visibleRanges.set(uri.toString(), ranges);
|
||||
let params: DidChangeVisibleRangesParams = {
|
||||
uri: uri.toString(),
|
||||
ranges: ranges
|
||||
};
|
||||
this.notifyWhenReady(() => this.languageClient.sendNotification(DidChangeVisibleRangesNotification, params));
|
||||
}
|
||||
}
|
||||
|
||||
public onDidChangeTextEditorVisibleRanges(textEditorVisibleRangesChangeEvent: vscode.TextEditorVisibleRangesChangeEvent): void {
|
||||
if (textEditorVisibleRangesChangeEvent.textEditor.document.uri.scheme === "file") {
|
||||
this.sendVisibleRanges(textEditorVisibleRangesChangeEvent.textEditor.document.uri);
|
||||
}
|
||||
}
|
||||
|
||||
public onRegisterCustomConfigurationProvider(provider: CustomConfigurationProvider1): Thenable<void> {
|
||||
let onRegistered: () => void = () => {
|
||||
// version 2 providers control the browse.path. Avoid thrashing the tag parser database by pausing parsing until
|
||||
@@ -582,6 +764,27 @@ class DefaultClient implements Client {
|
||||
});
|
||||
}
|
||||
|
||||
public async logDiagnostics(): Promise<void> {
|
||||
let response: GetDiagnosticsResult = await this.requestWhenReady(() => this.languageClient.sendRequest(GetDiagnosticsRequest, null));
|
||||
if (!this.diagnosticsChannel) {
|
||||
this.diagnosticsChannel = vscode.window.createOutputChannel("C/C++ Diagnostics");
|
||||
this.disposables.push(this.diagnosticsChannel);
|
||||
}
|
||||
|
||||
let header: string = `-------- Diagnostics - ${new Date().toLocaleString()}\n`;
|
||||
let version: string = `Version: ${util.packageJson.version}\n`;
|
||||
let configJson: string = "";
|
||||
if (this.configuration.CurrentConfiguration) {
|
||||
configJson = `Current Configuration:\n${JSON.stringify(this.configuration.CurrentConfiguration, null, 4)}\n`;
|
||||
}
|
||||
this.diagnosticsChannel.appendLine(`${header}${version}${configJson}${response.diagnostics}`);
|
||||
this.diagnosticsChannel.show(false);
|
||||
}
|
||||
|
||||
public async rescanFolder(): Promise<void> {
|
||||
await this.notifyWhenReady(() => this.languageClient.sendNotification(RescanFolderNotification));
|
||||
}
|
||||
|
||||
public async provideCustomConfiguration(document: vscode.TextDocument): Promise<void> {
|
||||
let tokenSource: CancellationTokenSource = new CancellationTokenSource();
|
||||
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
|
||||
@@ -595,6 +798,15 @@ class DefaultClient implements Client {
|
||||
}
|
||||
|
||||
let providerName: string = providerId;
|
||||
let params: QueryTranslationUnitSourceParams = {
|
||||
uri: document.uri.toString()
|
||||
};
|
||||
let response: QueryTranslationUnitSourceResult = await this.requestWhenReady(() => this.languageClient.sendRequest(QueryTranslationUnitSourceRequest, params));
|
||||
if (response.configDisposition === QueryTranslationUnitSourceConfigDisposition.ConfigNotNeeded) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let tuUri: vscode.Uri = vscode.Uri.parse(response.uri);
|
||||
let configName: string = await this.getCurrentConfigName();
|
||||
const notReadyMessage: string = `${providerName} is not ready`;
|
||||
let provideConfigurationAsync: () => Thenable<SourceFileConfigurationItem[]> = async () => {
|
||||
@@ -607,8 +819,8 @@ class DefaultClient implements Client {
|
||||
}
|
||||
|
||||
providerName = provider.name;
|
||||
if (await provider.canProvideConfiguration(document.uri, tokenSource.token)) {
|
||||
return provider.provideConfigurations([document.uri], tokenSource.token);
|
||||
if (await provider.canProvideConfiguration(tuUri, tokenSource.token)) {
|
||||
return provider.provideConfigurations([tuUri], tokenSource.token);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -621,6 +833,11 @@ class DefaultClient implements Client {
|
||||
(configs: SourceFileConfigurationItem[]) => {
|
||||
if (configs && configs.length > 0) {
|
||||
this.sendCustomConfigurations(configs, true);
|
||||
if (response.configDisposition === QueryTranslationUnitSourceConfigDisposition.AncestorConfigNeeded) {
|
||||
// replacing uri with original uri
|
||||
let newConfig: SourceFileConfigurationItem = { uri: document.uri, configuration: configs[0].configuration };
|
||||
this.sendCustomConfigurations([newConfig], true);
|
||||
}
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
@@ -628,7 +845,7 @@ class DefaultClient implements Client {
|
||||
return;
|
||||
}
|
||||
let settings: CppSettings = new CppSettings(this.RootUri);
|
||||
if (settings.configurationWarnings === "Enabled" && !this.isExternalHeader(document) && !vscode.debug.activeDebugSession) {
|
||||
if (settings.configurationWarnings === "Enabled" && !this.isExternalHeader(document.uri) && !vscode.debug.activeDebugSession) {
|
||||
const dismiss: string = "Dismiss";
|
||||
const disable: string = "Disable Warnings";
|
||||
let message: string = `'${providerName}' is unable to provide IntelliSense configuration information for '${document.uri.fsPath}'. ` +
|
||||
@@ -649,8 +866,8 @@ class DefaultClient implements Client {
|
||||
});
|
||||
}
|
||||
|
||||
private isExternalHeader(document: vscode.TextDocument): boolean {
|
||||
return util.isHeader(document) && !document.uri.toString().startsWith(this.RootUri.toString());
|
||||
private isExternalHeader(uri: vscode.Uri): boolean {
|
||||
return util.isHeader(uri) && !uri.toString().startsWith(this.RootUri.toString());
|
||||
}
|
||||
|
||||
private getCustomConfigurationProviderId(): Thenable<string|undefined> {
|
||||
@@ -661,6 +878,14 @@ class DefaultClient implements Client {
|
||||
return this.queueTask(() => Promise.resolve(this.configuration.CurrentConfiguration.name));
|
||||
}
|
||||
|
||||
public getCompilerPath(): Thenable<string> {
|
||||
return this.queueTask(() => Promise.resolve(this.configuration.CompilerPath));
|
||||
}
|
||||
|
||||
public getKnownCompilers(): Thenable<configs.KnownCompiler[]> {
|
||||
return this.queueTask(() => Promise.resolve(this.configuration.KnownCompiler));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take ownership of a document that was previously serviced by another client.
|
||||
* This process involves sending a textDocument/didOpen message to the server so
|
||||
@@ -715,7 +940,7 @@ class DefaultClient implements Client {
|
||||
*/
|
||||
private queueBlockingTask(task: () => Thenable<void>): Thenable<void> {
|
||||
if (this.isSupported) {
|
||||
this.pendingTask = new BlockingTask<void>(task, this.pendingTask);
|
||||
this.pendingTask = new util.BlockingTask<void>(task, this.pendingTask);
|
||||
} else {
|
||||
return Promise.reject("Unsupported client");
|
||||
}
|
||||
@@ -775,7 +1000,7 @@ class DefaultClient implements Client {
|
||||
this.languageClient.onNotification(ReportNavigationNotification, (e) => this.navigate(e));
|
||||
this.languageClient.onNotification(ReportStatusNotification, (e) => this.updateStatus(e));
|
||||
this.languageClient.onNotification(ReportTagParseStatusNotification, (e) => this.updateTagParseStatus(e));
|
||||
this.languageClient.onNotification(InactiveRegionNotification, (e) => this.updateInactiveRegions(e));
|
||||
this.languageClient.onNotification(SemanticColorizationRegionsNotification, (e) => this.updateSemanticColorizationRegions(e));
|
||||
this.languageClient.onNotification(CompileCommandsPathsNotification, (e) => this.promptCompileCommands(e));
|
||||
this.setupOutputHandlers();
|
||||
}
|
||||
@@ -850,7 +1075,11 @@ class DefaultClient implements Client {
|
||||
|
||||
// TODO: Move this code to a different place?
|
||||
if (cppSettings.autoAddFileAssociations && payload.navigation.startsWith("<def")) {
|
||||
this.addFileAssociations(payload.navigation.substr(4));
|
||||
let fileAssociations: string = payload.navigation.substr(4);
|
||||
let is_c: boolean = fileAssociations.startsWith("c");
|
||||
// Skip over rest of header: c>; or >;
|
||||
fileAssociations = fileAssociations.substr(is_c ? 3 : 2);
|
||||
this.addFileAssociations(fileAssociations, is_c);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -864,41 +1093,41 @@ class DefaultClient implements Client {
|
||||
this.model.navigationLocation.Value = currentNavigation;
|
||||
}
|
||||
|
||||
private addFileAssociations(fileAssociations: string): void {
|
||||
public addFileAssociations(fileAssociations: string, is_c: boolean): void {
|
||||
let settings: OtherSettings = new OtherSettings(this.RootUri);
|
||||
let assocs: any = settings.filesAssociations;
|
||||
let is_c: boolean = fileAssociations.startsWith("c");
|
||||
|
||||
// Skip over rest of header: c>; or >;
|
||||
fileAssociations = fileAssociations.substr(is_c ? 3 : 2);
|
||||
let filesAndPaths: string[] = fileAssociations.split(";");
|
||||
let foundNewAssociation: boolean = false;
|
||||
for (let i: number = 0; i < filesAndPaths.length - 1; ++i) {
|
||||
for (let i: number = 0; i < filesAndPaths.length; ++i) {
|
||||
let fileAndPath: string[] = filesAndPaths[i].split("@");
|
||||
let file: string = fileAndPath[0];
|
||||
let filePath: string = fileAndPath[1];
|
||||
if ((file in assocs) || (("**/" + file) in assocs)) {
|
||||
continue; // File already has an association.
|
||||
}
|
||||
let j: number = file.lastIndexOf('.');
|
||||
if (j !== -1) {
|
||||
let ext: string = file.substr(j);
|
||||
if ((("*" + ext) in assocs) || (("**/*" + ext) in assocs)) {
|
||||
continue; // Extension already has an association.
|
||||
// Skip empty or malformed
|
||||
if (fileAndPath.length === 2) {
|
||||
let file: string = fileAndPath[0];
|
||||
let filePath: string = fileAndPath[1];
|
||||
if ((file in assocs) || (("**/" + file) in assocs)) {
|
||||
continue; // File already has an association.
|
||||
}
|
||||
}
|
||||
let foundGlobMatch: boolean = false;
|
||||
for (let assoc in assocs) {
|
||||
if (minimatch(filePath, assoc)) {
|
||||
foundGlobMatch = true;
|
||||
break; // Assoc matched a glob pattern.
|
||||
let j: number = file.lastIndexOf('.');
|
||||
if (j !== -1) {
|
||||
let ext: string = file.substr(j);
|
||||
if ((("*" + ext) in assocs) || (("**/*" + ext) in assocs)) {
|
||||
continue; // Extension already has an association.
|
||||
}
|
||||
}
|
||||
let foundGlobMatch: boolean = false;
|
||||
for (let assoc in assocs) {
|
||||
if (minimatch(filePath, assoc)) {
|
||||
foundGlobMatch = true;
|
||||
break; // Assoc matched a glob pattern.
|
||||
}
|
||||
}
|
||||
if (foundGlobMatch) {
|
||||
continue;
|
||||
}
|
||||
assocs[file] = is_c ? "c" : "cpp";
|
||||
foundNewAssociation = true;
|
||||
}
|
||||
if (foundGlobMatch) {
|
||||
continue;
|
||||
}
|
||||
assocs[file] = is_c ? "c" : "cpp";
|
||||
foundNewAssociation = true;
|
||||
}
|
||||
if (foundNewAssociation) {
|
||||
settings.filesAssociations = assocs;
|
||||
@@ -913,9 +1142,16 @@ class DefaultClient implements Client {
|
||||
this.model.isTagParsing.Value = true;
|
||||
testHook.updateStatus(Status.TagParsingBegun);
|
||||
} else if (message.endsWith("Updating IntelliSense...")) {
|
||||
timeStamp = Date.now();
|
||||
this.model.isUpdatingIntelliSense.Value = true;
|
||||
testHook.updateStatus(Status.IntelliSenseCompiling);
|
||||
} else if (message.endsWith("IntelliSense Ready")) {
|
||||
let settings: CppSettings = new CppSettings(this.RootUri);
|
||||
if (settings.loggingLevel === "Debug") {
|
||||
let out: logger.Logger = logger.getOutputChannelLogger();
|
||||
let duration: number = Date.now() - timeStamp;
|
||||
out.appendLine(`Update IntelliSense time (sec): ${duration / 1000}`);
|
||||
}
|
||||
this.model.isUpdatingIntelliSense.Value = false;
|
||||
testHook.updateStatus(Status.IntelliSenseReady);
|
||||
} else if (message.endsWith("Ready")) { // Tag Parser Ready
|
||||
@@ -924,26 +1160,35 @@ class DefaultClient implements Client {
|
||||
util.setProgress(util.getProgressParseRootSuccess());
|
||||
} else if (message.endsWith("No Squiggles")) {
|
||||
util.setIntelliSenseProgress(util.getProgressIntelliSenseNoSquiggles());
|
||||
} else if (message.endsWith("IntelliSense Fallback")) {
|
||||
} else if (message.endsWith("Unresolved Headers")) {
|
||||
let showIntelliSenseFallbackMessage: PersistentState<boolean> = new PersistentState<boolean>("CPP.showIntelliSenseFallbackMessage", true);
|
||||
if (showIntelliSenseFallbackMessage.Value) {
|
||||
ui.showConfigureIncludePathMessage(() => {
|
||||
let learnMorePanel: string = "Configuration Help";
|
||||
let configJSON: string = "Configure (JSON)";
|
||||
let configUI: string = "Configure (UI)";
|
||||
let dontShowAgain: string = "Don't Show Again";
|
||||
let fallbackMsg: string = this.configuration.VcpkgInstalled ?
|
||||
"Update your IntelliSense settings or use Vcpkg to install libraries to help find missing headers." :
|
||||
"Configure your IntelliSense settings to help find missing headers.";
|
||||
return vscode.window.showInformationMessage(fallbackMsg, learnMorePanel, dontShowAgain).then((value) => {
|
||||
return vscode.window.showInformationMessage(fallbackMsg, configJSON, configUI, dontShowAgain).then((value) => {
|
||||
switch (value) {
|
||||
case learnMorePanel:
|
||||
let uri: vscode.Uri = vscode.Uri.parse(`https://go.microsoft.com/fwlink/?linkid=864631`);
|
||||
vscode.commands.executeCommand('vscode.open', uri);
|
||||
case configJSON:
|
||||
vscode.commands.getCommands(true).then((commands: string[]) => {
|
||||
if (commands.indexOf("workbench.action.problems.focus") >= 0) {
|
||||
vscode.commands.executeCommand("workbench.action.problems.focus");
|
||||
}
|
||||
});
|
||||
this.handleConfigurationEditCommand();
|
||||
this.handleConfigurationEditJSONCommand();
|
||||
telemetry.logLanguageServerEvent("SettingsCommand", { "toast": "json" }, null);
|
||||
break;
|
||||
case configUI:
|
||||
vscode.commands.getCommands(true).then((commands: string[]) => {
|
||||
if (commands.indexOf("workbench.action.problems.focus") >= 0) {
|
||||
vscode.commands.executeCommand("workbench.action.problems.focus");
|
||||
}
|
||||
});
|
||||
this.handleConfigurationEditUICommand();
|
||||
telemetry.logLanguageServerEvent("SettingsCommand", { "toast": "ui" }, null);
|
||||
break;
|
||||
case dontShowAgain:
|
||||
showIntelliSenseFallbackMessage.Value = false;
|
||||
@@ -961,47 +1206,33 @@ class DefaultClient implements Client {
|
||||
this.model.tagParserStatus.Value = notificationBody.status;
|
||||
}
|
||||
|
||||
private updateInactiveRegions(params: InactiveRegionParams): void {
|
||||
let settings: CppSettings = new CppSettings(this.RootUri);
|
||||
private getColorizationState(uri: string): ColorizationState {
|
||||
let colorizationState: ColorizationState = this.colorizationState.get(uri);
|
||||
if (!colorizationState) {
|
||||
colorizationState = new ColorizationState(this.RootUri, this.colorizationSettings);
|
||||
this.colorizationState.set(uri, colorizationState);
|
||||
}
|
||||
return colorizationState;
|
||||
}
|
||||
|
||||
let decoration: vscode.TextEditorDecorationType = vscode.window.createTextEditorDecorationType({
|
||||
opacity: settings.inactiveRegionOpacity.toString(),
|
||||
backgroundColor: settings.inactiveRegionBackgroundColor,
|
||||
color: settings.inactiveRegionForegroundColor,
|
||||
rangeBehavior: vscode.DecorationRangeBehavior.ClosedOpen
|
||||
});
|
||||
|
||||
// We must convert to vscode.Ranges in order to make use of the API's
|
||||
let ranges: vscode.Range[] = [];
|
||||
private updateSemanticColorizationRegions(params: SemanticColorizationRegionsParams): void {
|
||||
// Convert the params to vscode.Range's before passing to colorizationState.updateSemantic()
|
||||
let semanticRanges: vscode.Range[][] = new Array<vscode.Range[]>(TokenKind.Count);
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
semanticRanges[i] = [];
|
||||
}
|
||||
params.regions.forEach(element => {
|
||||
let newRange : vscode.Range = new vscode.Range(element.startLine, 0, element.endLine, 0);
|
||||
ranges.push(newRange);
|
||||
let newRange : vscode.Range = new vscode.Range(element.range.start.line, element.range.start.character, element.range.end.line, element.range.end.character);
|
||||
semanticRanges[element.kind].push(newRange);
|
||||
});
|
||||
|
||||
// Find entry for cached file and act accordingly
|
||||
let valuePair: DecorationRangesPair = this.inactiveRegionsDecorations.get(params.uri);
|
||||
if (valuePair) {
|
||||
// Disposing of and resetting the decoration will undo previously applied text decorations
|
||||
valuePair.decoration.dispose();
|
||||
valuePair.decoration = decoration;
|
||||
|
||||
// As vscode.TextEditor.setDecorations only applies to visible editors, we must cache the range for when another editor becomes visible
|
||||
valuePair.ranges = ranges;
|
||||
} else { // The entry does not exist. Make a new one
|
||||
let toInsert: DecorationRangesPair = {
|
||||
decoration: decoration,
|
||||
ranges: ranges
|
||||
};
|
||||
this.inactiveRegionsDecorations.set(params.uri, toInsert);
|
||||
}
|
||||
|
||||
if (settings.dimInactiveRegions) {
|
||||
// Apply the decorations to all *visible* text editors
|
||||
let editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri.toString() === params.uri);
|
||||
for (let e of editors) {
|
||||
e.setDecorations(decoration, ranges);
|
||||
}
|
||||
}
|
||||
let inactiveRanges: vscode.Range[] = [];
|
||||
params.inactiveRegions.forEach(element => {
|
||||
let newRange : vscode.Range = new vscode.Range(element.startLine, 0, element.endLine, 0);
|
||||
inactiveRanges.push(newRange);
|
||||
});
|
||||
let colorizationState: ColorizationState = this.getColorizationState(params.uri);
|
||||
colorizationState.updateSemantic(params.uri, semanticRanges, inactiveRanges, params.editVersion);
|
||||
this.languageClient.sendNotification(SemanticColorizationRegionsReceiptNotification, { uri: params.uri } );
|
||||
}
|
||||
|
||||
private promptCompileCommands(params: CompileCommandsPaths) : void {
|
||||
@@ -1009,7 +1240,7 @@ class DefaultClient implements Client {
|
||||
return;
|
||||
}
|
||||
|
||||
let ask: PersistentState<boolean> = new PersistentState<boolean>("CPP.showCompileCommandsSelection", true);
|
||||
let ask: PersistentFolderState<boolean> = new PersistentFolderState<boolean>("CPP.showCompileCommandsSelection", true, this.RootPath);
|
||||
if (!ask.Value) {
|
||||
return;
|
||||
}
|
||||
@@ -1130,6 +1361,9 @@ class DefaultClient implements Client {
|
||||
}).then(() => {
|
||||
let newProvider: string = this.configuration.CurrentConfigurationProvider;
|
||||
if (this.configurationProvider !== newProvider) {
|
||||
if (this.configurationProvider) {
|
||||
this.clearCustomConfigurations();
|
||||
}
|
||||
this.configurationProvider = newProvider;
|
||||
this.updateCustomConfigurations();
|
||||
this.updateCustomBrowseConfiguration();
|
||||
@@ -1283,7 +1517,15 @@ class DefaultClient implements Client {
|
||||
}
|
||||
|
||||
public handleConfigurationEditCommand(): void {
|
||||
this.notifyWhenReady(() => this.configuration.handleConfigurationEditCommand(vscode.window.showTextDocument));
|
||||
this.notifyWhenReady(() => this.configuration.handleConfigurationEditCommand(null, vscode.window.showTextDocument));
|
||||
}
|
||||
|
||||
public handleConfigurationEditJSONCommand(): void {
|
||||
this.notifyWhenReady(() => this.configuration.handleConfigurationEditJSONCommand(null, vscode.window.showTextDocument));
|
||||
}
|
||||
|
||||
public handleConfigurationEditUICommand(): void {
|
||||
this.notifyWhenReady(() => this.configuration.handleConfigurationEditUICommand(null, vscode.window.showTextDocument));
|
||||
}
|
||||
|
||||
public handleAddToIncludePathCommand(path: string): void {
|
||||
@@ -1302,6 +1544,11 @@ class DefaultClient implements Client {
|
||||
public dispose(): Thenable<void> {
|
||||
let promise: Thenable<void> = (this.languageClient) ? this.languageClient.stop() : Promise.resolve();
|
||||
return promise.then(() => {
|
||||
|
||||
this.colorizationState.forEach(colorizationState => {
|
||||
colorizationState.dispose();
|
||||
});
|
||||
|
||||
this.disposables.forEach((d) => d.dispose());
|
||||
this.disposables = [];
|
||||
|
||||
@@ -1342,13 +1589,20 @@ class NullClient implements Client {
|
||||
RootUri: vscode.Uri = vscode.Uri.file("/");
|
||||
Name: string = "(empty)";
|
||||
TrackedDocuments = new Set<vscode.TextDocument>();
|
||||
onDidChangeSettings(): { [key: string] : string } { return {}; }
|
||||
onDidChangeSettings(event: vscode.ConfigurationChangeEvent): { [key: string] : string } { return {}; }
|
||||
onDidOpenTextDocument(document: vscode.TextDocument): void {}
|
||||
onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {}
|
||||
onDidChangeTextDocument(textDocumentChangeEvent: vscode.TextDocumentChangeEvent): void {}
|
||||
onDidChangeTextEditorVisibleRanges(textEditorVisibleRangesChangeEvent: vscode.TextEditorVisibleRangesChangeEvent): void {}
|
||||
onRegisterCustomConfigurationProvider(provider: CustomConfigurationProvider1): Thenable<void> { return Promise.resolve(); }
|
||||
updateCustomConfigurations(requestingProvider?: CustomConfigurationProvider1): Thenable<void> { return Promise.resolve(); }
|
||||
updateCustomBrowseConfiguration(requestingProvider?: CustomConfigurationProvider1): Thenable<void> { return Promise.resolve(); }
|
||||
provideCustomConfiguration(document: vscode.TextDocument): Promise<void> { return Promise.resolve(); }
|
||||
logDiagnostics(): Promise<void> { return Promise.resolve(); }
|
||||
rescanFolder(): Promise<void> { return Promise.resolve(); }
|
||||
getCurrentConfigName(): Thenable<string> { return Promise.resolve(""); }
|
||||
getCompilerPath(): Thenable<string> { return Promise.resolve(""); }
|
||||
getKnownCompilers(): Thenable<configs.KnownCompiler[]> { return Promise.resolve([]); }
|
||||
takeOwnership(document: vscode.TextDocument): void {}
|
||||
queueTask<T>(task: () => Thenable<T>): Thenable<T> { return task(); }
|
||||
requestWhenReady(request: () => Thenable<any>): Thenable<any> { return; }
|
||||
@@ -1367,6 +1621,8 @@ class NullClient implements Client {
|
||||
handleConfigurationProviderSelectCommand(): void {}
|
||||
handleShowParsingCommands(): void {}
|
||||
handleConfigurationEditCommand(): void {}
|
||||
handleConfigurationEditJSONCommand(): void {}
|
||||
handleConfigurationEditUICommand(): void {}
|
||||
handleAddToIncludePathCommand(path: string): void {}
|
||||
onInterval(): void {}
|
||||
dispose(): Thenable<void> {
|
||||
@@ -1374,4 +1630,5 @@ class NullClient implements Client {
|
||||
this.stringEvent.dispose();
|
||||
return Promise.resolve();
|
||||
}
|
||||
addFileAssociations(fileAssociations: string, is_c: boolean): void {}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,8 @@ export class ClientCollection {
|
||||
}
|
||||
|
||||
private onDidOpenTextDocument(document: vscode.TextDocument): void {
|
||||
if (document.languageId === "c" || document.languageId === "cpp") {
|
||||
if (document.languageId === "c" || document.languageId === "cpp"
|
||||
|| document.languageId === "json" && document.uri.fsPath.endsWith("c_cpp_properties.json")) {
|
||||
// Make sure a client exists for this document's workspace.
|
||||
this.getClientFor(document.uri);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,657 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as util from '../common';
|
||||
import { CppSettings, OtherSettings, TextMateRule, TextMateRuleSettings } from './settings';
|
||||
import * as jsonc from 'jsonc-parser';
|
||||
import * as plist from 'plist';
|
||||
|
||||
export enum TokenKind {
|
||||
// These need to match the token_kind enum in the server
|
||||
|
||||
// Semantic tokens
|
||||
Macro,
|
||||
Enumerator,
|
||||
GlobalVariable,
|
||||
LocalVariable,
|
||||
Parameter,
|
||||
Type,
|
||||
RefType,
|
||||
ValueType,
|
||||
Function,
|
||||
MemberFunction,
|
||||
MemberField,
|
||||
StaticMemberFunction,
|
||||
StaticMemberField,
|
||||
Property,
|
||||
Event,
|
||||
ClassTemplate,
|
||||
GenericType,
|
||||
FunctionTemplate,
|
||||
Namespace,
|
||||
Label,
|
||||
UdlRaw,
|
||||
UdlNumber,
|
||||
UdlString,
|
||||
OperatorFunction,
|
||||
MemberOperator,
|
||||
NewDelete,
|
||||
|
||||
Count
|
||||
}
|
||||
|
||||
interface VersionedEdits {
|
||||
editVersion: number;
|
||||
changes: vscode.TextDocumentContentChangeEvent[];
|
||||
}
|
||||
|
||||
class ThemeStyle {
|
||||
foreground: string;
|
||||
background: string;
|
||||
fontStyle: string;
|
||||
}
|
||||
|
||||
export class ColorizationSettings {
|
||||
private uri: vscode.Uri;
|
||||
private pendingTask: util.BlockingTask<any>;
|
||||
private editorBackground: string;
|
||||
|
||||
public themeStyleCMap: ThemeStyle[] = [];
|
||||
public themeStyleCppMap: ThemeStyle[] = [];
|
||||
|
||||
private static readonly scopeToTokenColorNameMap = new Map<string, string>([
|
||||
["comment", "comments"],
|
||||
["string", "strings"],
|
||||
["keyword.operator", "keywords"],
|
||||
["keyword.control", "keywords"],
|
||||
["constant.numeric", "numbers"],
|
||||
["entity.name.type", "types"],
|
||||
["entity.name.class", "types"],
|
||||
["entity.name.function", "functions"],
|
||||
["variable", "variables"]
|
||||
]);
|
||||
|
||||
constructor(uri: vscode.Uri) {
|
||||
this.uri = uri;
|
||||
this.reload();
|
||||
}
|
||||
|
||||
// Given a TextMate rule 'settings' node, update a ThemeStyle to include any color or style information
|
||||
private updateStyleFromTextMateRuleSettings(baseStyle: ThemeStyle, textMateRuleSettings: TextMateRuleSettings): void {
|
||||
if (textMateRuleSettings.foreground) {
|
||||
baseStyle.foreground = textMateRuleSettings.foreground;
|
||||
}
|
||||
if (textMateRuleSettings.background && textMateRuleSettings.background.toUpperCase() !== this.editorBackground.toUpperCase()) {
|
||||
baseStyle.background = textMateRuleSettings.background;
|
||||
}
|
||||
// Any (even empty) string for fontStyle removes inherited value
|
||||
if (textMateRuleSettings.fontStyle) {
|
||||
baseStyle.fontStyle = textMateRuleSettings.fontStyle;
|
||||
} else if (textMateRuleSettings.fontStyle === "") {
|
||||
baseStyle.fontStyle = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// If the scope can be found in a set of TextMate rules, apply it to both C and Cpp ThemeStyle's
|
||||
private findThemeStyleForScope(baseCStyle: ThemeStyle, baseCppStyle: ThemeStyle, scope: string, textMateRules: TextMateRule[]): void {
|
||||
if (textMateRules) {
|
||||
let match: TextMateRule = textMateRules.find(e => e.settings && (e.scope === scope || ((e.scope instanceof Array) && e.scope.indexOf(scope) > -1)));
|
||||
if (match) {
|
||||
if (baseCStyle) {
|
||||
this.updateStyleFromTextMateRuleSettings(baseCStyle, match.settings);
|
||||
}
|
||||
if (baseCppStyle) {
|
||||
this.updateStyleFromTextMateRuleSettings(baseCppStyle, match.settings);
|
||||
}
|
||||
}
|
||||
|
||||
match = textMateRules.find(e => e.settings && (e.scope === "source " + scope || ((e.scope instanceof Array) && e.scope.indexOf("source " + scope) > -1)));
|
||||
if (match) {
|
||||
if (baseCStyle) {
|
||||
this.updateStyleFromTextMateRuleSettings(baseCStyle, match.settings);
|
||||
}
|
||||
if (baseCppStyle) {
|
||||
this.updateStyleFromTextMateRuleSettings(baseCppStyle, match.settings);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseCStyle) {
|
||||
match = textMateRules.find(e => e.settings && (e.scope === "source.c " + scope || ((e.scope instanceof Array) && e.scope.indexOf("source.c " + scope) > -1)));
|
||||
if (match) {
|
||||
this.updateStyleFromTextMateRuleSettings(baseCStyle, match.settings);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseCppStyle) {
|
||||
match = textMateRules.find(e => e.settings && (e.scope === "source.cpp " + scope || ((e.scope instanceof Array) && e.scope.indexOf("source.cpp " + scope) > -1)));
|
||||
if (match) {
|
||||
this.updateStyleFromTextMateRuleSettings(baseCppStyle, match.settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For a specific scope cascase all potential sources of style information to create a final ThemeStyle
|
||||
private calculateThemeStyleForScope(baseCStyle: ThemeStyle, baseCppStyle: ThemeStyle, scope: string, themeName: string, themeTextMateRules: TextMateRule[][]): void {
|
||||
// Search for settings with this scope in current theme
|
||||
themeTextMateRules.forEach((rules) => {
|
||||
this.findThemeStyleForScope(baseCStyle, baseCppStyle, scope, rules);
|
||||
});
|
||||
|
||||
let otherSettings: OtherSettings = new OtherSettings(this.uri);
|
||||
|
||||
// Next in priority would be a global user override of token color of the equivilent scope
|
||||
let colorTokenName: string | undefined = ColorizationSettings.scopeToTokenColorNameMap.get(scope);
|
||||
if (colorTokenName) {
|
||||
let settingValue: string = otherSettings.getCustomColorToken(colorTokenName);
|
||||
if (settingValue) {
|
||||
if (baseCStyle) {
|
||||
baseCStyle.foreground = settingValue;
|
||||
}
|
||||
if (baseCppStyle) {
|
||||
baseCppStyle.foreground = settingValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next in priority would be a global user override of this scope in textMateRules
|
||||
this.findThemeStyleForScope(baseCStyle, baseCppStyle, scope, otherSettings.customTextMateRules);
|
||||
|
||||
// Next in priority would be a theme-specific user override of token color of the equivilent scope
|
||||
if (colorTokenName) {
|
||||
let settingValue: string = otherSettings.getCustomThemeSpecificColorToken(colorTokenName, themeName);
|
||||
if (settingValue) {
|
||||
if (baseCStyle) {
|
||||
baseCStyle.foreground = settingValue;
|
||||
}
|
||||
if (baseCppStyle) {
|
||||
baseCppStyle.foreground = settingValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next in priority would be a theme-specific user override of this scope in textMateRules
|
||||
let textMateRules: TextMateRule[] = otherSettings.getCustomThemeSpecificTextMateRules(themeName);
|
||||
this.findThemeStyleForScope(baseCStyle, baseCppStyle, scope, textMateRules);
|
||||
}
|
||||
|
||||
// For each level of the scope, look of style information
|
||||
private calculateStyleForToken(tokenKind: TokenKind, scope: string, themeName: string, themeTextMateRules: TextMateRule[][]): void {
|
||||
// Try scopes, from most general to most specific, apply style in cascading manner
|
||||
let parts: string[] = scope.split(".");
|
||||
let accumulatedScope: string = "";
|
||||
for (let i: number = 0; i < parts.length; i++) {
|
||||
accumulatedScope += parts[i];
|
||||
this.calculateThemeStyleForScope(this.themeStyleCMap[tokenKind], this.themeStyleCppMap[tokenKind], accumulatedScope, themeName, themeTextMateRules);
|
||||
this.calculateThemeStyleForScope(this.themeStyleCMap[tokenKind], null, accumulatedScope + ".c", themeName, themeTextMateRules);
|
||||
this.calculateThemeStyleForScope(null, this.themeStyleCppMap[tokenKind], accumulatedScope + ".cpp", themeName, themeTextMateRules);
|
||||
accumulatedScope += ".";
|
||||
}
|
||||
}
|
||||
|
||||
public syncWithLoadingSettings(f: () => any): void {
|
||||
this.pendingTask = new util.BlockingTask<void>(f, this.pendingTask);
|
||||
}
|
||||
|
||||
public updateStyles(themeName: string, defaultStyle: ThemeStyle, textMateRules: TextMateRule[][]): void {
|
||||
this.themeStyleCMap = new Array<ThemeStyle>(TokenKind.Count);
|
||||
this.themeStyleCppMap = new Array<ThemeStyle>(TokenKind.Count);
|
||||
|
||||
// Populate with unique objects, as they will be individual modified in place
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
this.themeStyleCMap[i] = Object.assign({}, defaultStyle);
|
||||
this.themeStyleCppMap[i] = Object.assign({}, defaultStyle);
|
||||
}
|
||||
|
||||
this.calculateStyleForToken(TokenKind.Macro, "entity.name.function.preprocessor", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Enumerator, "variable.other.enummember", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.GlobalVariable, "variable.other.global", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.LocalVariable, "variable.other.local", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Parameter, "variable.parameter", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Type, "entity.name.type", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.RefType, "entity.name.class.reference", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.ValueType, "entity.name.class.value", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Function, "entity.name.function", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.MemberFunction, "entity.name.function.member", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.MemberField, "variable.other.member", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.StaticMemberFunction, "entity.name.function.member.static", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.StaticMemberField, "variable.other.member.static", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Property, "variable.other.property", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Event, "variable.other.event", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.ClassTemplate, "entity.name.class.template", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.GenericType, "entity.name.class.generic", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.FunctionTemplate, "entity.name.function.template", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Namespace, "entity.name.type.namespace", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.Label, "entity.name.label", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.UdlRaw, "entity.name.user-defined-literal", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.UdlNumber, "entity.name.user-defined-literal.number", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.UdlString, "entity.name.user-defined-literal.string", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.OperatorFunction, "entity.name.function.operator", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.MemberOperator, "keyword.operator.member", themeName, textMateRules);
|
||||
this.calculateStyleForToken(TokenKind.NewDelete, "keyword.operator.new", themeName, textMateRules);
|
||||
}
|
||||
|
||||
public async loadTheme(themePath: string, defaultStyle: ThemeStyle): Promise<TextMateRule[][]> {
|
||||
let rules: TextMateRule[][] = [];
|
||||
if (await util.checkFileExists(themePath)) {
|
||||
let themeContentText: string = await util.readFileText(themePath);
|
||||
let themeContent: any;
|
||||
let textMateRules: TextMateRule[];
|
||||
if (themePath.endsWith("tmTheme")) {
|
||||
themeContent = plist.parse(themeContentText);
|
||||
if (themeContent) {
|
||||
textMateRules = themeContent.settings;
|
||||
}
|
||||
} else {
|
||||
themeContent = jsonc.parse(themeContentText);
|
||||
if (themeContent) {
|
||||
textMateRules = themeContent.tokenColors;
|
||||
if (themeContent.include) {
|
||||
// parse included theme file
|
||||
let includedThemePath: string = path.join(path.dirname(themePath), themeContent.include);
|
||||
rules = await this.loadTheme(includedThemePath, defaultStyle);
|
||||
}
|
||||
|
||||
if (themeContent.colors && themeContent.colors["editor.background"]) {
|
||||
this.editorBackground = themeContent.colors["editor.background"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (textMateRules) {
|
||||
// Convert comma delimited scopes into an array
|
||||
textMateRules.forEach(e => {
|
||||
if (e.scope && e.scope.includes(',')) {
|
||||
e.scope = e.scope.split(',').map((s: string) => s.trim());
|
||||
}
|
||||
});
|
||||
|
||||
let scopelessSetting: any = textMateRules.find(e => e.settings && !e.scope);
|
||||
if (scopelessSetting) {
|
||||
if (scopelessSetting.settings.background) {
|
||||
this.editorBackground = scopelessSetting.settings.background;
|
||||
}
|
||||
this.updateStyleFromTextMateRuleSettings(defaultStyle, scopelessSetting.settings);
|
||||
}
|
||||
rules.push(textMateRules);
|
||||
}
|
||||
}
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
public reload(): void {
|
||||
let f: () => void = async () => {
|
||||
let otherSettings: OtherSettings = new OtherSettings(this.uri);
|
||||
let themeName: string = otherSettings.colorTheme;
|
||||
|
||||
// Enumerate through all extensions, looking for this theme. (Themes are implemented as extensions - even the default ones)
|
||||
// Open each package.json to check for a theme path
|
||||
for (let i: number = 0; i < vscode.extensions.all.length; i++) {
|
||||
let extensionPath: string = vscode.extensions.all[i].extensionPath;
|
||||
let extensionPackageJsonPath: string = path.join(extensionPath, "package.json");
|
||||
if (!await util.checkFileExists(extensionPackageJsonPath)) {
|
||||
continue;
|
||||
}
|
||||
let packageJsonText: string = await util.readFileText(extensionPackageJsonPath);
|
||||
let packageJson: any = jsonc.parse(packageJsonText);
|
||||
if (packageJson.contributes && packageJson.contributes.themes) {
|
||||
let foundTheme: any = packageJson.contributes.themes.find(e => e.id === themeName || e.label === themeName);
|
||||
if (foundTheme) {
|
||||
let themeRelativePath: string = foundTheme.path;
|
||||
let themeFullPath: string = path.join(extensionPath, themeRelativePath);
|
||||
let defaultStyle: ThemeStyle = new ThemeStyle();
|
||||
let rulesSet: TextMateRule[][] = await this.loadTheme(themeFullPath, defaultStyle);
|
||||
this.updateStyles(themeName, defaultStyle, rulesSet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.syncWithLoadingSettings(f);
|
||||
}
|
||||
|
||||
public static createDecorationFromThemeStyle(themeStyle: ThemeStyle): vscode.TextEditorDecorationType {
|
||||
if (themeStyle && (themeStyle.foreground || themeStyle.background || themeStyle.fontStyle)) {
|
||||
let options: vscode.DecorationRenderOptions = {};
|
||||
options.rangeBehavior = vscode.DecorationRangeBehavior.OpenOpen;
|
||||
if (themeStyle.foreground) {
|
||||
options.color = themeStyle.foreground;
|
||||
}
|
||||
if (themeStyle.background) {
|
||||
options.backgroundColor = themeStyle.background;
|
||||
}
|
||||
if (themeStyle.fontStyle) {
|
||||
let parts: string[] = themeStyle.fontStyle.split(" ");
|
||||
parts.forEach((part) => {
|
||||
switch (part) {
|
||||
case "italic":
|
||||
options.fontStyle = "italic";
|
||||
break;
|
||||
case "bold":
|
||||
options.fontWeight = "bold";
|
||||
break;
|
||||
case "underline":
|
||||
options.textDecoration = "underline";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
return vscode.window.createTextEditorDecorationType(options);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export class ColorizationState {
|
||||
private uri: vscode.Uri;
|
||||
private colorizationSettings: ColorizationSettings;
|
||||
private decorations: vscode.TextEditorDecorationType[] = new Array<vscode.TextEditorDecorationType>(TokenKind.Count);
|
||||
private semanticRanges: vscode.Range[][] = new Array<vscode.Range[]>(TokenKind.Count);
|
||||
private inactiveDecoration: vscode.TextEditorDecorationType = null;
|
||||
private inactiveRanges: vscode.Range[] = [];
|
||||
private versionedEdits: VersionedEdits[] = [];
|
||||
private currentSemanticVersion: number = 0;
|
||||
private lastReceivedSemanticVersion: number = 0;
|
||||
|
||||
public constructor(uri: vscode.Uri, colorizationSettings: ColorizationSettings) {
|
||||
this.uri = uri;
|
||||
this.colorizationSettings = colorizationSettings;
|
||||
}
|
||||
|
||||
private createColorizationDecorations(isCpp: boolean): void {
|
||||
let settings: CppSettings = new CppSettings(this.uri);
|
||||
if (settings.enhancedColorization) {
|
||||
// Create new decorators
|
||||
// The first decorator created takes precedence, so these need to be created in reverse order
|
||||
for (let i: number = TokenKind.Count; i > 0;) {
|
||||
i--;
|
||||
let themeStyleMap: any;
|
||||
if (isCpp) {
|
||||
themeStyleMap = this.colorizationSettings.themeStyleCppMap;
|
||||
} else {
|
||||
themeStyleMap = this.colorizationSettings.themeStyleCMap;
|
||||
}
|
||||
this.decorations[i] = ColorizationSettings.createDecorationFromThemeStyle(themeStyleMap[i]);
|
||||
}
|
||||
}
|
||||
if (settings.dimInactiveRegions) {
|
||||
this.inactiveDecoration = vscode.window.createTextEditorDecorationType({
|
||||
opacity: settings.inactiveRegionOpacity.toString(),
|
||||
backgroundColor: settings.inactiveRegionBackgroundColor,
|
||||
color: settings.inactiveRegionForegroundColor,
|
||||
rangeBehavior: vscode.DecorationRangeBehavior.OpenOpen
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private disposeColorizationDecorations(): void {
|
||||
// Dispose of all old decorations
|
||||
if (this.inactiveDecoration) {
|
||||
this.inactiveDecoration.dispose();
|
||||
this.inactiveDecoration = null;
|
||||
}
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
if (this.decorations[i]) {
|
||||
this.decorations[i].dispose();
|
||||
this.decorations[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.disposeColorizationDecorations();
|
||||
}
|
||||
|
||||
private refreshInner(e: vscode.TextEditor): void {
|
||||
let settings: CppSettings = new CppSettings(this.uri);
|
||||
if (settings.enhancedColorization) {
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
if (this.decorations[i]) {
|
||||
let ranges: vscode.Range[] = this.semanticRanges[i];
|
||||
if (ranges && ranges.length > 0) {
|
||||
e.setDecorations(this.decorations[i], ranges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normally, decorators are honored in the order in which they were created, not the
|
||||
// order in which they were applied. Decorators with opacity appear to be handled
|
||||
// differently, in that the opacity is applied to overlapping decorators even if
|
||||
// created afterwards.
|
||||
if (settings.dimInactiveRegions && this.inactiveDecoration && this.inactiveRanges) {
|
||||
e.setDecorations(this.inactiveDecoration, this.inactiveRanges);
|
||||
}
|
||||
}
|
||||
|
||||
public refresh(e: vscode.TextEditor): void {
|
||||
this.applyEdits();
|
||||
let f: () => void = async () => {
|
||||
this.refreshInner(e);
|
||||
};
|
||||
this.colorizationSettings.syncWithLoadingSettings(f);
|
||||
}
|
||||
|
||||
public onSettingsChanged(uri: vscode.Uri): void {
|
||||
let f: () => void = async () => {
|
||||
this.applyEdits();
|
||||
this.disposeColorizationDecorations();
|
||||
let isCpp: boolean = util.isEditorFileCpp(uri.toString());
|
||||
this.createColorizationDecorations(isCpp);
|
||||
let editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri === uri);
|
||||
for (let e of editors) {
|
||||
this.refreshInner(e);
|
||||
}
|
||||
};
|
||||
this.colorizationSettings.syncWithLoadingSettings(f);
|
||||
}
|
||||
|
||||
// Utility function to convert a string and a start Position into a Range
|
||||
private textToRange(text: string, startPosition: vscode.Position): vscode.Range {
|
||||
let parts: string[] = text.split("\n");
|
||||
let addedLines: number = parts.length - 1;
|
||||
let newStartLine: number = startPosition.line;
|
||||
let newStartCharacter: number = startPosition.character;
|
||||
let newEndLine: number = newStartLine + addedLines;
|
||||
let newEndCharacter: number = parts[parts.length - 1].length;
|
||||
if (newStartLine === newEndLine) {
|
||||
newEndCharacter += newStartCharacter;
|
||||
}
|
||||
return new vscode.Range(newStartLine, newStartCharacter, newEndLine, newEndCharacter);
|
||||
}
|
||||
|
||||
// Utility function to shift a range back after removing content before it
|
||||
private shiftRangeAfterRemove(range: vscode.Range, removeStartPosition: vscode.Position, removeEndPosition: vscode.Position): vscode.Range {
|
||||
let lineDelta: number = removeStartPosition.line - removeEndPosition.line;
|
||||
let startCharacterDelta: number = 0;
|
||||
let endCharacterDelta: number = 0;
|
||||
if (range.start.line === removeEndPosition.line) {
|
||||
startCharacterDelta = removeStartPosition.character - removeEndPosition.character;
|
||||
if (range.end.line === removeEndPosition.line) {
|
||||
endCharacterDelta = startCharacterDelta;
|
||||
}
|
||||
}
|
||||
let newStart: vscode.Position = range.start.translate(lineDelta, startCharacterDelta);
|
||||
let newEnd: vscode.Position = range.end.translate(lineDelta, endCharacterDelta);
|
||||
return new vscode.Range(newStart, newEnd);
|
||||
}
|
||||
|
||||
// Utility function to shift a range forward after inserting content before it
|
||||
private shiftRangeAfterInsert(range: vscode.Range, insertStartPosition: vscode.Position, insertEndPosition: vscode.Position): vscode.Range {
|
||||
let addedLines: number = insertEndPosition.line - insertStartPosition.line;
|
||||
let newStartLine: number = range.start.line + addedLines;
|
||||
let newEndLine: number = range.end.line + addedLines;
|
||||
let newStartCharacter: number = range.start.character;
|
||||
let newEndCharacter: number = range.end.character;
|
||||
// If starts on the same line as replacement ended
|
||||
if (insertEndPosition.line === newStartLine) {
|
||||
let endOffsetLength: number = insertEndPosition.character;
|
||||
// If insertRange starts and ends on the same line, only offset by it's length
|
||||
if (insertEndPosition.line === insertStartPosition.line) {
|
||||
endOffsetLength -= insertStartPosition.character;
|
||||
}
|
||||
newStartCharacter += endOffsetLength;
|
||||
if (insertEndPosition.line === newEndLine) {
|
||||
newEndCharacter += endOffsetLength;
|
||||
}
|
||||
}
|
||||
return new vscode.Range(newStartLine, newStartCharacter, newEndLine, newEndCharacter);
|
||||
}
|
||||
|
||||
// Utility function to adjust a range to account for an insert and/or replace
|
||||
private fixRange(range: vscode.Range, removeInsertStartPosition: vscode.Position, removeEndPosition: vscode.Position, insertEndPosition: vscode.Position): vscode.Range {
|
||||
// If the replace/insert starts after this range ends, no adjustment is needed.
|
||||
if (removeInsertStartPosition.isAfterOrEqual(range.end)) {
|
||||
return range;
|
||||
}
|
||||
// Else, replace/insert range starts before this range ends.
|
||||
|
||||
// If replace/insert starts before/where this range starts, we don't need to extend the existing range, but need to shift it
|
||||
if (removeInsertStartPosition.isBeforeOrEqual(range.start)) {
|
||||
|
||||
// If replace consumes the entire range, remove it
|
||||
if (removeEndPosition.isAfterOrEqual(range.end)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If replace ends within this range, we need to trim it before we shift it
|
||||
let newRange: vscode.Range;
|
||||
if (removeEndPosition.isAfterOrEqual(range.start)) {
|
||||
newRange = new vscode.Range(removeEndPosition, range.end);
|
||||
} else {
|
||||
newRange = range;
|
||||
}
|
||||
// Else, if replace ends before this range starts, we just need to shift it.
|
||||
|
||||
newRange = this.shiftRangeAfterRemove(newRange, removeInsertStartPosition, removeEndPosition);
|
||||
return this.shiftRangeAfterInsert(newRange, removeInsertStartPosition, insertEndPosition);
|
||||
}
|
||||
// Else, if replace/insert starts within (not before or after) range, extend it.
|
||||
|
||||
// If there replace/insert overlaps past the end of the original range, just extend existing range to the insert end position
|
||||
if (removeEndPosition.isAfterOrEqual(range.end)) {
|
||||
return new vscode.Range(range.start.line, range.start.character, insertEndPosition.line, insertEndPosition.character);
|
||||
}
|
||||
// Else, range has some left over at the end, which needs to be shifted after insertEndPosition.
|
||||
|
||||
// If the trailing segment is on the last line replace, we just need to extend by the remaining number of characters
|
||||
if (removeEndPosition.line === range.end.line) {
|
||||
return new vscode.Range(range.start.line, range.start.character, insertEndPosition.line, insertEndPosition.character + (range.end.character - removeEndPosition.character));
|
||||
}
|
||||
// Else, the trailing segment ends on another line, so the character position should remain the same. Just adjust based on added/removed lined.
|
||||
let removedLines: number = removeEndPosition.line - removeInsertStartPosition.line;
|
||||
let addedLines: number = insertEndPosition.line - removeInsertStartPosition.line;
|
||||
let deltaLines: number = addedLines - removedLines;
|
||||
return new vscode.Range(range.start.line, range.start.character, range.end.line + deltaLines, range.end.character);
|
||||
}
|
||||
|
||||
private fixRanges(originalRanges: vscode.Range[], changes: vscode.TextDocumentContentChangeEvent[]): vscode.Range[] {
|
||||
// outer loop needs to be the versioned edits, then changes within that edit, then ranges
|
||||
let ranges: vscode.Range[] = originalRanges;
|
||||
if (ranges && ranges.length > 0) {
|
||||
changes.forEach((change) => {
|
||||
let newRanges: vscode.Range[] = [];
|
||||
let insertRange: vscode.Range = this.textToRange(change.text, change.range.start);
|
||||
for (let i: number = 0; i < ranges.length; i++) {
|
||||
let newRange: vscode.Range = this.fixRange(ranges[i], change.range.start, change.range.end, insertRange.end);
|
||||
if (newRange !== null) {
|
||||
newRanges.push(newRange);
|
||||
}
|
||||
}
|
||||
ranges = newRanges;
|
||||
});
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
// Add edits to be applied when/if cached tokens need to be reapplied.
|
||||
public addEdits(changes: vscode.TextDocumentContentChangeEvent[], editVersion: number): void {
|
||||
let edits: VersionedEdits = {
|
||||
editVersion: editVersion,
|
||||
changes: changes
|
||||
};
|
||||
this.versionedEdits.push(edits);
|
||||
}
|
||||
|
||||
// Apply any pending edits to the currently cached tokens
|
||||
private applyEdits() : void {
|
||||
this.versionedEdits.forEach((edit) => {
|
||||
if (edit.editVersion > this.currentSemanticVersion) {
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
this.semanticRanges[i] = this.fixRanges(this.semanticRanges[i], edit.changes);
|
||||
}
|
||||
this.inactiveRanges = this.fixRanges(this.inactiveRanges, edit.changes);
|
||||
this.currentSemanticVersion = edit.editVersion;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Remove any edits from the list if we will never receive tokens that old.
|
||||
private purgeOldVersionedEdits(): void {
|
||||
let minVersion: number = this.lastReceivedSemanticVersion;
|
||||
let index: number = this.versionedEdits.findIndex((edit) => edit.editVersion > minVersion);
|
||||
if (index === -1) {
|
||||
this.versionedEdits = [];
|
||||
} else if (index > 0) {
|
||||
this.versionedEdits = this.versionedEdits.slice(index);
|
||||
}
|
||||
}
|
||||
|
||||
private updateColorizationRanges(uri: string): void {
|
||||
let f: () => void = async () => {
|
||||
this.applyEdits();
|
||||
this.purgeOldVersionedEdits();
|
||||
|
||||
// The only way to un-apply decorators is to dispose them.
|
||||
// If we dispose old decorators before applying new decorators, we see a flicker on Mac,
|
||||
// likely due to a race with UI updates. Here we set aside the existing decorators to be
|
||||
// disposed of after the new decorators have been applied, so there is not a gap
|
||||
// in which decorators are not applied.
|
||||
let oldInactiveDecoration: vscode.TextEditorDecorationType = this.inactiveDecoration;
|
||||
let oldDecorations: vscode.TextEditorDecorationType[] = this.decorations;
|
||||
this.inactiveDecoration = null;
|
||||
this.decorations = new Array<vscode.TextEditorDecorationType>(TokenKind.Count);
|
||||
|
||||
let isCpp: boolean = util.isEditorFileCpp(uri);
|
||||
this.createColorizationDecorations(isCpp);
|
||||
|
||||
// Apply the decorations to all *visible* text editors
|
||||
let editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri.toString() === uri);
|
||||
for (let e of editors) {
|
||||
this.refreshInner(e);
|
||||
}
|
||||
|
||||
// Dispose of the old decorators only after the new ones have been applied.
|
||||
if (oldInactiveDecoration) {
|
||||
oldInactiveDecoration.dispose();
|
||||
}
|
||||
if (oldDecorations) {
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
if (oldDecorations[i]) {
|
||||
oldDecorations[i].dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.colorizationSettings.syncWithLoadingSettings(f);
|
||||
}
|
||||
|
||||
public updateSemantic(uri: string, semanticRanges: vscode.Range[][], inactiveRanges: vscode.Range[], editVersion: number): void {
|
||||
this.inactiveRanges = inactiveRanges;
|
||||
for (let i: number = 0; i < TokenKind.Count; i++) {
|
||||
this.semanticRanges[i] = semanticRanges[i];
|
||||
}
|
||||
this.currentSemanticVersion = editVersion;
|
||||
this.lastReceivedSemanticVersion = editVersion;
|
||||
this.updateColorizationRanges(uri);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,15 +14,17 @@ import { UI, getUI } from './ui';
|
||||
import { Client } from './client';
|
||||
import { ClientCollection } from './clientCollection';
|
||||
import { CppSettings } from './settings';
|
||||
import { PersistentWorkspaceState } from './persistentState';
|
||||
import { PersistentWorkspaceState, PersistentState } from './persistentState';
|
||||
import { getLanguageConfig } from './languageConfig';
|
||||
import { getCustomConfigProviders } from './customProviders';
|
||||
import { PlatformInformation } from '../platform';
|
||||
import { Range } from 'vscode-languageclient';
|
||||
import { ChildProcess, spawn, execSync } from 'child_process';
|
||||
import * as tmp from 'tmp';
|
||||
import { getTargetBuildInfo } from '../githubAPI';
|
||||
import { getTargetBuildInfo, BuildInfo } from '../githubAPI';
|
||||
import * as configs from './configurations';
|
||||
import { PackageVersion } from '../packageVersion';
|
||||
import { getTemporaryCommandRegistrarInstance } from '../commands';
|
||||
|
||||
let prevCrashFile: string;
|
||||
let clients: ClientCollection;
|
||||
@@ -36,12 +38,19 @@ let realActivationOccurred: boolean = false;
|
||||
let tempCommands: vscode.Disposable[] = [];
|
||||
let activatedPreviously: PersistentWorkspaceState<boolean>;
|
||||
const insiderUpdateTimerInterval: number = 1000 * 60 * 60;
|
||||
let buildInfoCache: BuildInfo | null = null;
|
||||
const taskSourceStr: string = "C/C++";
|
||||
const cppInstallVsixStr: string = 'C/C++: Install vsix -- ';
|
||||
let taskProvider: vscode.Disposable;
|
||||
const intelliSenseDisabledError: string = "Do not activate the extension when IntelliSense is disabled.";
|
||||
|
||||
/**
|
||||
* activate: set up the extension for language services
|
||||
*/
|
||||
export function activate(activationEventOccurred: boolean): void {
|
||||
console.log("activating extension");
|
||||
if (realActivationOccurred) {
|
||||
return; // Occurs if multiple delayed commands occur before the real commands are registered.
|
||||
}
|
||||
|
||||
// Activate immediately if an activation event occurred in the previous workspace session.
|
||||
// If onActivationEvent doesn't occur, it won't auto-activate next time.
|
||||
@@ -51,8 +60,9 @@ export function activate(activationEventOccurred: boolean): void {
|
||||
realActivation();
|
||||
}
|
||||
|
||||
registerCommands();
|
||||
tempCommands.push(vscode.workspace.onDidOpenTextDocument(d => onDidOpenTextDocument(d)));
|
||||
if (tempCommands.length === 0) { // Only needs to be added once.
|
||||
tempCommands.push(vscode.workspace.onDidOpenTextDocument(d => onDidOpenTextDocument(d)));
|
||||
}
|
||||
|
||||
// Check if an activation event has already occurred.
|
||||
if (activationEventOccurred) {
|
||||
@@ -60,6 +70,21 @@ export function activate(activationEventOccurred: boolean): void {
|
||||
return;
|
||||
}
|
||||
|
||||
taskProvider = vscode.tasks.registerTaskProvider(taskSourceStr, {
|
||||
provideTasks: () => {
|
||||
return getBuildTasks(false);
|
||||
},
|
||||
resolveTask(task: vscode.Task): vscode.Task {
|
||||
// Currently cannot implement because VS Code does not call this. Can implement custom output file directory when enabled.
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
vscode.tasks.onDidStartTask(event => {
|
||||
if (event.execution.task.source === taskSourceStr) {
|
||||
telemetry.logLanguageServerEvent('buildTaskStarted');
|
||||
}
|
||||
});
|
||||
|
||||
// handle "workspaceContains:/.vscode/c_cpp_properties.json" activation event.
|
||||
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
|
||||
for (let i: number = 0; i < vscode.workspace.workspaceFolders.length; ++i) {
|
||||
@@ -83,6 +108,163 @@ export function activate(activationEventOccurred: boolean): void {
|
||||
}
|
||||
}
|
||||
|
||||
export interface BuildTaskDefinition extends vscode.TaskDefinition {
|
||||
compilerPath: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension.
|
||||
*/
|
||||
export async function getBuildTasks(returnComplerPath: boolean): Promise<vscode.Task[]> {
|
||||
const editor: vscode.TextEditor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const fileExt: string = path.extname(editor.document.fileName);
|
||||
if (!fileExt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't offer tasks for header files.
|
||||
const fileExtLower: string = fileExt.toLowerCase();
|
||||
const isHeader: boolean = !fileExt || [".hpp", ".hh", ".hxx", ".h", ".inl", ""].some(ext => fileExtLower === ext);
|
||||
if (isHeader) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Don't offer tasks if the active file's extension is not a recognized C/C++ extension.
|
||||
let fileIsCpp: boolean;
|
||||
let fileIsC: boolean;
|
||||
if (fileExt === ".C") { // ".C" file extensions are both C and C++.
|
||||
fileIsCpp = true;
|
||||
fileIsC = true;
|
||||
} else {
|
||||
fileIsCpp = [".cpp", ".cc", ".cxx", ".mm", ".ino"].some(ext => fileExtLower === ext);
|
||||
fileIsC = fileExtLower === ".c";
|
||||
}
|
||||
if (!(fileIsCpp || fileIsC)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get a list of compilers found from the C++ side, then filter them based on the file type to get a reduced list appropriate
|
||||
// for the active file, remove duplicate compiler names, then finally add the user's compilerPath setting.
|
||||
let compilerPaths: string[];
|
||||
const isWindows: boolean = os.platform() === 'win32';
|
||||
let activeClient: Client;
|
||||
try {
|
||||
activeClient = getActiveClient();
|
||||
} catch (e) {
|
||||
if (!e || e.message !== intelliSenseDisabledError) {
|
||||
console.error("Unknown error calling getActiveClient().");
|
||||
}
|
||||
return []; // Language service features may be disabled.
|
||||
}
|
||||
let userCompilerPath: string = await activeClient.getCompilerPath();
|
||||
if (userCompilerPath) {
|
||||
userCompilerPath = userCompilerPath.trim();
|
||||
if (isWindows && userCompilerPath.startsWith("/")) { // TODO: Add WSL compiler support.
|
||||
userCompilerPath = null;
|
||||
} else {
|
||||
userCompilerPath = userCompilerPath.replace(/\\\\/g, "\\");
|
||||
}
|
||||
}
|
||||
|
||||
let knownCompilers: configs.KnownCompiler[] = await activeClient.getKnownCompilers();
|
||||
if (knownCompilers) {
|
||||
knownCompilers = knownCompilers.filter(info => {
|
||||
return ((fileIsCpp && !info.isC) || (fileIsC && info.isC)) &&
|
||||
(!isWindows || !info.path.startsWith("/")); // TODO: Add WSL compiler support.
|
||||
});
|
||||
compilerPaths = knownCompilers.map<string>(info => { return info.path; });
|
||||
|
||||
let map: Map<string, string> = new Map<string, string>();
|
||||
const insertOrAssignEntry: (compilerPath: string) => void = (compilerPath: string): void => {
|
||||
let basename: string = compilerPath;
|
||||
if (compilerPath === userCompilerPath) {
|
||||
// Make sure the compiler args are not part of the basename.
|
||||
const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(compilerPath);
|
||||
basename = compilerPathAndArgs.compilerPath;
|
||||
}
|
||||
basename = path.basename(basename);
|
||||
map.set(basename, compilerPath);
|
||||
};
|
||||
compilerPaths.forEach(insertOrAssignEntry);
|
||||
|
||||
// Ensure that the user's compilerPath setting is used by inserting/assigning last.
|
||||
if (userCompilerPath) {
|
||||
insertOrAssignEntry(userCompilerPath);
|
||||
}
|
||||
|
||||
compilerPaths = [...map.values()];
|
||||
} else if (userCompilerPath) {
|
||||
compilerPaths = [userCompilerPath];
|
||||
}
|
||||
|
||||
if (!compilerPaths) {
|
||||
// Don't prompt a message yet until we can make a data-based decision.
|
||||
telemetry.logLanguageServerEvent('noCompilerFound');
|
||||
// Display a message prompting the user to install compilers if none were found.
|
||||
// const dontShowAgain: string = "Don't Show Again";
|
||||
// const learnMore: string = "Learn More";
|
||||
// const message: string = "No C/C++ compiler found on the system. Please install a C/C++ compiler to use the C/C++: build active file tasks.";
|
||||
|
||||
// let showNoCompilerFoundMessage: PersistentState<boolean> = new PersistentState<boolean>("CPP.showNoCompilerFoundMessage", true);
|
||||
// if (showNoCompilerFoundMessage) {
|
||||
// vscode.window.showInformationMessage(message, learnMore, dontShowAgain).then(selection => {
|
||||
// switch (selection) {
|
||||
// case learnMore:
|
||||
// const uri: vscode.Uri = vscode.Uri.parse(`https://go.microsoft.com/fwlink/?linkid=864631`);
|
||||
// vscode.commands.executeCommand('vscode.open', uri);
|
||||
// break;
|
||||
// case dontShowAgain:
|
||||
// showNoCompilerFoundMessage.Value = false;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
return [];
|
||||
}
|
||||
|
||||
// Generate tasks.
|
||||
return compilerPaths.map<vscode.Task>(compilerPath => {
|
||||
// Handle compiler args in compilerPath.
|
||||
let compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(compilerPath);
|
||||
compilerPath = compilerPathAndArgs.compilerPath;
|
||||
const filePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}');
|
||||
const compilerPathBase: string = path.basename(compilerPath);
|
||||
const taskName: string = compilerPathBase + " build active file";
|
||||
const isCl: boolean = taskName.startsWith("cl.exe");
|
||||
let args: string[] = isCl ? [ '/Zi', '/EHsc', '/Fe:', filePath + '.exe', '${file}' ] : ['-g', '${file}', '-o', filePath + (isWindows ? '.exe' : '')];
|
||||
if (compilerPathAndArgs.additionalArgs) {
|
||||
args = args.concat(compilerPathAndArgs.additionalArgs);
|
||||
}
|
||||
const cwd: string = isCl ? "" : path.dirname(compilerPath);
|
||||
const kind: BuildTaskDefinition = {
|
||||
type: 'shell',
|
||||
label: taskName,
|
||||
command: isCl ? compilerPathBase : compilerPath,
|
||||
args: args,
|
||||
options: isCl ? undefined : {"cwd": cwd},
|
||||
compilerPath: isCl ? compilerPathBase : compilerPath
|
||||
};
|
||||
|
||||
const command: vscode.ShellExecution = new vscode.ShellExecution(compilerPath, [...args], { cwd: cwd });
|
||||
const target: vscode.WorkspaceFolder = vscode.workspace.getWorkspaceFolder(clients.ActiveClient.RootUri);
|
||||
let task: vscode.Task = new vscode.Task(kind, target, taskName, taskSourceStr, command, '$gcc');
|
||||
task.definition = kind; // The constructor for vscode.Task will eat the definition. Reset it by reassigning.
|
||||
task.group = vscode.TaskGroup.Build;
|
||||
|
||||
if (!returnComplerPath) {
|
||||
delete task.definition.compilerPath;
|
||||
}
|
||||
|
||||
return task;
|
||||
});
|
||||
}
|
||||
|
||||
function onDidOpenTextDocument(document: vscode.TextDocument): void {
|
||||
if (document.languageId === "c" || document.languageId === "cpp") {
|
||||
onActivationEvent();
|
||||
@@ -107,7 +289,19 @@ function onActivationEvent(): void {
|
||||
|
||||
function realActivation(): void {
|
||||
if (new CppSettings().intelliSenseEngine === "Disabled") {
|
||||
throw new Error("Do not activate the extension when IntelliSense is disabled.");
|
||||
throw new Error(intelliSenseDisabledError);
|
||||
} else {
|
||||
console.log("activating extension");
|
||||
let checkForConflictingExtensions: PersistentState<boolean> = new PersistentState<boolean>("CPP." + util.packageJson.version + ".checkForConflictingExtensions", true);
|
||||
if (checkForConflictingExtensions.Value) {
|
||||
checkForConflictingExtensions.Value = false;
|
||||
let clangCommandAdapterActive: boolean = vscode.extensions.all.some((extension: vscode.Extension<any>, index: number, array: vscode.Extension<any>[]): boolean => {
|
||||
return extension.isActive && extension.id === "mitaki28.vscode-clang";
|
||||
});
|
||||
if (clangCommandAdapterActive) {
|
||||
telemetry.logLanguageServerEvent("conflictingExtension");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
realActivationOccurred = true;
|
||||
@@ -132,13 +326,17 @@ function realActivation(): void {
|
||||
disposables.push(vscode.window.onDidChangeActiveTextEditor(onDidChangeActiveTextEditor));
|
||||
disposables.push(vscode.window.onDidChangeTextEditorSelection(onDidChangeTextEditorSelection));
|
||||
disposables.push(vscode.window.onDidChangeVisibleTextEditors(onDidChangeVisibleTextEditors));
|
||||
disposables.push(vscode.window.onDidChangeTextEditorVisibleRanges(onDidChangeTextEditorVisibleRanges));
|
||||
|
||||
updateLanguageConfigurations();
|
||||
|
||||
reportMacCrashes();
|
||||
|
||||
|
||||
const settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
|
||||
if (settings.updateChannel === 'Insiders') {
|
||||
|
||||
if (settings.updateChannel === 'Default') {
|
||||
suggestInsidersChannel();
|
||||
} else if (settings.updateChannel === 'Insiders') {
|
||||
insiderUpdateTimer = setInterval(checkAndApplyUpdate, insiderUpdateTimerInterval, settings.updateChannel);
|
||||
checkAndApplyUpdate(settings.updateChannel);
|
||||
}
|
||||
@@ -158,9 +356,14 @@ export function updateLanguageConfigurations(): void {
|
||||
* workspace events
|
||||
*********************************************/
|
||||
|
||||
function onDidChangeSettings(): void {
|
||||
const changedActiveClientSettings: { [key: string] : string } = clients.ActiveClient.onDidChangeSettings();
|
||||
clients.forEach(client => client.onDidChangeSettings());
|
||||
function onDidChangeSettings(event: vscode.ConfigurationChangeEvent): void {
|
||||
let activeClient: Client = clients.ActiveClient;
|
||||
const changedActiveClientSettings: { [key: string] : string } = activeClient.onDidChangeSettings(event);
|
||||
clients.forEach(client => {
|
||||
if (client !== activeClient) {
|
||||
client.onDidChangeSettings(event);
|
||||
}
|
||||
});
|
||||
|
||||
const newUpdateChannel: string = changedActiveClientSettings['updateChannel'];
|
||||
if (newUpdateChannel) {
|
||||
@@ -169,7 +372,7 @@ function onDidChangeSettings(): void {
|
||||
} else if (newUpdateChannel === 'Insiders') {
|
||||
insiderUpdateTimer = setInterval(checkAndApplyUpdate, insiderUpdateTimerInterval);
|
||||
}
|
||||
|
||||
|
||||
checkAndApplyUpdate(newUpdateChannel);
|
||||
}
|
||||
}
|
||||
@@ -221,7 +424,30 @@ function onDidChangeTextEditorSelection(event: vscode.TextEditorSelectionChangeE
|
||||
}
|
||||
|
||||
function onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
|
||||
clients.forEach(client => client.onDidChangeVisibleTextEditors(editors));
|
||||
clients.forEach(client => {
|
||||
let editorsForThisClient: vscode.TextEditor[] = [];
|
||||
editors.forEach(editor => {
|
||||
if (editor.document.languageId === "c" || editor.document.languageId === "cpp") {
|
||||
if (clients.checkOwnership(client, editor.document)) {
|
||||
editorsForThisClient.push(editor);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (editorsForThisClient.length > 0) {
|
||||
client.onDidChangeVisibleTextEditors(editorsForThisClient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onDidChangeTextEditorVisibleRanges(textEditorVisibleRangesChangeEvent: vscode.TextEditorVisibleRangesChangeEvent): void {
|
||||
let languageId: String = textEditorVisibleRangesChangeEvent.textEditor.document.languageId;
|
||||
if (languageId === "c" || languageId === "cpp") {
|
||||
clients.forEach(client => {
|
||||
if (clients.checkOwnership(client, textEditorVisibleRangesChangeEvent.textEditor.document)) {
|
||||
client.onDidChangeTextEditorVisibleRanges(textEditorVisibleRangesChangeEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onInterval(): void {
|
||||
@@ -233,7 +459,15 @@ function onInterval(): void {
|
||||
* Install a VSIX package. This helper function will exist until VSCode offers a command to do so.
|
||||
* @param updateChannel The user's updateChannel setting.
|
||||
*/
|
||||
async function installVsix(vsixLocation: string, updateChannel: string): Promise<void> {
|
||||
function installVsix(vsixLocation: string): Thenable<void> {
|
||||
let userVersion: PackageVersion = new PackageVersion(vscode.version);
|
||||
|
||||
// 1.33.0 introduces workbench.extensions.installExtension. 1.32.3 was immediately prior.
|
||||
let lastVersionWithoutInstallExtensionCommand: PackageVersion = new PackageVersion('1.32.3');
|
||||
if (userVersion.isGreaterThan(lastVersionWithoutInstallExtensionCommand)) {
|
||||
return vscode.commands.executeCommand('workbench.extensions.installExtension', vscode.Uri.file(vsixLocation));
|
||||
}
|
||||
|
||||
// Get the path to the VSCode command -- replace logic later when VSCode allows calling of
|
||||
// workbench.extensions.action.installVSIX from TypeScript w/o instead popping up a file dialog
|
||||
return PlatformInformation.GetPlatformInformation().then((platformInfo) => {
|
||||
@@ -267,14 +501,28 @@ async function installVsix(vsixLocation: string, updateChannel: string): Promise
|
||||
return Promise.reject(new Error('Failed to find VS Code script'));
|
||||
}
|
||||
|
||||
// 1.28.0 changes the CLI for making installations
|
||||
let userVersion: PackageVersion = new PackageVersion(vscode.version);
|
||||
let breakingVersion: PackageVersion = new PackageVersion('1.28.0');
|
||||
if (userVersion.isGreaterThan(breakingVersion, 'insider')) {
|
||||
// 1.28.0 changes the CLI for making installations. 1.27.2 was immediately prior.
|
||||
let oldVersion: PackageVersion = new PackageVersion('1.27.2');
|
||||
if (userVersion.isGreaterThan(oldVersion)) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
let process: ChildProcess;
|
||||
try {
|
||||
process = spawn(vsCodeScriptPath, ['--install-extension', vsixLocation, '--force']);
|
||||
|
||||
// Timeout the process if no response is sent back. Ensures this Promise resolves/rejects
|
||||
const timer: NodeJS.Timer = setTimeout(() => {
|
||||
process.kill();
|
||||
reject(new Error('Failed to receive response from VS Code script process for installation within 30s.'));
|
||||
}, 30000);
|
||||
|
||||
process.on('exit', (code: number) => {
|
||||
clearInterval(timer);
|
||||
if (code !== 0) {
|
||||
reject(new Error(`VS Code script exited with error code ${code}`));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
if (process.pid === undefined) {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -282,7 +530,6 @@ async function installVsix(vsixLocation: string, updateChannel: string): Promise
|
||||
reject(new Error('Failed to launch VS Code script process for installation'));
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -320,78 +567,99 @@ async function installVsix(vsixLocation: string, updateChannel: string): Promise
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query package.json and the GitHub API to determine whether the user should update, if so then install the update.
|
||||
* The update can be an upgrade or downgrade depending on the the updateChannel setting.
|
||||
* @param updateChannel The user's updateChannel setting.
|
||||
*/
|
||||
async function checkAndApplyUpdate(updateChannel: string): Promise<void> {
|
||||
// Wrap in new Promise to allow tmp.file callback to successfully resolve/reject
|
||||
// as tmp.file does not do anything with the callback functions return value
|
||||
const p: Promise<void> = new Promise<void>((resolve, reject) => {
|
||||
getTargetBuildInfo(updateChannel).then(buildInfo => {
|
||||
if (!buildInfo) {
|
||||
resolve();
|
||||
async function suggestInsidersChannel(): Promise<void> {
|
||||
let suggestInsiders: PersistentState<boolean> = new PersistentState<boolean>("CPP.suggestInsiders", true);
|
||||
|
||||
if (!suggestInsiders.Value) {
|
||||
return;
|
||||
}
|
||||
let buildInfo: BuildInfo;
|
||||
try {
|
||||
buildInfo = await getTargetBuildInfo("Insiders");
|
||||
} catch (error) {
|
||||
console.log(`${cppInstallVsixStr}${error.message}`);
|
||||
if (error.message.indexOf('/') !== -1 || error.message.indexOf('\\') !== -1) {
|
||||
error.message = "Potential PII hidden";
|
||||
}
|
||||
telemetry.logLanguageServerEvent('suggestInsiders', { 'error': error.message, 'success': 'false' });
|
||||
}
|
||||
if (!buildInfo) {
|
||||
return; // No need to update.
|
||||
}
|
||||
const message: string = `Insiders version ${buildInfo.name} is available. Would you like to switch to the Insiders channel and install this update?`;
|
||||
const yes: string = "Yes";
|
||||
const askLater: string = "Ask Me Later";
|
||||
const dontShowAgain: string = "Don't Show Again";
|
||||
let selection: string = await vscode.window.showInformationMessage(message, yes, askLater, dontShowAgain);
|
||||
switch (selection) {
|
||||
case yes:
|
||||
// Cache buildInfo.
|
||||
buildInfoCache = buildInfo;
|
||||
// It will call onDidChangeSettings.
|
||||
vscode.workspace.getConfiguration("C_Cpp").update("updateChannel", "Insiders", vscode.ConfigurationTarget.Global);
|
||||
break;
|
||||
case dontShowAgain:
|
||||
suggestInsiders.Value = false;
|
||||
break;
|
||||
case askLater:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function applyUpdate(buildInfo: BuildInfo): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
tmp.file({postfix: '.vsix'}, async (err, vsixPath, fd, cleanupCallback) => {
|
||||
if (err) {
|
||||
reject(new Error('Failed to create vsix file'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a temporary file, download the VSIX to it, then install the VSIX
|
||||
tmp.file({postfix: '.vsix'}, async (err, vsixPath, fd, cleanupCallback) => {
|
||||
if (err) {
|
||||
reject(new Error('Failed to create vsix file'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Place in try/catch as the .catch call catches a rejection in downloadFileToDestination
|
||||
// then the .catch call will return a resolved promise
|
||||
// Thusly, the .catch call must also throw, as a return would simply return an unused promise
|
||||
// instead of returning early from this function scope
|
||||
let config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
|
||||
let originalProxySupport: string = config.inspect<string>('http.proxySupport').globalValue;
|
||||
while (true) { // Might need to try again with a different http.proxySupport setting.
|
||||
try {
|
||||
await util.downloadFileToDestination(buildInfo.downloadUrl, vsixPath);
|
||||
} catch {
|
||||
// Try again with the proxySupport to "off".
|
||||
if (originalProxySupport !== config.inspect<string>('http.proxySupport').globalValue) {
|
||||
config.update('http.proxySupport', originalProxySupport, true); // Reset the http.proxySupport.
|
||||
reject(new Error('Failed to download VSIX package with proxySupport off')); // Changing the proxySupport didn't help.
|
||||
return;
|
||||
}
|
||||
if (config.get('http.proxySupport') !== "off" && originalProxySupport !== "off") {
|
||||
config.update('http.proxySupport', "off", true);
|
||||
continue;
|
||||
}
|
||||
reject(new Error('Failed to download VSIX package'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Place in try/catch as the .catch call catches a rejection in downloadFileToDestination
|
||||
// then the .catch call will return a resolved promise
|
||||
// Thusly, the .catch call must also throw, as a return would simply return an unused promise
|
||||
// instead of returning early from this function scope
|
||||
let config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
|
||||
let originalProxySupport: string = config.inspect<string>('http.proxySupport').globalValue;
|
||||
while (true) { // Might need to try again with a different http.proxySupport setting.
|
||||
try {
|
||||
await util.downloadFileToDestination(buildInfo.downloadUrl, vsixPath);
|
||||
} catch {
|
||||
// Try again with the proxySupport to "off".
|
||||
if (originalProxySupport !== config.inspect<string>('http.proxySupport').globalValue) {
|
||||
config.update('http.proxySupport', originalProxySupport, true); // Reset the http.proxySupport.
|
||||
telemetry.logLanguageServerEvent('installVsix', { 'error': "Success with proxySupport off", 'success': 'true' });
|
||||
reject(new Error('Failed to download VSIX package with proxySupport off')); // Changing the proxySupport didn't help.
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
try {
|
||||
await installVsix(vsixPath, updateChannel);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
if (config.get('http.proxySupport') !== "off" && originalProxySupport !== "off") {
|
||||
config.update('http.proxySupport', "off", true);
|
||||
continue;
|
||||
}
|
||||
reject(new Error('Failed to download VSIX package'));
|
||||
return;
|
||||
}
|
||||
clearInterval(insiderUpdateTimer);
|
||||
const message: string =
|
||||
`The C/C++ Extension has been updated to version ${buildInfo.name}. Please reload the window for the changes to take effect.`;
|
||||
util.promptReloadWindow(message);
|
||||
telemetry.logLanguageServerEvent('installVsix', { 'success': 'true' });
|
||||
|
||||
resolve();
|
||||
});
|
||||
}, (error: Error) => {
|
||||
// Handle getTargetBuildInfo rejection
|
||||
reject(error);
|
||||
if (originalProxySupport !== config.inspect<string>('http.proxySupport').globalValue) {
|
||||
config.update('http.proxySupport', originalProxySupport, true); // Reset the http.proxySupport.
|
||||
telemetry.logLanguageServerEvent('installVsix', { 'error': "Success with proxySupport off", 'success': 'true' });
|
||||
}
|
||||
break;
|
||||
}
|
||||
try {
|
||||
await installVsix(vsixPath);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
clearInterval(insiderUpdateTimer);
|
||||
const message: string =
|
||||
`The C/C++ Extension has been updated to version ${buildInfo.name}. Please reload the window for the changes to take effect.`;
|
||||
util.promptReloadWindow(message);
|
||||
telemetry.logLanguageServerEvent('installVsix', { 'success': 'true' });
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
await p.catch((error: Error) => {
|
||||
// Handle .then following getTargetBuildInfo rejection
|
||||
}).catch(error => {
|
||||
console.error(`${cppInstallVsixStr}${error.message}`);
|
||||
if (error.message.indexOf('/') !== -1 || error.message.indexOf('\\') !== -1) {
|
||||
error.message = "Potential PII hidden";
|
||||
}
|
||||
@@ -399,11 +667,41 @@ async function checkAndApplyUpdate(updateChannel: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query package.json and the GitHub API to determine whether the user should update, if so then install the update.
|
||||
* The update can be an upgrade or downgrade depending on the the updateChannel setting.
|
||||
* @param updateChannel The user's updateChannel setting.
|
||||
*/
|
||||
async function checkAndApplyUpdate(updateChannel: string): Promise<void> {
|
||||
// If we have buildInfo cache, we should use it.
|
||||
let buildInfo: BuildInfo | null = buildInfoCache;
|
||||
// clear buildInfo cache.
|
||||
buildInfoCache = null;
|
||||
|
||||
if (!buildInfo) {
|
||||
try {
|
||||
buildInfo = await getTargetBuildInfo(updateChannel);
|
||||
} catch (error) {
|
||||
telemetry.logLanguageServerEvent('installVsix', { 'error': error.message, 'success': 'false' });
|
||||
}
|
||||
}
|
||||
if (!buildInfo) {
|
||||
return; // No need to update.
|
||||
}
|
||||
await applyUpdate(buildInfo);
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* registered commands
|
||||
*********************************************/
|
||||
let commandsRegistered: boolean = false;
|
||||
|
||||
function registerCommands(): void {
|
||||
export function registerCommands(): void {
|
||||
if (commandsRegistered) {
|
||||
return;
|
||||
}
|
||||
commandsRegistered = true;
|
||||
getTemporaryCommandRegistrarInstance().clearTempCommands();
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.Navigate', onNavigate));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.GoToDeclaration', onGoToDeclaration));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.PeekDeclaration', onPeekDeclaration));
|
||||
@@ -411,9 +709,12 @@ function registerCommands(): void {
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ResetDatabase', onResetDatabase));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationSelect', onSelectConfiguration));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationProviderSelect', onSelectConfigurationProvider));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEditJSON', onEditConfigurationJSON));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEditUI', onEditConfigurationUI));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEdit', onEditConfiguration));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.AddToIncludePath', onAddToIncludePath));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleErrorSquiggles', onToggleSquiggles));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.EnableErrorSquiggles', onEnableSquiggles));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.DisableErrorSquiggles', onDisableSquiggles));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleIncludeFallback', onToggleIncludeFallback));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleDimInactiveRegions', onToggleDimInactiveRegions));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ShowReleaseNotes', onShowReleaseNotes));
|
||||
@@ -421,6 +722,10 @@ function registerCommands(): void {
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ResumeParsing', onResumeParsing));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.ShowParsingCommands', onShowParsingCommands));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.TakeSurvey', onTakeSurvey));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.LogDiagnostics', onLogDiagnostics));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.RescanWorkspace', onRescanWorkspace));
|
||||
disposables.push(vscode.commands.registerCommand('cpptools.activeConfigName', onGetActiveConfigName));
|
||||
getTemporaryCommandRegistrarInstance().executeDelayedCommands();
|
||||
}
|
||||
|
||||
function onNavigate(): void {
|
||||
@@ -534,6 +839,26 @@ function onSelectConfigurationProvider(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function onEditConfigurationJSON(): void {
|
||||
onActivationEvent();
|
||||
telemetry.logLanguageServerEvent("SettingsCommand", { "palette": "json" }, null);
|
||||
if (!isFolderOpen()) {
|
||||
vscode.window.showInformationMessage('Open a folder first to edit configurations');
|
||||
} else {
|
||||
selectClient().then(client => client.handleConfigurationEditJSONCommand(), rejected => {});
|
||||
}
|
||||
}
|
||||
|
||||
function onEditConfigurationUI(): void {
|
||||
onActivationEvent();
|
||||
telemetry.logLanguageServerEvent("SettingsCommand", { "palette": "ui" }, null);
|
||||
if (!isFolderOpen()) {
|
||||
vscode.window.showInformationMessage('Open a folder first to edit configurations');
|
||||
} else {
|
||||
selectClient().then(client => client.handleConfigurationEditUICommand(), rejected => {});
|
||||
}
|
||||
}
|
||||
|
||||
function onEditConfiguration(): void {
|
||||
onActivationEvent();
|
||||
if (!isFolderOpen()) {
|
||||
@@ -553,11 +878,18 @@ function onAddToIncludePath(path: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
function onToggleSquiggles(): void {
|
||||
function onEnableSquiggles(): void {
|
||||
onActivationEvent();
|
||||
// This only applies to the active client.
|
||||
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
|
||||
settings.toggleSetting("errorSquiggles", "Enabled", "Disabled");
|
||||
settings.update<string>("errorSquiggles", "Enabled");
|
||||
}
|
||||
|
||||
function onDisableSquiggles(): void {
|
||||
onActivationEvent();
|
||||
// This only applies to the active client.
|
||||
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
|
||||
settings.update<string>("errorSquiggles", "Disabled");
|
||||
}
|
||||
|
||||
function onToggleIncludeFallback(): void {
|
||||
@@ -601,6 +933,20 @@ function onTakeSurvey(): void {
|
||||
vscode.commands.executeCommand('vscode.open', uri);
|
||||
}
|
||||
|
||||
function onGetActiveConfigName(): Thenable<string> {
|
||||
return clients.ActiveClient.getCurrentConfigName();
|
||||
}
|
||||
|
||||
function onLogDiagnostics(): void {
|
||||
onActivationEvent();
|
||||
clients.ActiveClient.logDiagnostics();
|
||||
}
|
||||
|
||||
function onRescanWorkspace(): void {
|
||||
onActivationEvent();
|
||||
clients.forEach(client => client.rescanFolder());
|
||||
}
|
||||
|
||||
function reportMacCrashes(): void {
|
||||
if (process.platform === "darwin") {
|
||||
prevCrashFile = "";
|
||||
@@ -657,6 +1003,16 @@ function handleCrashFileRead(err: NodeJS.ErrnoException, data: string): void {
|
||||
return logCrashTelemetry("readFile: " + err.code);
|
||||
}
|
||||
|
||||
// Extract the crashing process version, because the version might not match
|
||||
// if multiple VS Codes are running with different extension versions.
|
||||
let binaryVersion: string = "";
|
||||
let startVersion: number = data.indexOf("Version:");
|
||||
if (startVersion >= 0) {
|
||||
data = data.substr(startVersion);
|
||||
const binaryVersionMatches: string[] = data.match(/^Version:\s*(\d|\d*\.\d*\.\d*\.\d*)/);
|
||||
binaryVersion = binaryVersionMatches && binaryVersionMatches.length > 1 ? binaryVersionMatches[1] : "";
|
||||
}
|
||||
|
||||
// Extract the crashing thread's call stack.
|
||||
const crashStart: string = " Crashed:";
|
||||
let startCrash: number = data.indexOf(crashStart);
|
||||
@@ -675,16 +1031,17 @@ function handleCrashFileRead(err: NodeJS.ErrnoException, data: string): void {
|
||||
|
||||
// Get rid of the memory addresses (which breaks being able get a hit count for each crash call stack).
|
||||
data = data.replace(/0x................ /g, "");
|
||||
data = data.replace(/0x1........ \+ 0/g, "");
|
||||
|
||||
// Get rid of the process names on each line and just add it to the start.
|
||||
const process1: string = "Microsoft.VSCode.CPP.IntelliSense.Msvc.darwin\t";
|
||||
const process2: string = "Microsoft.VSCode.CPP.Extension.darwin\t";
|
||||
if (data.includes(process1)) {
|
||||
data = data.replace(new RegExp(process1, "g"), "");
|
||||
data = process1 + "\n" + data;
|
||||
data = `${process1}${binaryVersion}\n${data}`;
|
||||
} else if (data.includes(process2)) {
|
||||
data = data.replace(new RegExp(process2, "g"), "");
|
||||
data = process2 + "\n" + data;
|
||||
data = `${process2}${binaryVersion}\n${data}`;
|
||||
} else {
|
||||
return logCrashTelemetry("No process"); // Not expected, but just in case.
|
||||
}
|
||||
@@ -716,6 +1073,9 @@ export function deactivate(): Thenable<void> {
|
||||
disposables.forEach(d => d.dispose());
|
||||
languageConfigurations.forEach(d => d.dispose());
|
||||
ui.dispose();
|
||||
if (taskProvider) {
|
||||
taskProvider.dispose();
|
||||
}
|
||||
return clients.dispose();
|
||||
}
|
||||
|
||||
@@ -735,4 +1095,4 @@ export function getActiveClient(): Client {
|
||||
realActivation();
|
||||
}
|
||||
return clients.ActiveClient;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,24 @@ class PersistentStateBase<T> {
|
||||
private key: string;
|
||||
private defaultvalue: T;
|
||||
private state: vscode.Memento;
|
||||
private curvalue: T;
|
||||
|
||||
constructor(key: string, defaultValue: T, state: vscode.Memento) {
|
||||
this.key = key;
|
||||
this.defaultvalue = defaultValue;
|
||||
this.state = state;
|
||||
this.curvalue = defaultValue;
|
||||
}
|
||||
|
||||
public get Value(): T {
|
||||
return this.state.get<T>(this.key, this.defaultvalue);
|
||||
return this.state ? this.state.get<T>(this.key, this.defaultvalue) : this.curvalue;
|
||||
}
|
||||
|
||||
public set Value(newValue: T) {
|
||||
this.state.update(this.key, newValue);
|
||||
if (this.state) {
|
||||
this.state.update(this.key, newValue);
|
||||
}
|
||||
this.curvalue = newValue;
|
||||
}
|
||||
|
||||
public get DefaultValue(): T {
|
||||
@@ -35,13 +40,13 @@ class PersistentStateBase<T> {
|
||||
// Abstraction for global state that persists across activations but is not present in a settings file
|
||||
export class PersistentState<T> extends PersistentStateBase<T> {
|
||||
constructor(key: string, defaultValue: T) {
|
||||
super(key, defaultValue, util.extensionContext.globalState);
|
||||
super(key, defaultValue, util.extensionContext ? util.extensionContext.globalState : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class PersistentWorkspaceState<T> extends PersistentStateBase<T> {
|
||||
constructor(key: string, defaultValue: T) {
|
||||
super(key, defaultValue, util.extensionContext.workspaceState);
|
||||
super(key, defaultValue, util.extensionContext ? util.extensionContext.workspaceState : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import { Middleware } from 'vscode-languageclient';
|
||||
import { ClientCollection } from './clientCollection';
|
||||
import { Client } from './client';
|
||||
@@ -23,6 +24,15 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid
|
||||
didOpen: (document, sendMessage) => {
|
||||
if (clients.checkOwnership(me, document)) {
|
||||
me.TrackedDocuments.add(document);
|
||||
|
||||
// Work around vscode treating ".C" as c, by adding this file name to file associations as cpp
|
||||
if (document.uri.path.endsWith(".C")) {
|
||||
let fileName: string = path.basename(document.uri.fsPath);
|
||||
let mappingString: string = fileName + "@" + document.uri.fsPath;
|
||||
me.addFileAssociations(mappingString, false);
|
||||
}
|
||||
|
||||
me.onDidOpenTextDocument(document);
|
||||
me.provideCustomConfiguration(document).then(() => {
|
||||
sendMessage(document);
|
||||
}, () => {
|
||||
@@ -30,7 +40,12 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid
|
||||
});
|
||||
}
|
||||
},
|
||||
didChange: defaultHandler,
|
||||
didChange: (textDocumentChangeEvent, sendMessage) => {
|
||||
if (clients.ActiveClient === me) {
|
||||
me.onDidChangeTextDocument(textDocumentChangeEvent);
|
||||
me.notifyWhenReady(() => sendMessage(textDocumentChangeEvent));
|
||||
}
|
||||
},
|
||||
willSave: defaultHandler,
|
||||
willSaveWaitUntil: (event, sendMessage) => {
|
||||
if (clients.ActiveClient === me) {
|
||||
@@ -49,7 +64,12 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid
|
||||
|
||||
provideCompletionItem: invoke4,
|
||||
resolveCompletionItem: invoke2,
|
||||
provideHover: invoke3,
|
||||
provideHover: (document, position, token, next: (document, position, token) => any) => {
|
||||
if (clients.checkOwnership(me, document)) {
|
||||
return me.requestWhenReady(() => next(document, position, token));
|
||||
}
|
||||
return null;
|
||||
},
|
||||
provideSignatureHelp: invoke3,
|
||||
provideDefinition: invoke3,
|
||||
provideReferences: invoke4,
|
||||
|
||||
@@ -36,10 +36,12 @@ export class CppSettings extends Settings {
|
||||
public get clangFormatSortIncludes(): string { return super.Section.get<string>("clang_format_sortIncludes"); }
|
||||
public get clangFormatOnSave(): string { return super.Section.get<string>("clang_format_formatOnSave"); }
|
||||
public get formatting(): string { return super.Section.get<string>("formatting"); }
|
||||
public get suggestSnippets(): boolean { return super.Section.get<boolean>("suggestSnippets"); }
|
||||
public get intelliSenseEngine(): string { return super.Section.get<string>("intelliSenseEngine"); }
|
||||
public get intelliSenseEngineFallback(): string { return super.Section.get<string>("intelliSenseEngineFallback"); }
|
||||
public get intelliSenseCachePath(): string { return super.Section.get<string>("intelliSenseCachePath"); }
|
||||
public get intelliSenseCacheSize(): number { return super.Section.get<number>("intelliSenseCacheSize"); }
|
||||
public get errorSquiggles(): string { return super.Section.get<string>("errorSquiggles"); }
|
||||
public get dimInactiveRegions(): boolean { return super.Section.get<boolean>("dimInactiveRegions"); }
|
||||
public get inactiveRegionOpacity(): number { return super.Section.get<number>("inactiveRegionOpacity"); }
|
||||
public get inactiveRegionForegroundColor(): string { return super.Section.get<string>("inactiveRegionForegroundColor"); }
|
||||
public get inactiveRegionBackgroundColor(): string { return super.Section.get<string>("inactiveRegionBackgroundColor"); }
|
||||
@@ -69,6 +71,19 @@ export class CppSettings extends Settings {
|
||||
public get defaultDatabaseFilename(): string { return super.Section.get<string>("default.browse.databaseFilename"); }
|
||||
public get defaultLimitSymbolsToIncludedHeaders(): boolean { return super.Section.get<boolean>("default.browse.limitSymbolsToIncludedHeaders"); }
|
||||
public get defaultSystemIncludePath(): string[] { return super.Section.get<string[]>("default.systemIncludePath"); }
|
||||
public get defaultEnableConfigurationSquiggles(): boolean { return super.Section.get<boolean>("default.enableConfigurationSquiggles"); }
|
||||
|
||||
public get enhancedColorization(): boolean {
|
||||
return super.Section.get<string>("enhancedColorization") === "Enabled"
|
||||
&& super.Section.get<string>("intelliSenseEngine") === "Default"
|
||||
&& vscode.workspace.getConfiguration("workbench").get<string>("colorTheme") !== "Default High Contrast";
|
||||
}
|
||||
|
||||
public get dimInactiveRegions(): boolean {
|
||||
return super.Section.get<boolean>("dimInactiveRegions")
|
||||
&& super.Section.get<string>("intelliSenseEngine") === "Default"
|
||||
&& vscode.workspace.getConfiguration("workbench").get<string>("colorTheme") !== "Default High Contrast";
|
||||
}
|
||||
|
||||
public toggleSetting(name: string, value1: string, value2: string): void {
|
||||
let value: string = super.Section.get<string>(name);
|
||||
@@ -79,6 +94,17 @@ export class CppSettings extends Settings {
|
||||
}
|
||||
}
|
||||
|
||||
export interface TextMateRuleSettings {
|
||||
foreground: string | undefined;
|
||||
background: string | undefined;
|
||||
fontStyle: string | undefined;
|
||||
}
|
||||
|
||||
export interface TextMateRule {
|
||||
scope: any;
|
||||
settings: TextMateRuleSettings;
|
||||
}
|
||||
|
||||
export class OtherSettings {
|
||||
private resource: vscode.Uri;
|
||||
|
||||
@@ -89,12 +115,21 @@ export class OtherSettings {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public get editorTabSize(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("editor", this.resource).get("tabSize"); }
|
||||
public get editorTabSize(): number { return vscode.workspace.getConfiguration("editor", this.resource).get<number>("tabSize"); }
|
||||
public get filesAssociations(): any { return vscode.workspace.getConfiguration("files", null).get("associations"); }
|
||||
public get filesExclude(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); }
|
||||
public get searchExclude(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); }
|
||||
public get settingsEditor(): string { return vscode.workspace.getConfiguration("workbench.settings").get<string>("editor"); }
|
||||
|
||||
public get colorTheme(): string { return vscode.workspace.getConfiguration("workbench").get<string>("colorTheme"); }
|
||||
|
||||
public getCustomColorToken(colorTokenName: string): string { return vscode.workspace.getConfiguration("editor.tokenColorCustomizations").get<string>(colorTokenName); }
|
||||
public getCustomThemeSpecificColorToken(themeName: string, colorTokenName: string): string { return vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource).get<string>(colorTokenName); }
|
||||
|
||||
public get customTextMateRules(): TextMateRule[] { return vscode.workspace.getConfiguration("editor.tokenColorCustomizations").get<TextMateRule[]>("textMateRules"); }
|
||||
public getCustomThemeSpecificTextMateRules(themeName: string): TextMateRule[] { return vscode.workspace.getConfiguration(`editor.tokenColorCustomizations.[${themeName}]`, this.resource).get<TextMateRule[]>("textMateRules"); }
|
||||
|
||||
public set filesAssociations(value: any) {
|
||||
vscode.workspace.getConfiguration("files", null).update("associations", value, vscode.ConfigurationTarget.Workspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as vscode from 'vscode';
|
||||
import * as util from '../common';
|
||||
import * as config from './configurations';
|
||||
import * as telemetry from '../telemetry';
|
||||
|
||||
// TODO: share ElementId between SettingsPanel and SettingsApp. Investigate why SettingsApp cannot import/export
|
||||
const elementId: { [key: string]: string } = {
|
||||
// Basic settings
|
||||
configName: "configName",
|
||||
configSelection: "configSelection",
|
||||
addConfigBtn: "addConfigBtn",
|
||||
addConfigOk: "addConfigOk",
|
||||
addConfigCancel: "addConfigCancel",
|
||||
addConfigName: "addConfigName",
|
||||
|
||||
compilerPath: "compilerPath",
|
||||
compilerPathInvalid: "compilerPathInvalid",
|
||||
knownCompilers: "knownCompilers",
|
||||
|
||||
intelliSenseMode: "intelliSenseMode",
|
||||
intelliSenseModeInvalid: "intelliSenseModeInvalid",
|
||||
includePath: "includePath",
|
||||
includePathInvalid: "includePathInvalid",
|
||||
defines: "defines",
|
||||
cStandard: "cStandard",
|
||||
cppStandard: "cppStandard",
|
||||
|
||||
// Advanced settings
|
||||
windowsSdkVersion: "windowsSdkVersion",
|
||||
macFrameworkPath: "macFrameworkPath",
|
||||
compileCommands: "compileCommands",
|
||||
configurationProvider: "configurationProvider",
|
||||
forcedInclude: "forcedInclude",
|
||||
|
||||
// Browse properties
|
||||
browsePath: "browsePath",
|
||||
limitSymbolsToIncludedHeaders: "limitSymbolsToIncludedHeaders",
|
||||
databaseFilename: "databaseFilename",
|
||||
|
||||
// Other
|
||||
showAdvancedBtn: "showAdvancedBtn"
|
||||
};
|
||||
|
||||
export class SettingsPanel {
|
||||
private telemetry: { [key: string]: number } = {};
|
||||
private disposable: vscode.Disposable = undefined;
|
||||
|
||||
// Events
|
||||
private settingsPanelActivated = new vscode.EventEmitter<void>();
|
||||
private configValuesChanged = new vscode.EventEmitter<void>();
|
||||
private configSelectionChanged = new vscode.EventEmitter<void>();
|
||||
private addConfigRequested = new vscode.EventEmitter<string>();
|
||||
|
||||
// Configuration data
|
||||
private configValues: config.Configuration;
|
||||
private isIntelliSenseModeDefined: boolean = false;
|
||||
private configIndexSelected: number = 0;
|
||||
private compilerPaths: string[] = [];
|
||||
|
||||
// WebviewPanel objects
|
||||
private panel: vscode.WebviewPanel;
|
||||
private disposablesPanel: vscode.Disposable = undefined;
|
||||
private static readonly viewType: string = 'settingsPanel';
|
||||
private static readonly title: string = 'C/C++ Configurations';
|
||||
|
||||
constructor() {
|
||||
this.configValues = { name: undefined };
|
||||
this.disposable = vscode.Disposable.from(
|
||||
this.settingsPanelActivated,
|
||||
this.configValuesChanged,
|
||||
this.configSelectionChanged,
|
||||
this.addConfigRequested
|
||||
);
|
||||
}
|
||||
|
||||
public createOrShow(configSelection: string[], activeConfiguration: config.Configuration, errors: config.ConfigurationErrors): void {
|
||||
const column: vscode.ViewColumn = vscode.window.activeTextEditor
|
||||
? vscode.window.activeTextEditor.viewColumn
|
||||
: undefined;
|
||||
|
||||
// Show existing panel
|
||||
if (this.panel) {
|
||||
this.panel.reveal(column, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new panel
|
||||
this.panel = vscode.window.createWebviewPanel(
|
||||
SettingsPanel.viewType,
|
||||
SettingsPanel.title,
|
||||
column || vscode.ViewColumn.One,
|
||||
{
|
||||
enableCommandUris: true,
|
||||
enableScripts: true,
|
||||
|
||||
// Restrict the webview to only loading content from these directories
|
||||
localResourceRoots: [
|
||||
vscode.Uri.file(util.extensionPath),
|
||||
vscode.Uri.file(path.join(util.extensionPath, 'ui')),
|
||||
vscode.Uri.file(path.join(util.extensionPath, 'out', 'ui'))]
|
||||
}
|
||||
);
|
||||
|
||||
this.panel.iconPath = vscode.Uri.file(util.getExtensionFilePath("LanguageCCPP_color_128x.png"));
|
||||
|
||||
this.disposablesPanel = vscode.Disposable.from(
|
||||
this.panel,
|
||||
this.panel.onDidDispose(this.onPanelDisposed, this),
|
||||
this.panel.onDidChangeViewState(this.onViewStateChanged, this),
|
||||
this.panel.webview.onDidReceiveMessage(this.onMessageReceived, this),
|
||||
vscode.window.onDidChangeWindowState(this.onWindowStateChanged, this)
|
||||
);
|
||||
|
||||
this.panel.webview.html = this.getHtml();
|
||||
|
||||
this.updateWebview(configSelection, activeConfiguration, errors);
|
||||
}
|
||||
|
||||
public get SettingsPanelActivated(): vscode.Event<void> {
|
||||
return this.settingsPanelActivated.event;
|
||||
}
|
||||
|
||||
public get ConfigValuesChanged(): vscode.Event<void> {
|
||||
return this.configValuesChanged.event;
|
||||
}
|
||||
|
||||
public get ConfigSelectionChanged(): vscode.Event<void> {
|
||||
return this.configSelectionChanged.event;
|
||||
}
|
||||
|
||||
public get AddConfigRequested(): vscode.Event<string> {
|
||||
return this.addConfigRequested.event;
|
||||
}
|
||||
|
||||
public get selectedConfigIndex(): number {
|
||||
return this.configIndexSelected;
|
||||
}
|
||||
|
||||
public set selectedConfigIndex(index: number) {
|
||||
this.configIndexSelected = index;
|
||||
}
|
||||
|
||||
public getLastValuesFromConfigUI(): config.Configuration {
|
||||
return this.configValues;
|
||||
}
|
||||
|
||||
public updateConfigUI(configSelection: string[], configuration: config.Configuration, errors: config.ConfigurationErrors|null): void {
|
||||
if (this.panel) {
|
||||
this.updateWebview(configSelection, configuration, errors);
|
||||
}
|
||||
}
|
||||
|
||||
public setKnownCompilers(knownCompilers: config.KnownCompiler[], pathSeparator: string): void {
|
||||
if (knownCompilers.length > 0) {
|
||||
for (let compiler of knownCompilers) {
|
||||
// Normalize path separators.
|
||||
let path: string = compiler.path;
|
||||
if (pathSeparator === "Forward Slash") {
|
||||
path = path.replace(/\\/g, '/');
|
||||
} else {
|
||||
path = path.replace(/\//g, '\\');
|
||||
}
|
||||
// Do not add duplicate paths in case the default compilers for cpp and c are the same.
|
||||
if (this.compilerPaths.indexOf(path) === -1) {
|
||||
this.compilerPaths.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public updateErrors(errors: config.ConfigurationErrors): void {
|
||||
if (this.panel) {
|
||||
this.panel.webview.postMessage({ command: 'updateErrors', errors: errors});
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
// Log any telemetry
|
||||
if (Object.keys(this.telemetry).length > 0) {
|
||||
telemetry.logLanguageServerEvent("ConfigUI", null, this.telemetry);
|
||||
}
|
||||
|
||||
// Clean up resources
|
||||
this.panel.dispose();
|
||||
|
||||
if (this.disposable) {
|
||||
this.disposable.dispose();
|
||||
}
|
||||
|
||||
if (this.disposablesPanel) {
|
||||
this.disposablesPanel.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private onPanelDisposed(): void {
|
||||
if (this.disposablesPanel) {
|
||||
this.disposablesPanel.dispose();
|
||||
this.panel = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private updateWebview(configSelection: string[], configuration: config.Configuration, errors: config.ConfigurationErrors|null): void {
|
||||
this.configValues = Object.assign({}, configuration); // Copy configuration values
|
||||
this.isIntelliSenseModeDefined = (this.configValues.intelliSenseMode !== undefined);
|
||||
if (this.panel) {
|
||||
this.panel.webview.postMessage({ command: 'setKnownCompilers', compilers: this.compilerPaths});
|
||||
this.panel.webview.postMessage({ command: 'updateConfigSelection', selections: configSelection, selectedIndex: this.configIndexSelected});
|
||||
this.panel.webview.postMessage({ command: 'updateConfig', config: this.configValues});
|
||||
if (errors !== null) {
|
||||
this.panel.webview.postMessage({ command: 'updateErrors', errors: errors});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onViewStateChanged(e: vscode.WebviewPanelOnDidChangeViewStateEvent): void {
|
||||
if (e.webviewPanel.active) {
|
||||
this.settingsPanelActivated.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private onWindowStateChanged(e: vscode.WindowState): void {
|
||||
if (e.focused) {
|
||||
this.settingsPanelActivated.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private onMessageReceived(message: any): void {
|
||||
if (message === null) {
|
||||
return;
|
||||
}
|
||||
switch (message.command) {
|
||||
case 'change':
|
||||
this.updateConfig(message);
|
||||
break;
|
||||
case 'configSelect':
|
||||
this.configSelect(message.index);
|
||||
break;
|
||||
case 'addConfig':
|
||||
this.addConfig(message.name);
|
||||
break;
|
||||
case 'knownCompilerSelect':
|
||||
this.knownCompilerSelect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private addConfig(name: string): void {
|
||||
this.addConfigRequested.fire(name);
|
||||
this.logTelemetryForElement(elementId.addConfigName);
|
||||
}
|
||||
|
||||
private configSelect(index: number): void {
|
||||
this.configIndexSelected = index;
|
||||
this.configSelectionChanged.fire();
|
||||
this.logTelemetryForElement(elementId.configSelection);
|
||||
}
|
||||
|
||||
private knownCompilerSelect(): void {
|
||||
this.logTelemetryForElement(elementId.knownCompilers);
|
||||
// Remove one count from compilerPath because selecting a different compiler causes a change on the compiler path
|
||||
if (this.telemetry[elementId.compilerPath]) {
|
||||
this.telemetry[elementId.compilerPath]--;
|
||||
}
|
||||
}
|
||||
|
||||
private updateConfig(message: any): void {
|
||||
let splitEntries: (input: any) => string[] = (input: any) => {
|
||||
return input.split("\n").filter((e: string) => e);
|
||||
};
|
||||
|
||||
switch (message.key) {
|
||||
case elementId.configName:
|
||||
this.configValues.name = message.value;
|
||||
break;
|
||||
case elementId.compilerPath:
|
||||
this.configValues.compilerPath = message.value;
|
||||
break;
|
||||
case elementId.includePath:
|
||||
this.configValues.includePath = splitEntries(message.value);
|
||||
break;
|
||||
case elementId.defines:
|
||||
this.configValues.defines = splitEntries(message.value);
|
||||
break;
|
||||
case elementId.intelliSenseMode:
|
||||
if (message.value !== "${default}" || this.isIntelliSenseModeDefined) {
|
||||
this.configValues.intelliSenseMode = message.value;
|
||||
} else {
|
||||
this.configValues.intelliSenseMode = undefined;
|
||||
}
|
||||
break;
|
||||
case elementId.cStandard:
|
||||
this.configValues.cStandard = message.value;
|
||||
break;
|
||||
case elementId.cppStandard:
|
||||
this.configValues.cppStandard = message.value;
|
||||
break;
|
||||
case elementId.windowsSdkVersion:
|
||||
this.configValues.windowsSdkVersion = message.value;
|
||||
break;
|
||||
case elementId.macFrameworkPath:
|
||||
this.configValues.macFrameworkPath = splitEntries(message.value);
|
||||
break;
|
||||
case elementId.compileCommands:
|
||||
this.configValues.compileCommands = message.value;
|
||||
break;
|
||||
case elementId.configurationProvider:
|
||||
this.configValues.configurationProvider = message.value;
|
||||
break;
|
||||
case elementId.forcedInclude:
|
||||
this.configValues.forcedInclude = splitEntries(message.value);
|
||||
break;
|
||||
case elementId.browsePath:
|
||||
this.initializeBrowseProperties();
|
||||
this.configValues.browse.path = splitEntries(message.value);
|
||||
break;
|
||||
case elementId.limitSymbolsToIncludedHeaders:
|
||||
this.initializeBrowseProperties();
|
||||
this.configValues.browse.limitSymbolsToIncludedHeaders = message.value;
|
||||
break;
|
||||
case elementId.databaseFilename:
|
||||
this.initializeBrowseProperties();
|
||||
this.configValues.browse.databaseFilename = message.value;
|
||||
break;
|
||||
}
|
||||
|
||||
this.configValuesChanged.fire();
|
||||
this.logTelemetryForElement(message.key);
|
||||
}
|
||||
|
||||
private logTelemetryForElement(elementId: string): void {
|
||||
if (this.telemetry[elementId] === undefined) {
|
||||
this.telemetry[elementId] = 0;
|
||||
}
|
||||
this.telemetry[elementId]++;
|
||||
}
|
||||
|
||||
private initializeBrowseProperties(): void {
|
||||
if (this.configValues.browse === undefined) {
|
||||
this.configValues.browse = {};
|
||||
}
|
||||
}
|
||||
|
||||
private getHtml(): string {
|
||||
let content: string | undefined;
|
||||
content = fs.readFileSync(util.getExtensionFilePath("ui/settings.html")).toString();
|
||||
|
||||
content = content.replace(
|
||||
/{{root}}/g,
|
||||
vscode.Uri.file(util.extensionPath)
|
||||
.with({ scheme: 'vscode-resource' })
|
||||
.toString());
|
||||
|
||||
content = content.replace(
|
||||
/{{nonce}}/g,
|
||||
this.getNonce());
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
private getNonce(): string {
|
||||
let nonce: string;
|
||||
const possible: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for (let i: number = 0; i < 32; i++) {
|
||||
nonce += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
}
|
||||
return nonce;
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ export class SettingsTracker {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (key === "clang_format_path" || key.startsWith("default.")) {
|
||||
if (key === "clang_format_path" || key === "intelliSenseCachePath" || key.startsWith("default.")) {
|
||||
value = this.areEqual(val, settings.inspect(key).defaultValue) ? "<default>" : "..."; // Track whether it's being used, but nothing specific about it.
|
||||
} else {
|
||||
value = String(this.previousCppSettings[key]);
|
||||
|
||||
@@ -171,7 +171,8 @@ export class UI {
|
||||
for (let i: number = 0; i < configurationNames.length; i++) {
|
||||
items.push({ label: configurationNames[i], description: "", index: i });
|
||||
}
|
||||
items.push({ label: "Edit Configurations...", description: "", index: configurationNames.length });
|
||||
items.push({ label: "Edit Configurations (UI)", description: "", index: configurationNames.length });
|
||||
items.push({ label: "Edit Configurations (JSON)", description: "", index: configurationNames.length + 1 });
|
||||
|
||||
return vscode.window.showQuickPick(items, options)
|
||||
.then(selection => (selection) ? selection.index : -1);
|
||||
|
||||
@@ -17,6 +17,7 @@ interface Settings {
|
||||
defaultIntelliSenseEngine?: number;
|
||||
recursiveIncludes?: number;
|
||||
gotoDefIntelliSense?: number;
|
||||
enhancedColorization?: number;
|
||||
}
|
||||
|
||||
export class ABTestSettings {
|
||||
@@ -24,16 +25,19 @@ export class ABTestSettings {
|
||||
private intelliSenseEngineDefault: PersistentState<number>;
|
||||
private recursiveIncludesDefault: PersistentState<number>;
|
||||
private gotoDefIntelliSenseDefault: PersistentState<number>;
|
||||
private enhancedColorizationDefault: PersistentState<number>;
|
||||
private bucket: PersistentState<number>;
|
||||
|
||||
constructor() {
|
||||
this.intelliSenseEngineDefault = new PersistentState<number>("ABTest.1", 100);
|
||||
this.recursiveIncludesDefault = new PersistentState<number>("ABTest.2", 100);
|
||||
this.gotoDefIntelliSenseDefault = new PersistentState<number>("ABTest.3", 100);
|
||||
this.enhancedColorizationDefault = new PersistentState<number>("ABTest.4", 100);
|
||||
this.settings = {
|
||||
defaultIntelliSenseEngine: this.intelliSenseEngineDefault.Value,
|
||||
recursiveIncludes: this.recursiveIncludesDefault.Value,
|
||||
gotoDefIntelliSense: this.gotoDefIntelliSenseDefault.Value
|
||||
gotoDefIntelliSense: this.gotoDefIntelliSenseDefault.Value,
|
||||
enhancedColorization: this.enhancedColorizationDefault.Value
|
||||
};
|
||||
this.bucket = new PersistentState<number>(userBucketString, -1);
|
||||
if (this.bucket.Value === -1) {
|
||||
@@ -61,6 +65,10 @@ export class ABTestSettings {
|
||||
return util.isNumber(this.settings.gotoDefIntelliSense) ? this.settings.gotoDefIntelliSense >= this.bucket.Value : true;
|
||||
}
|
||||
|
||||
public get UseEnhancedColorization(): boolean {
|
||||
return util.isNumber(this.settings.enhancedColorization) ? this.settings.enhancedColorization >= this.bucket.Value : true;
|
||||
}
|
||||
|
||||
private updateSettings(): void {
|
||||
const cpptoolsJsonFile: string = util.getExtensionFilePath(localConfigFile);
|
||||
|
||||
@@ -72,10 +80,12 @@ export class ABTestSettings {
|
||||
this.intelliSenseEngineDefault.Value = util.isNumber(newSettings.defaultIntelliSenseEngine) ? newSettings.defaultIntelliSenseEngine : this.intelliSenseEngineDefault.DefaultValue;
|
||||
this.recursiveIncludesDefault.Value = util.isNumber(newSettings.recursiveIncludes) ? newSettings.recursiveIncludes : this.recursiveIncludesDefault.DefaultValue;
|
||||
this.gotoDefIntelliSenseDefault.Value = util.isNumber(newSettings.gotoDefIntelliSense) ? newSettings.gotoDefIntelliSense : this.gotoDefIntelliSenseDefault.DefaultValue;
|
||||
this.enhancedColorizationDefault.Value = util.isNumber(newSettings.enhancedColorization) ? newSettings.enhancedColorization : this.enhancedColorizationDefault.DefaultValue;
|
||||
this.settings = {
|
||||
defaultIntelliSenseEngine: this.intelliSenseEngineDefault.Value,
|
||||
recursiveIncludes: this.recursiveIncludesDefault.Value,
|
||||
gotoDefIntelliSense: this.gotoDefIntelliSenseDefault.Value
|
||||
gotoDefIntelliSense: this.gotoDefIntelliSenseDefault.Value,
|
||||
enhancedColorization: this.enhancedColorizationDefault.Value
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -87,7 +97,7 @@ export class ABTestSettings {
|
||||
let hasError: boolean = false;
|
||||
let telemetryProperties: { [key: string]: string } = {};
|
||||
const localConfigPath: string = util.getExtensionFilePath(localConfigFile);
|
||||
return util.downloadFileToDestination("https://go.microsoft.com/fwlink/?linkid=2026205", localConfigPath)
|
||||
return util.downloadFileToDestination("https://go.microsoft.com/fwlink/?linkid=2097702", localConfigPath)
|
||||
.catch((error) => {
|
||||
// More specific error info is not likely to be helpful, and we get detailed download data from the initial install.
|
||||
hasError = true;
|
||||
|
||||
@@ -6,22 +6,26 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as LanguageServer from './LanguageServer/extension';
|
||||
import * as util from './common';
|
||||
|
||||
class TemporaryCommandRegistrar {
|
||||
// Used to save/re-execute commands used before the extension has activated (e.g. delayed by dependency downloading).
|
||||
private delayedCommandsToExecute: Set<string>;
|
||||
private tempCommands: vscode.Disposable[]; // Need to save this to unregister/dispose the temporary commands.
|
||||
private isLanguageServerDisabled: boolean;
|
||||
private isLanguageServerDisabled: boolean = false;
|
||||
private isActivationReady: boolean = false;
|
||||
|
||||
private commandsToRegister: string[] = [
|
||||
"C_Cpp.ConfigurationEdit",
|
||||
"C_Cpp.ConfigurationEditJSON",
|
||||
"C_Cpp.ConfigurationEditUI",
|
||||
"C_Cpp.ConfigurationSelect",
|
||||
"C_Cpp.ConfigurationProviderSelect",
|
||||
"C_Cpp.SwitchHeaderSource",
|
||||
"C_Cpp.Navigate",
|
||||
"C_Cpp.GoToDeclaration",
|
||||
"C_Cpp.PeekDeclaration",
|
||||
"C_Cpp.ToggleErrorSquiggles",
|
||||
"C_Cpp.EnableErrorSquiggles",
|
||||
"C_Cpp.DisableErrorSquiggles",
|
||||
"C_Cpp.ToggleIncludeFallback",
|
||||
"C_Cpp.ToggleDimInactiveRegions",
|
||||
"C_Cpp.ShowReleaseNotes",
|
||||
@@ -29,7 +33,9 @@ class TemporaryCommandRegistrar {
|
||||
"C_Cpp.PauseParsing",
|
||||
"C_Cpp.ResumeParsing",
|
||||
"C_Cpp.ShowParsingCommands",
|
||||
"C_Cpp.TakeSurvey"
|
||||
"C_Cpp.TakeSurvey",
|
||||
"C_Cpp.LogDiagnostics",
|
||||
"C_Cpp.RescanWorkspace",
|
||||
];
|
||||
|
||||
constructor() {
|
||||
@@ -37,9 +43,11 @@ class TemporaryCommandRegistrar {
|
||||
this.delayedCommandsToExecute = new Set<string>();
|
||||
|
||||
// Add temp commands that invoke the real commands after download/install is complete (preventing an error message)
|
||||
this.commandsToRegister.forEach(command => {
|
||||
this.registerTempCommand(command);
|
||||
});
|
||||
if (util.extensionContext) {
|
||||
this.commandsToRegister.forEach(command => {
|
||||
this.registerTempCommand(command);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public registerTempCommand(command: string): void {
|
||||
@@ -49,6 +57,9 @@ class TemporaryCommandRegistrar {
|
||||
return;
|
||||
}
|
||||
this.delayedCommandsToExecute.add(command);
|
||||
if (this.isActivationReady) {
|
||||
LanguageServer.activate(true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -58,13 +69,18 @@ class TemporaryCommandRegistrar {
|
||||
|
||||
public activateLanguageServer(): void {
|
||||
// Main activation code.
|
||||
LanguageServer.activate(this.delayedCommandsToExecute.size > 0);
|
||||
this.isActivationReady = true;
|
||||
}
|
||||
|
||||
public clearTempCommands(): void {
|
||||
this.tempCommands.forEach((command) => {
|
||||
command.dispose();
|
||||
});
|
||||
this.tempCommands = [];
|
||||
}
|
||||
|
||||
LanguageServer.activate(this.delayedCommandsToExecute.size > 0);
|
||||
|
||||
public executeDelayedCommands(): void {
|
||||
this.delayedCommandsToExecute.forEach((command) => {
|
||||
vscode.commands.executeCommand(command);
|
||||
});
|
||||
|
||||
+242
-9
@@ -16,11 +16,20 @@ import { getOutputChannelLogger, showOutputChannel } from './logger';
|
||||
import * as assert from 'assert';
|
||||
import * as https from 'https';
|
||||
import { ClientRequest, OutgoingHttpHeaders } from 'http';
|
||||
import { getBuildTasks } from './LanguageServer/extension';
|
||||
import { OtherSettings } from './LanguageServer/settings';
|
||||
|
||||
export let extensionPath: string;
|
||||
export let extensionContext: vscode.ExtensionContext;
|
||||
export function setExtensionContext(context: vscode.ExtensionContext): void {
|
||||
extensionContext = context;
|
||||
extensionPath = extensionContext.extensionPath;
|
||||
}
|
||||
export function setExtensionPath(path: string): void {
|
||||
extensionPath = path;
|
||||
}
|
||||
|
||||
export const failedToParseTasksJson: string = "Failed to parse tasks.json, possibly due to comments or trailing commas.";
|
||||
|
||||
// Use this package.json to read values
|
||||
export const packageJson: any = vscode.extensions.getExtension("ms-vscode.cpptools").packageJSON;
|
||||
@@ -36,6 +45,69 @@ export function getRawPackageJson(): any {
|
||||
return rawPackageJson;
|
||||
}
|
||||
|
||||
export function getRawTasksJson(): Promise<any> {
|
||||
const path: string = getTasksJsonPath();
|
||||
if (!path) {
|
||||
return undefined;
|
||||
}
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
fs.exists(path, exists => {
|
||||
if (!exists) {
|
||||
return resolve({});
|
||||
}
|
||||
let fileContents: string = fs.readFileSync(path).toString();
|
||||
fileContents = fileContents.replace(/^\s*\/\/.*$/gm, ""); // Remove start of line // comments.
|
||||
let rawTasks: any = {};
|
||||
try {
|
||||
rawTasks = JSON.parse(fileContents);
|
||||
} catch (error) {
|
||||
return reject(new Error(failedToParseTasksJson));
|
||||
}
|
||||
resolve(rawTasks);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function ensureBuildTaskExists(taskName: string): Promise<void> {
|
||||
let rawTasksJson: any = await getRawTasksJson();
|
||||
|
||||
// Ensure that the task exists in the user's task.json. Task will not be found otherwise.
|
||||
if (!rawTasksJson.tasks) {
|
||||
rawTasksJson.tasks = new Array();
|
||||
}
|
||||
// Find or create the task which should be created based on the selected "debug configuration".
|
||||
let selectedTask: vscode.Task = rawTasksJson.tasks.find(task => {
|
||||
return task.label && task.label === task;
|
||||
});
|
||||
if (selectedTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
const buildTasks: vscode.Task[] = await getBuildTasks(false);
|
||||
selectedTask = buildTasks.find(task => task.name === taskName);
|
||||
console.assert(selectedTask);
|
||||
|
||||
rawTasksJson.version = "2.0.0";
|
||||
|
||||
if (!rawTasksJson.tasks.find(task => { return task.label === selectedTask.definition.label; })) {
|
||||
rawTasksJson.tasks.push(selectedTask.definition);
|
||||
}
|
||||
|
||||
// TODO: It's dangerous to overwrite this file. We could be wiping out comments.
|
||||
let settings: OtherSettings = new OtherSettings();
|
||||
await writeFileText(getTasksJsonPath(), JSON.stringify(rawTasksJson, null, settings.editorTabSize));
|
||||
}
|
||||
|
||||
export function fileIsCOrCppSource(file: string): boolean {
|
||||
const fileExtLower: string = path.extname(file).toLowerCase();
|
||||
return [".C", ".c", ".cpp", ".cc", ".cxx", ".mm", ".ino", ".inl"].some(ext => fileExtLower === ext);
|
||||
}
|
||||
|
||||
export function isEditorFileCpp(file: string): boolean {
|
||||
let editor: vscode.TextEditor = vscode.window.visibleTextEditors.find(e => e.document.uri.toString() === file);
|
||||
return editor && editor.document.languageId === "cpp";
|
||||
}
|
||||
|
||||
// This function is used to stringify the rawPackageJson.
|
||||
// Do not use with util.packageJson or else the expanded
|
||||
// package.json will be written back.
|
||||
@@ -44,13 +116,22 @@ export function stringifyPackageJson(packageJson: string): string {
|
||||
}
|
||||
|
||||
export function getExtensionFilePath(extensionfile: string): string {
|
||||
return path.resolve(extensionContext.extensionPath, extensionfile);
|
||||
return path.resolve(extensionPath, extensionfile);
|
||||
}
|
||||
|
||||
export function getPackageJsonPath(): string {
|
||||
return getExtensionFilePath("package.json");
|
||||
}
|
||||
|
||||
export function getTasksJsonPath(): string {
|
||||
const editor: vscode.TextEditor = vscode.window.activeTextEditor;
|
||||
const folder: vscode.WorkspaceFolder = vscode.workspace.getWorkspaceFolder(editor.document.uri);
|
||||
if (!folder) {
|
||||
return undefined;
|
||||
}
|
||||
return path.join(folder.uri.fsPath, ".vscode", "tasks.json");
|
||||
}
|
||||
|
||||
export function getVcpkgPathDescriptorFile(): string {
|
||||
if (process.platform === 'win32') {
|
||||
return path.join(process.env.LOCALAPPDATA, "vcpkg/vcpkg.path.txt");
|
||||
@@ -80,8 +161,8 @@ export function getVcpkgRoot(): string {
|
||||
* For the purposes of this function, a header file has no extension, or an extension that begins with the letter 'h'.
|
||||
* @param document The document to check.
|
||||
*/
|
||||
export function isHeader(document: vscode.TextDocument): boolean {
|
||||
let ext: string = path.extname(document.uri.fsPath);
|
||||
export function isHeader(uri: vscode.Uri): boolean {
|
||||
let ext: string = path.extname(uri.fsPath);
|
||||
return !ext || ext.startsWith(".h") || ext.startsWith(".H");
|
||||
}
|
||||
|
||||
@@ -124,15 +205,15 @@ let installProgressStr: string = "CPP." + packageJson.version + ".Progress";
|
||||
let intelliSenseProgressStr: string = "CPP." + packageJson.version + ".IntelliSenseProgress";
|
||||
|
||||
export function getProgress(): number {
|
||||
return extensionContext.globalState.get<number>(installProgressStr, -1);
|
||||
return extensionContext ? extensionContext.globalState.get<number>(installProgressStr, -1) : -1;
|
||||
}
|
||||
|
||||
export function getIntelliSenseProgress(): number {
|
||||
return extensionContext.globalState.get<number>(intelliSenseProgressStr, -1);
|
||||
return extensionContext ? extensionContext.globalState.get<number>(intelliSenseProgressStr, -1) : -1;
|
||||
}
|
||||
|
||||
export function setProgress(progress: number): void {
|
||||
if (getProgress() < progress) {
|
||||
if (extensionContext && getProgress() < progress) {
|
||||
extensionContext.globalState.update(installProgressStr, progress);
|
||||
let telemetryProperties: { [key: string]: string } = {};
|
||||
let progressName: string;
|
||||
@@ -149,7 +230,7 @@ export function setProgress(progress: number): void {
|
||||
}
|
||||
|
||||
export function setIntelliSenseProgress(progress: number): void {
|
||||
if (getIntelliSenseProgress() < progress) {
|
||||
if (extensionContext && getIntelliSenseProgress() < progress) {
|
||||
extensionContext.globalState.update(intelliSenseProgressStr, progress);
|
||||
let telemetryProperties: { [key: string]: string } = {};
|
||||
let progressName: string;
|
||||
@@ -211,6 +292,19 @@ export function isOptionalArrayOfString(input: any): input is string[]|undefined
|
||||
return input === undefined || isArrayOfString(input);
|
||||
}
|
||||
|
||||
export function resolveCachePath(input: string, additionalEnvironment: {[key: string]: string | string[]}): string {
|
||||
let resolvedPath: string = "";
|
||||
if (!input) {
|
||||
// If no path is set, return empty string to language service process, where it will set the default path as
|
||||
// Windows: %LocalAppData%/Microsoft/vscode-cpptools/
|
||||
// Linux and Mac: ~/.vscode-cpptools/
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
resolvedPath = resolveVariables(input, additionalEnvironment);
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
export function resolveVariables(input: string, additionalEnvironment: {[key: string]: string | string[]}): string {
|
||||
if (!input) {
|
||||
return "";
|
||||
@@ -350,7 +444,7 @@ export function touchInstallLockFile(): Promise<void> {
|
||||
|
||||
export function touchExtensionFolder(): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
fs.utimes(path.resolve(extensionContext.extensionPath, ".."), new Date(Date.now()), new Date(Date.now()), (err) => {
|
||||
fs.utimes(path.resolve(extensionPath, ".."), new Date(Date.now()), new Date(Date.now()), (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
@@ -386,6 +480,23 @@ export function checkDirectoryExists(dirPath: string): Promise<boolean> {
|
||||
});
|
||||
}
|
||||
|
||||
export function checkFileExistsSync(filePath: string): boolean {
|
||||
try {
|
||||
return fs.statSync(filePath).isFile();
|
||||
} catch (e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Test whether a directory exists */
|
||||
export function checkDirectoryExistsSync(dirPath: string): boolean {
|
||||
try {
|
||||
return fs.statSync(dirPath).isDirectory();
|
||||
} catch (e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Read the files in a directory */
|
||||
export function readDir(dirPath: string): Promise<string[]> {
|
||||
return new Promise((resolve) => {
|
||||
@@ -669,4 +780,126 @@ export function downloadFileToStr(urlStr: string, headers?: OutgoingHttpHeaders)
|
||||
request.on('error', (error) => { reject(error); });
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface CompilerPathAndArgs {
|
||||
compilerPath: string;
|
||||
compilerName: string;
|
||||
additionalArgs: string[];
|
||||
}
|
||||
|
||||
export function extractCompilerPathAndArgs(inputCompilerPath: string): CompilerPathAndArgs {
|
||||
let compilerPath: string = inputCompilerPath;
|
||||
let compilerName: string = "";
|
||||
let additionalArgs: string[];
|
||||
let isWindows: boolean = os.platform() === 'win32';
|
||||
if (compilerPath) {
|
||||
if (compilerPath === "cl.exe") {
|
||||
// Input is only compiler name, this is only for cl.exe
|
||||
compilerName = compilerPath;
|
||||
|
||||
} else if (compilerPath.startsWith("\"")) {
|
||||
// Input has quotes around compiler path
|
||||
let endQuote: number = compilerPath.substr(1).search("\"") + 1;
|
||||
if (endQuote !== -1) {
|
||||
additionalArgs = compilerPath.substr(endQuote + 1).split(" ");
|
||||
additionalArgs = additionalArgs.filter((arg: string) => { return arg.trim().length !== 0; }); // Remove empty args.
|
||||
compilerPath = compilerPath.substr(1, endQuote - 1);
|
||||
compilerName = compilerPath.replace(/^.*(\\|\/|\:)/, '');
|
||||
}
|
||||
} else {
|
||||
// Input has no quotes but can have a compiler path with spaces and args.
|
||||
// Go from right to left checking if a valid path is to the left of a space.
|
||||
let spaceStart: number = compilerPath.lastIndexOf(" ");
|
||||
if (spaceStart !== -1 && (!isWindows || !compilerPath.endsWith("cl.exe")) && !checkFileExistsSync(compilerPath)) {
|
||||
let potentialCompilerPath: string = compilerPath.substr(0, spaceStart);
|
||||
while ((!isWindows || !potentialCompilerPath.endsWith("cl.exe")) && !checkFileExistsSync(potentialCompilerPath)) {
|
||||
spaceStart = potentialCompilerPath.lastIndexOf(" ");
|
||||
if (spaceStart === -1) {
|
||||
// Reached the start without finding a valid path. Use the original value.
|
||||
potentialCompilerPath = compilerPath;
|
||||
break;
|
||||
}
|
||||
potentialCompilerPath = potentialCompilerPath.substr(0, spaceStart);
|
||||
}
|
||||
if (compilerPath !== potentialCompilerPath) {
|
||||
// Found a valid compilerPath and args.
|
||||
additionalArgs = compilerPath.substr(spaceStart + 1).split(" ");
|
||||
additionalArgs = additionalArgs.filter((arg: string) => { return arg.trim().length !== 0; }); // Remove empty args.
|
||||
compilerPath = potentialCompilerPath;
|
||||
}
|
||||
}
|
||||
// Get compiler name if there are no args but path is valid or a valid path was found with args.
|
||||
if (compilerPath === "cl.exe" || checkFileExistsSync(compilerPath)) {
|
||||
compilerName = compilerPath.replace(/^.*(\\|\/|\:)/, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
return { compilerPath, compilerName, additionalArgs };
|
||||
}
|
||||
|
||||
export function escapeForSquiggles(s: string): string {
|
||||
// Replace all \<escape character> with \\<character>, except for \"
|
||||
// Otherwise, the JSON.parse result will have the \<escape character> missing.
|
||||
let newResults: string = "";
|
||||
let lastWasBackslash: Boolean = false;
|
||||
let lastBackslashWasEscaped: Boolean = false;
|
||||
for (let i: number = 0; i < s.length; i++) {
|
||||
if (s[i] === '\\') {
|
||||
if (lastWasBackslash) {
|
||||
newResults += "\\";
|
||||
lastBackslashWasEscaped = !lastBackslashWasEscaped;
|
||||
} else {
|
||||
lastBackslashWasEscaped = false;
|
||||
}
|
||||
newResults += "\\";
|
||||
lastWasBackslash = true;
|
||||
} else {
|
||||
if (lastWasBackslash && (lastBackslashWasEscaped || (s[i] !== '"'))) {
|
||||
newResults += "\\";
|
||||
}
|
||||
lastWasBackslash = false;
|
||||
lastBackslashWasEscaped = false;
|
||||
newResults += s[i];
|
||||
}
|
||||
}
|
||||
if (lastWasBackslash) {
|
||||
newResults += "\\";
|
||||
}
|
||||
return newResults;
|
||||
}
|
||||
|
||||
export class BlockingTask<T> {
|
||||
private dependency: BlockingTask<any>;
|
||||
private done: boolean = false;
|
||||
private promise: Thenable<T>;
|
||||
|
||||
constructor(task: () => Thenable<T>, dependency?: BlockingTask<any>) {
|
||||
if (!dependency) {
|
||||
this.promise = task();
|
||||
} else {
|
||||
this.dependency = dependency;
|
||||
this.promise = new Promise<T>((resolve, reject) => {
|
||||
let f1: () => void = () => {
|
||||
task().then(resolve, reject);
|
||||
};
|
||||
let f2: (err: any) => void = (err) => {
|
||||
console.log(err);
|
||||
task().then(resolve, reject);
|
||||
};
|
||||
this.dependency.promise.then(f1, f2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get Done(): boolean {
|
||||
return this.done;
|
||||
}
|
||||
|
||||
public then<T2>(onSucceeded: (value: T) => T2, onRejected?: (err) => any): Thenable<T2> {
|
||||
if (onRejected) {
|
||||
return this.promise.then(onSucceeded, onRejected);
|
||||
}
|
||||
return this.promise.then(onSucceeded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import * as util from './common';
|
||||
import { PlatformInformation } from './platform';
|
||||
import { OutgoingHttpHeaders } from 'http';
|
||||
|
||||
const testingInsidersVsixInstall: boolean = false; // Change this to true to enable testing of the Insiders vsix installation.
|
||||
|
||||
/**
|
||||
* The object representation of a Build Asset. Each Asset corresponds to information about a release file on GitHub.
|
||||
*/
|
||||
@@ -139,7 +141,7 @@ export async function getTargetBuildInfo(updateChannel: string): Promise<BuildIn
|
||||
// Allows testing pre-releases without accidentally downgrading to the latest version
|
||||
const userVersion: PackageVersion = new PackageVersion(util.packageJson.version);
|
||||
const latestVersion: PackageVersion = new PackageVersion(builds[0].name);
|
||||
if (userVersion.isGreaterThan(latestVersion) || (userVersion.suffix && userVersion.suffix !== 'insiders')) {
|
||||
if (!testingInsidersVsixInstall && (userVersion.isGreaterThan(latestVersion) || (userVersion.suffix && userVersion.suffix !== 'insiders'))) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -172,7 +174,7 @@ function getTargetBuild(builds: Build[], userVersion: PackageVersion, updateChan
|
||||
let needsUpdate: (installed: PackageVersion, target: PackageVersion) => boolean;
|
||||
let useBuild: (build: Build) => boolean;
|
||||
if (updateChannel === 'Insiders') {
|
||||
needsUpdate = (installed: PackageVersion, target: PackageVersion) => { return target.isGreaterThan(installed); };
|
||||
needsUpdate = (installed: PackageVersion, target: PackageVersion) => { return testingInsidersVsixInstall || target.isGreaterThan(installed); };
|
||||
useBuild = (build: Build): boolean => { return true; };
|
||||
} else if (updateChannel === 'Default') {
|
||||
needsUpdate = function(installed: PackageVersion, target: PackageVersion): boolean { return installed.isGreaterThan(target); };
|
||||
@@ -189,7 +191,10 @@ function getTargetBuild(builds: Build[], userVersion: PackageVersion, updateChan
|
||||
|
||||
// Check current version against target's version to determine if the installation should happen
|
||||
const targetVersion: PackageVersion = new PackageVersion(targetBuild.name);
|
||||
return needsUpdate(userVersion, targetVersion) ? targetBuild : undefined;
|
||||
if (needsUpdate(userVersion, targetVersion)) {
|
||||
return targetBuild;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
interface Rate {
|
||||
@@ -201,7 +206,7 @@ interface RateLimit {
|
||||
}
|
||||
|
||||
function isRate(input: any): input is Rate {
|
||||
return input && input.remaining && util.isNumber(input.remaining);
|
||||
return input && util.isNumber(input.remaining);
|
||||
}
|
||||
|
||||
function isRateLimit(input: any): input is RateLimit {
|
||||
@@ -212,7 +217,7 @@ async function getRateLimit(): Promise<RateLimit> {
|
||||
const header: OutgoingHttpHeaders = { 'User-Agent': 'vscode-cpptools' };
|
||||
const data: string = await util.downloadFileToStr('https://api.github.com/rate_limit', header)
|
||||
.catch((error) => {
|
||||
if (error.code && error.code !== "ENOENT") {
|
||||
if (error && error.code && error.code !== "ENOENT") {
|
||||
// Only throw if the user is connected to the Internet.
|
||||
throw new Error('Failed to download rate limit JSON');
|
||||
}
|
||||
@@ -255,7 +260,7 @@ async function getReleaseJson(): Promise<Build[]> {
|
||||
|
||||
const data: string = await util.downloadFileToStr(releaseUrl, header)
|
||||
.catch((error) => {
|
||||
if (error.code && error.code !== "ENOENT") {
|
||||
if (error && error.code && error.code !== "ENOENT") {
|
||||
// Only throw if the user is connected to the Internet.
|
||||
throw new Error('Failed to download release JSON');
|
||||
}
|
||||
|
||||
@@ -3,8 +3,14 @@
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
export enum InstallationType {
|
||||
Online,
|
||||
Offline
|
||||
}
|
||||
|
||||
export class InstallationInformation {
|
||||
stage: string;
|
||||
type: InstallationType;
|
||||
hasError: boolean;
|
||||
telemetryProperties: { [key: string]: string };
|
||||
|
||||
@@ -25,4 +31,8 @@ export function getInstallationInformation(): InstallationInformation {
|
||||
|
||||
export function setInstallationStage(stage: string): void {
|
||||
getInstallationInformation().stage = stage;
|
||||
}
|
||||
|
||||
export function setInstallationType(type: InstallationType): void {
|
||||
getInstallationInformation().type = type;
|
||||
}
|
||||
+36
-12
@@ -18,24 +18,24 @@ import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistr
|
||||
import { PlatformInformation } from './platform';
|
||||
import { PackageManager, PackageManagerError, IPackage } from './packageManager';
|
||||
import { PersistentState } from './LanguageServer/persistentState';
|
||||
import { getInstallationInformation, InstallationInformation, setInstallationStage } from './installationInformation';
|
||||
import { getInstallationInformation, InstallationInformation, setInstallationStage, setInstallationType, InstallationType } from './installationInformation';
|
||||
import { Logger, getOutputChannelLogger, showOutputChannel } from './logger';
|
||||
import { CppTools1 } from './cppTools1';
|
||||
|
||||
const releaseNotesVersion: number = 3;
|
||||
const releaseNotesVersion: number = 5;
|
||||
const cppTools: CppTools1 = new CppTools1();
|
||||
let languageServiceDisabled: boolean = false;
|
||||
let reloadMessageShown: boolean = false;
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<CppToolsApi & CppToolsExtension> {
|
||||
initializeTemporaryCommandRegistrar();
|
||||
util.setExtensionContext(context);
|
||||
initializeTemporaryCommandRegistrar();
|
||||
Telemetry.activate();
|
||||
util.setProgress(0);
|
||||
|
||||
// Initialize the DebuggerExtension and register the related commands and providers.
|
||||
DebuggerExtension.initialize();
|
||||
DebuggerExtension.initialize(context);
|
||||
|
||||
await processRuntimeDependencies();
|
||||
|
||||
@@ -87,6 +87,7 @@ async function processRuntimeDependencies(): Promise<void> {
|
||||
|
||||
async function offlineInstallation(): Promise<void> {
|
||||
setInstallationStage('getPlatformInfo');
|
||||
setInstallationType(InstallationType.Offline);
|
||||
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
|
||||
|
||||
setInstallationStage('makeBinariesExecutable');
|
||||
@@ -107,6 +108,7 @@ async function offlineInstallation(): Promise<void> {
|
||||
|
||||
async function onlineInstallation(): Promise<void> {
|
||||
setInstallationStage('getPlatformInfo');
|
||||
setInstallationType(InstallationType.Online);
|
||||
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
|
||||
|
||||
await downloadAndInstallPackages(info);
|
||||
@@ -234,6 +236,7 @@ function sendTelemetry(info: PlatformInformation): boolean {
|
||||
const success: boolean = !installBlob.hasError;
|
||||
|
||||
installBlob.telemetryProperties['success'] = success.toString();
|
||||
installBlob.telemetryProperties['type'] = installBlob.type === InstallationType.Online ? "online" : "offline";
|
||||
|
||||
if (info.distribution) {
|
||||
installBlob.telemetryProperties['linuxDistroName'] = info.distribution.name;
|
||||
@@ -244,7 +247,9 @@ function sendTelemetry(info: PlatformInformation): boolean {
|
||||
util.setProgress(util.getProgressInstallSuccess());
|
||||
let versionShown: PersistentState<number> = new PersistentState<number>("CPP.ReleaseNotesVersion", -1);
|
||||
if (versionShown.Value < releaseNotesVersion) {
|
||||
util.showReleaseNotes();
|
||||
if (versionShown.Value !== versionShown.DefaultValue) {
|
||||
util.showReleaseNotes();
|
||||
}
|
||||
versionShown.Value = releaseNotesVersion;
|
||||
}
|
||||
}
|
||||
@@ -298,10 +303,11 @@ async function finalizeExtensionActivation(): Promise<void> {
|
||||
// Update default for C_Cpp.intelliSenseEngine based on A/B testing settings.
|
||||
// (this may result in rewriting the package.json file)
|
||||
|
||||
let abTestSettings: cpptoolsJsonUtils.ABTestSettings = cpptoolsJsonUtils.getABTestSettings();
|
||||
let packageJson: any = util.getRawPackageJson();
|
||||
let writePackageJson: boolean = false;
|
||||
let packageJsonPath: string = util.getExtensionFilePath("package.json");
|
||||
if (!packageJsonPath.includes(".vscode-insiders") && !packageJsonPath.includes(".vscode-exploration")) {
|
||||
let abTestSettings: cpptoolsJsonUtils.ABTestSettings = cpptoolsJsonUtils.getABTestSettings();
|
||||
let packageJson: any = util.getRawPackageJson();
|
||||
let prevIntelliSenseEngineDefault: any = packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default;
|
||||
if (abTestSettings.UseDefaultIntelliSenseEngine) {
|
||||
packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default = "Default";
|
||||
@@ -309,15 +315,28 @@ async function finalizeExtensionActivation(): Promise<void> {
|
||||
packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default = "Tag Parser";
|
||||
}
|
||||
if (prevIntelliSenseEngineDefault !== packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default) {
|
||||
return util.writeFileText(util.getPackageJsonPath(), util.stringifyPackageJson(packageJson));
|
||||
writePackageJson = true;
|
||||
}
|
||||
} else {
|
||||
let packageJson: any = util.getRawPackageJson();
|
||||
if (packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default === 'Default') {
|
||||
packageJson.contributes.configuration.properties['C_Cpp.updateChannel'].default = 'Insiders';
|
||||
return util.writeFileText(util.getPackageJsonPath(), util.stringifyPackageJson(packageJson));
|
||||
writePackageJson = true;
|
||||
}
|
||||
}
|
||||
|
||||
let prevEnhancedColorizationDefault: any = packageJson.contributes.configuration.properties["C_Cpp.enhancedColorization"].default;
|
||||
if (abTestSettings.UseEnhancedColorization) {
|
||||
packageJson.contributes.configuration.properties["C_Cpp.enhancedColorization"].default = "Enabled";
|
||||
} else {
|
||||
packageJson.contributes.configuration.properties["C_Cpp.enhancedColorization"].default = "Disabled";
|
||||
}
|
||||
if (prevEnhancedColorizationDefault !== packageJson.contributes.configuration.properties["C_Cpp.enhancedColorization"].default) {
|
||||
writePackageJson = true;
|
||||
}
|
||||
|
||||
if (writePackageJson) {
|
||||
return util.writeFileText(util.getPackageJsonPath(), util.stringifyPackageJson(packageJson));
|
||||
}
|
||||
}
|
||||
|
||||
function rewriteManifest(): Promise<void> {
|
||||
@@ -329,14 +348,17 @@ function rewriteManifest(): Promise<void> {
|
||||
"onLanguage:c",
|
||||
"onCommand:extension.pickNativeProcess",
|
||||
"onCommand:extension.pickRemoteNativeProcess",
|
||||
"onCommand:C_Cpp.ConfigurationEdit",
|
||||
"onCommand:C_Cpp.BuildAndDebugActiveFile",
|
||||
"onCommand:C_Cpp.ConfigurationEditJSON",
|
||||
"onCommand:C_Cpp.ConfigurationEditUI",
|
||||
"onCommand:C_Cpp.ConfigurationSelect",
|
||||
"onCommand:C_Cpp.ConfigurationProviderSelect",
|
||||
"onCommand:C_Cpp.SwitchHeaderSource",
|
||||
"onCommand:C_Cpp.Navigate",
|
||||
"onCommand:C_Cpp.GoToDeclaration",
|
||||
"onCommand:C_Cpp.PeekDeclaration",
|
||||
"onCommand:C_Cpp.ToggleErrorSquiggles",
|
||||
"onCommand:C_Cpp.EnableErrorSquiggles",
|
||||
"onCommand:C_Cpp.DisableErrorSquiggles",
|
||||
"onCommand:C_Cpp.ToggleIncludeFallback",
|
||||
"onCommand:C_Cpp.ToggleDimInactiveRegions",
|
||||
"onCommand:C_Cpp.ShowReleaseNotes",
|
||||
@@ -345,6 +367,8 @@ function rewriteManifest(): Promise<void> {
|
||||
"onCommand:C_Cpp.ResumeParsing",
|
||||
"onCommand:C_Cpp.ShowParsingCommands",
|
||||
"onCommand:C_Cpp.TakeSurvey",
|
||||
"onCommand:C_Cpp.LogDiagnostics",
|
||||
"onCommand:C_Cpp.RescanWorkspace",
|
||||
"onDebug",
|
||||
"workspaceContains:/.vscode/c_cpp_properties.json"
|
||||
];
|
||||
|
||||
@@ -39,7 +39,7 @@ export class PlatformInformation {
|
||||
public static GetUnknownArchitecture(): string { return "Unknown"; }
|
||||
|
||||
private static GetWindowsArchitecture(): Promise<string> {
|
||||
return util.execChildProcess('wmic os get osarchitecture', util.extensionContext.extensionPath)
|
||||
return util.execChildProcess('wmic os get osarchitecture', util.extensionPath)
|
||||
.then((architecture) => {
|
||||
if (architecture) {
|
||||
let archArray: string[] = architecture.split(os.EOL);
|
||||
|
||||
@@ -30,23 +30,25 @@ export function deactivate(): void {
|
||||
}
|
||||
|
||||
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }): void {
|
||||
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
|
||||
if (telemetryReporter) {
|
||||
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
|
||||
telemetryReporter.sendTelemetryEvent(eventNamePrefix + eventName, properties);
|
||||
}
|
||||
}
|
||||
|
||||
export function logLanguageServerEvent(eventName: string, properties?: { [key: string]: string }, metrics?: { [key: string]: number }): void {
|
||||
const eventNamePrefix: string = "C_Cpp/LanguageServer/";
|
||||
if (telemetryReporter) {
|
||||
const eventNamePrefix: string = "C_Cpp/LanguageServer/";
|
||||
telemetryReporter.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics);
|
||||
}
|
||||
}
|
||||
|
||||
function createReporter(): TelemetryReporter {
|
||||
let packageInfo: IPackageInfo = getPackageInfo();
|
||||
if (packageInfo && packageInfo.aiKey) {
|
||||
return new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
if (util.extensionContext) {
|
||||
let packageInfo: IPackageInfo = getPackageInfo();
|
||||
if (packageInfo && packageInfo.aiKey) {
|
||||
return new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"lib": [
|
||||
"es6", "dom"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": ".",
|
||||
"removeComments": true,
|
||||
"noImplicitUseStrict": true
|
||||
},
|
||||
"include": [
|
||||
"test/**/*.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as vscode from "vscode";
|
||||
import * as path from 'path';
|
||||
|
||||
// import * as util from '../src/common' <- DO NOT USE. Also do not use anything with relative paths, it will break during replacing in test/integrationTests/debug/integration.test.ts
|
||||
|
||||
abstract class AbstractDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
|
||||
protected readonly context: vscode.ExtensionContext;
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
abstract createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor>;
|
||||
}
|
||||
|
||||
export class CppdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDescriptorFactory {
|
||||
public static DEBUG_TYPE : string = "cppdbg";
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
console.warn("This should only appear in a test scenario.");
|
||||
|
||||
return new vscode.DebugAdapterExecutable('node', [path.join(this.context.extensionPath, './out/test/integrationTests/MockDebugger/mockDebug.js')]);
|
||||
}
|
||||
}
|
||||
|
||||
export class CppvsdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDescriptorFactory {
|
||||
public static DEBUG_TYPE : string = "cppvsdbg";
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
createDebugAdapterDescriptor(session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
|
||||
console.warn("This should only appear in a test scenario.");
|
||||
|
||||
return new vscode.DebugAdapterExecutable('node', [path.join(this.context.extensionPath, './out/test/integrationTests/MockDebugger/mockDebug.js')]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import { MockDebugSession } from './mockDebugSession';
|
||||
|
||||
MockDebugSession.run(MockDebugSession);
|
||||
@@ -0,0 +1,67 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import { Logger, logger, LoggingDebugSession, InitializedEvent, TerminatedEvent } from 'vscode-debugadapter';
|
||||
import { DebugProtocol } from 'vscode-debugprotocol';
|
||||
import { Subject } from 'await-notify';
|
||||
|
||||
interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
|
||||
/** An absolute path to the "program" to debug. */
|
||||
program: string;
|
||||
|
||||
/** enable logging the Debug Adapter Protocol */
|
||||
logPath?: string;
|
||||
}
|
||||
|
||||
export class MockDebugSession extends LoggingDebugSession
|
||||
{
|
||||
private _configurationDone = new Subject();
|
||||
|
||||
public constructor() {
|
||||
super("mock-debug.txt");
|
||||
}
|
||||
|
||||
protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
|
||||
// build and return the capabilities of this debug adapter:
|
||||
response.body = response.body || {};
|
||||
|
||||
// the adapter implements the configurationDoneRequest.
|
||||
|
||||
response.body.supportsConfigurationDoneRequest = true;
|
||||
|
||||
this.sendResponse(response);
|
||||
// since this debug adapter can accept configuration requests like 'setBreakpoint' at any time,
|
||||
// we request them early by sending an 'initializeRequest' to the frontend.
|
||||
// The frontend will end the configuration sequence by calling 'configurationDone' request.
|
||||
this.sendEvent(new InitializedEvent());
|
||||
|
||||
}
|
||||
|
||||
protected configurationDoneRequest(response: DebugProtocol.ConfigurationDoneResponse, args: DebugProtocol.ConfigurationDoneArguments): void {
|
||||
|
||||
super.configurationDoneRequest(response, args);
|
||||
// notify the launchRequest that configuration has finished
|
||||
this._configurationDone.notify();
|
||||
|
||||
}
|
||||
|
||||
protected async launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments) {
|
||||
// make sure to 'Stop' the buffered logging if 'trace' is not set
|
||||
logger.setup(Logger.LogLevel.Verbose, args.logPath);
|
||||
|
||||
// wait until configuration has finished (and configurationDoneRequest has been called)
|
||||
await this._configurationDone.wait(1000);
|
||||
|
||||
this.sendResponse(response);
|
||||
|
||||
// Terminate after launch.
|
||||
this.sendEvent(new TerminatedEvent());
|
||||
}
|
||||
|
||||
protected async disconnectRequest(response: DebugProtocol.DisconnectResponse, args: DebugProtocol.DisconnectArguments)
|
||||
{
|
||||
this.sendResponse(response);
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -7,14 +7,15 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from 'path';
|
||||
|
||||
import { subscribeToAllLoggers } from "../../src/logger";
|
||||
import { subscribeToAllLoggers } from "../../../src/logger";
|
||||
|
||||
//
|
||||
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
|
||||
//
|
||||
// This file is providing the test runner to use when running extension tests.
|
||||
// By default the test runner in use is Mocha based.
|
||||
//
|
||||
// git status
|
||||
|
||||
// You can provide your own test runner if you want to override it by exporting
|
||||
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
|
||||
// host can call to run the tests. The test runner is expected to use console.log
|
||||
@@ -26,8 +27,9 @@ var testRunner = require('vscode/lib/testrunner');
|
||||
// You can directly control Mocha options by uncommenting the following lines
|
||||
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
|
||||
testRunner.configure({
|
||||
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
|
||||
useColors: true, // colored output from test results
|
||||
ui: 'tdd', // the TDD UI is being used in *.test.ts (suite, test, etc.)
|
||||
useColors: true, // colored output from test results
|
||||
fullTrace: true,
|
||||
timeout: 60000
|
||||
});
|
||||
|
||||
+7
-2
@@ -7,14 +7,19 @@ import * as vscode from 'vscode';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite(`Debug Integration Test: `, function(): void {
|
||||
suiteSetup(async function(): Promise<void> {
|
||||
let origFactoryFile: string;
|
||||
let tempFactoryFile: string;
|
||||
let hijackedFactoryFile: string;
|
||||
|
||||
suiteSetup(async function(): Promise<void> {
|
||||
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("Starting (gdb) Launch from the workspace root should create an Active Debug Session", async () => {
|
||||
// If it is failing on startDebugging. Investigate the SimpleCppProject's tasks.json or launch.json.
|
||||
await vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], "(gdb) Launch");
|
||||
|
||||
let debugSessionTerminated: Promise<void> = new Promise(resolve => {
|
||||
@@ -0,0 +1,42 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as path from 'path';
|
||||
|
||||
import { subscribeToAllLoggers } from "../../../src/logger";
|
||||
|
||||
//
|
||||
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
|
||||
//
|
||||
// This file is providing the test runner to use when running extension tests.
|
||||
// By default the test runner in use is Mocha based.
|
||||
//
|
||||
// You can provide your own test runner if you want to override it by exporting
|
||||
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
|
||||
// host can call to run the tests. The test runner is expected to use console.log
|
||||
// to report the results back to the caller. When the tests are finished, return
|
||||
// a possible error to the callback or null if none.
|
||||
|
||||
import testRunner = require('vscode/lib/testrunner');
|
||||
|
||||
// You can directly control Mocha options by uncommenting the following lines
|
||||
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
|
||||
testRunner.configure({
|
||||
ui: 'tdd', // the TDD UI is being used in *.test.ts (suite, test, etc.)
|
||||
useColors: true, // colored output from test results
|
||||
fullStackTrace: true,
|
||||
timeout: 60000
|
||||
});
|
||||
|
||||
const logFolder: string = path.join( __dirname, ".logs");
|
||||
|
||||
if (!fs.existsSync(logFolder)) {
|
||||
fs.mkdirSync(logFolder);
|
||||
}
|
||||
const logFilePath: string = path.join(logFolder, "integrationTests.log");
|
||||
subscribeToAllLoggers(message => fs.appendFileSync(logFilePath, message));
|
||||
|
||||
module.exports = testRunner;
|
||||
+13
-9
@@ -5,17 +5,21 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as assert from 'assert';
|
||||
import { getLanguageConfigFromPatterns } from '../../src/LanguageServer/languageConfig';
|
||||
import * as util from '../../src/common';
|
||||
import { getLanguageConfigFromPatterns } from '../../../src/LanguageServer/languageConfig';
|
||||
import * as util from '../../../src/common';
|
||||
import * as api from 'vscode-cpptools';
|
||||
import * as apit from 'vscode-cpptools/out/testApi';
|
||||
import * as config from '../../src/LanguageServer/configurations';
|
||||
import { CppSettings } from '../../src/LanguageServer/settings';
|
||||
import { getActiveClient } from '../../src/LanguageServer/extension';
|
||||
import * as config from '../../../src/LanguageServer/configurations';
|
||||
import { getActiveClient } from '../../../src/LanguageServer/extension';
|
||||
import { initializeTemporaryCommandRegistrar } from '../../../src/commands';
|
||||
|
||||
const defaultTimeout: number = 60000;
|
||||
|
||||
suite("multiline comment setting tests", function(): void {
|
||||
suiteSetup(async function(): Promise<void> {
|
||||
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
util.setExtensionPath(extension.extensionPath);
|
||||
initializeTemporaryCommandRegistrar();
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
@@ -187,7 +191,7 @@ suite("extensibility tests v2", function(): void {
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
setTimeout(() => { reject(new Error("timeout")); }, 2500);
|
||||
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
|
||||
});
|
||||
disposables.push(testHook);
|
||||
|
||||
@@ -262,7 +266,7 @@ suite("extensibility tests v1", function(): void {
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
setTimeout(() => { reject(new Error("timeout")); }, 2500);
|
||||
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
|
||||
});
|
||||
disposables.push(testHook);
|
||||
|
||||
@@ -334,7 +338,7 @@ suite("extensibility tests v0", function(): void {
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
setTimeout(() => { reject(new Error("timeout")); }, 2500);
|
||||
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
|
||||
});
|
||||
disposables.push(testHook);
|
||||
|
||||
+8
-4
@@ -5,15 +5,12 @@
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/program",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": true,
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
@@ -22,10 +19,17 @@
|
||||
}
|
||||
],
|
||||
"windows": {
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "C:\\MinGW\\bin\\gdb.exe"
|
||||
},
|
||||
"osx": {
|
||||
"miDebuggerPath": "/usr/bin/lldb"
|
||||
"MIMode": "lldb",
|
||||
"preLaunchTask": "build"
|
||||
},
|
||||
"linux": {
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"preLaunchTask": "build"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Environment, ParsedEnvironmentFile } from '../../src/Debugger/ParsedEnvironmentFile'
|
||||
import * as assert from 'assert';
|
||||
|
||||
// Because the environment variable is set as an array, the index does not matter.
|
||||
function AssertEnvironmentEqual(env: Environment[], name: string, value: string) {
|
||||
let found: boolean = false;
|
||||
for (let e of env)
|
||||
{
|
||||
if (e.name == name)
|
||||
{
|
||||
assert(e.value == value, `Checking if ${e.value} == ${value}`);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(found, `${name} was not found in env.`)
|
||||
}
|
||||
|
||||
suite("ParsedEnvironmentFile", () => {
|
||||
test("Add single variable", () => {
|
||||
const content = `MyName=VALUE`;
|
||||
const fakeConfig : Environment[] = [];
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
|
||||
|
||||
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
|
||||
AssertEnvironmentEqual(result.Env, "MyName", "VALUE");
|
||||
});
|
||||
|
||||
test("Handle quoted values", () => {
|
||||
const content = `MyName="VALUE"`;
|
||||
const fakeConfig : Environment[] = [];
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
|
||||
|
||||
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
|
||||
AssertEnvironmentEqual(result.Env, "MyName", "VALUE");
|
||||
});
|
||||
|
||||
test("Handle BOM", () => {
|
||||
const content = "\uFEFFMyName=VALUE";
|
||||
const fakeConfig : Environment[] = [];
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
|
||||
|
||||
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
|
||||
AssertEnvironmentEqual(result.Env, "MyName", "VALUE");
|
||||
});
|
||||
|
||||
test("Add multiple variables", () => {
|
||||
const content = `
|
||||
MyName1=Value1
|
||||
MyName2=Value2
|
||||
|
||||
`;
|
||||
const fakeConfig : Environment[] = [];
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
|
||||
|
||||
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
|
||||
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
|
||||
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
|
||||
});
|
||||
|
||||
test("Update variable", () => {
|
||||
const content = `
|
||||
MyName1=Value1
|
||||
MyName2=Value2
|
||||
|
||||
`;
|
||||
const initialEnv : Environment[] = [];
|
||||
initialEnv.push({name : "MyName1", value: "Value7"});
|
||||
initialEnv.push({name : "ThisShouldNotChange", value : "StillHere"});
|
||||
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", initialEnv);
|
||||
|
||||
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
|
||||
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
|
||||
AssertEnvironmentEqual(result.Env, "ThisShouldNotChange", "StillHere");
|
||||
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
|
||||
});
|
||||
|
||||
test("Handle comments", () => {
|
||||
const content = `# This is an environment file
|
||||
MyName1=Value1
|
||||
# This is a comment in the middle of the file
|
||||
MyName2=Value2
|
||||
`;
|
||||
const fakeConfig : Environment[] = [];
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
|
||||
|
||||
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
|
||||
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
|
||||
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
|
||||
});
|
||||
|
||||
test("Handle invalid lines", () => {
|
||||
const content = `
|
||||
This_Line_Is_Wrong
|
||||
MyName1=Value1
|
||||
MyName2=Value2
|
||||
|
||||
`;
|
||||
const fakeConfig : Environment[] = [];
|
||||
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
|
||||
|
||||
assert(result.Warning.startsWith("Ignoring non-parseable lines in envFile TestEnvFileName"), 'Checking if warning exists');
|
||||
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
|
||||
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as assert from "assert";
|
||||
import { resolveVariables } from "../../src/common";
|
||||
import { resolveVariables, escapeForSquiggles } from "../../src/common";
|
||||
|
||||
suite("Common Utility validation", () => {
|
||||
suite("resolveVariables", () => {
|
||||
@@ -198,6 +198,25 @@ suite("Common Utility validation", () => {
|
||||
.shouldLookupSymbol("Root");
|
||||
});
|
||||
|
||||
test("escapeForSquiggles:", () => {
|
||||
let testEscapeForSquigglesScenario: any = (input: string, expectedOutput: string) => {
|
||||
let result: string = escapeForSquiggles(input);
|
||||
if (result !== expectedOutput) {
|
||||
throw new Error(`escapeForSquiggles failure: for \"${input}\", \"${result}\" !== \"${expectedOutput}\"`);
|
||||
}
|
||||
};
|
||||
|
||||
testEscapeForSquigglesScenario("\\", "\\\\"); // single backslash
|
||||
testEscapeForSquigglesScenario("\\\"", "\\\""); // escaped quote
|
||||
testEscapeForSquigglesScenario("\\\t", "\\\\\t"); // escaped non-quote
|
||||
testEscapeForSquigglesScenario("\\\\\"", "\\\\\\\\\""); // escaped backslash, unescaped quote
|
||||
testEscapeForSquigglesScenario("\\\\\t", "\\\\\\\\\t"); // escaped backslash, unescaped non-quote
|
||||
testEscapeForSquigglesScenario("\\t", "\\\\t"); // escaped non-quote
|
||||
testEscapeForSquigglesScenario("\\\\\\t", "\\\\\\\\\\\\t"); // escaped backslash, unescaped non-quote
|
||||
testEscapeForSquigglesScenario("\"\"", "\"\""); // empty quoted string
|
||||
testEscapeForSquigglesScenario("\"\\\\\"", "\"\\\\\\\\\""); // quoted string containing escaped backslash
|
||||
});
|
||||
|
||||
interface ResolveTestFlowEnvironment {
|
||||
withEnvironment(additionalEnvironment: {[key: string]: string | string[]}): ResolveTestFlowAssert;
|
||||
shouldLookupSymbol: (key: string) => void;
|
||||
@@ -229,6 +248,5 @@ suite("Common Utility validation", () => {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
@@ -196,6 +196,11 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"envFile": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a file containing environment variable definitions. This file has key value pairs separated by an equals sign per line. E.g. KEY=VALUE",
|
||||
"default": "${workspaceFolder}/.env"
|
||||
},
|
||||
"additionalSOLibSearchPath": {
|
||||
"type": "string",
|
||||
"description": "Semicolon separated list of directories to use to search for .so files. Example: \"c:\\dir1;c:\\dir2\".",
|
||||
@@ -345,12 +350,12 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": "${command:pickProcess}"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
@@ -429,6 +434,11 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"envFile": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a file containing environment variable definitions. This file has key value pairs separated by an equals sign per line. E.g. KEY=VALUE",
|
||||
"default": "${workspaceFolder}/.env"
|
||||
},
|
||||
"symbolSearchPath": {
|
||||
"type": "string",
|
||||
"description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".",
|
||||
@@ -461,6 +471,11 @@
|
||||
"<source-path>": "<target-path>"
|
||||
}
|
||||
},
|
||||
"enableDebugHeap": {
|
||||
"type": "boolean",
|
||||
"description": "If false, the process will be launched with debug heap disabled. This sets the environment variable '_NO_DEBUG_HEAP' to '1'.",
|
||||
"default": false
|
||||
},
|
||||
"logging": {
|
||||
"type": "object",
|
||||
"description": "Optional flags to determine what types of messages should be logged to the Debug Console.",
|
||||
@@ -511,12 +526,12 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": "${command:pickProcess}"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"description": "Optional process id to attach the debugger to. Use \"${command:pickProcess}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.",
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
|
||||
@@ -10,9 +10,17 @@
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
const cp = require("child_process");
|
||||
const path = require("path");
|
||||
|
||||
let compile = function(tsPath) {
|
||||
const folderName = path.dirname(tsPath);
|
||||
|
||||
console.log(">> tsc " + tsPath + " --outDir out/" + folderName);
|
||||
cp.execSync("tsc " + tsPath + " --outDir out/" + folderName, {stdio:[0, 1, 2]});
|
||||
};
|
||||
|
||||
if (!process.env.CPPTOOLS_DEV && fs.existsSync('./node_modules')) {
|
||||
console.warn("WARNING: Skipping npm install since it appears to have been executed already.");
|
||||
} else {
|
||||
@@ -20,13 +28,17 @@ if (!process.env.CPPTOOLS_DEV && fs.existsSync('./node_modules')) {
|
||||
cp.execSync("npm install", { stdio: [0, 1, 2] });
|
||||
}
|
||||
|
||||
// Compile the TypeScript code
|
||||
console.log(">> tsc -p ./");
|
||||
cp.execSync("tsc -p ./", {stdio:[0, 1, 2]});
|
||||
const tscCompileListStr = fs.readFileSync("./tscCompileList.txt").toString();
|
||||
|
||||
tscCompileListStr.split(/\r?\n/).forEach(filePath => {
|
||||
if (!filePath.startsWith("#") && /\S/.test(filePath)) {
|
||||
compile(filePath);
|
||||
}
|
||||
});
|
||||
|
||||
// If the required debugger file doesn't exist, make sure it is copied.
|
||||
if (process.env.CPPTOOLS_DEV || !fs.existsSync('./debugAdapters/bin/cppdbg.ad7Engine.json')) {
|
||||
const copyDebuggerDependenciesJSFile = './out/src/Support/copyDebuggerDependencies.js';
|
||||
const copyDebuggerDependenciesJSFile = './out/tools/copyDebuggerDependencies.js';
|
||||
|
||||
// Required for nightly builds. Nightly builds do not enable CPPTOOLS_DEV.
|
||||
console.log(">> node " + copyDebuggerDependenciesJSFile);
|
||||
@@ -0,0 +1,13 @@
|
||||
# This file is consumed in tools\prepublish.js
|
||||
# '#' at the start of the line is treated as a comment and is ignored.
|
||||
# whitespace empty lines are also ignores.
|
||||
#
|
||||
# This file is to be used if you do not wish to webpack a .ts file
|
||||
# If you do not want it to be webpacked:
|
||||
# 1. Please make sure it is not in the src directory
|
||||
# 2. Add it to the list below
|
||||
# 3. If you created a new folder, please make sure it is added to the .vscodeignore
|
||||
|
||||
tools/GenerateOptionsSchema.ts
|
||||
tools/copyDebuggerDependencies.ts
|
||||
ui/settings.ts
|
||||
@@ -4,15 +4,16 @@
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"lib": [
|
||||
"es6"
|
||||
"es6", "dom"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": ".",
|
||||
"removeComments": true,
|
||||
"noImplicitUseStrict": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"server"
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"./node_modules/vscode/vscode.d.ts",
|
||||
"./node_modules/vscode/lib/*",
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,671 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Security-Policy" content="style-src 'unsafe-inline'; img-src vscode-resource:; script-src 'nonce-{{nonce}}';">
|
||||
|
||||
<style type="text/css">
|
||||
@media (max-width: 1140px) {
|
||||
#sidebar {
|
||||
display: none;
|
||||
}
|
||||
#main {
|
||||
max-width: 800px;
|
||||
padding: 0px 20px;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.page-margins {
|
||||
vertical-align: top;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 10px
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 290px;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 45px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--vscode-inputValidation-errorForeground);
|
||||
background: var(--vscode-inputValidation-errorBackground);
|
||||
border: solid 1px var(--vscode-inputValidation-errorBorder);
|
||||
white-space: pre-wrap;
|
||||
display: none;
|
||||
padding: 1px 4px 4px 4px;
|
||||
}
|
||||
|
||||
.headerBtn,
|
||||
.headerBtn:hover,
|
||||
.headerBtn:active {
|
||||
cursor: pointer;
|
||||
color: var(--vscode-foreground);
|
||||
background: var(--vscode-background);
|
||||
border: 0px;
|
||||
padding: 0px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.headerBtn:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.expand:after {
|
||||
font-weight: bold;
|
||||
float: right;
|
||||
margin-right: 6px;
|
||||
margin-top: -4px;
|
||||
content: '\276E';
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.collapse:after {
|
||||
font-weight: bold;
|
||||
float: right;
|
||||
margin-right: 6px;
|
||||
margin-top: -4px;
|
||||
content: '\276E';
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.main {
|
||||
max-width: 800px;
|
||||
margin-left: 320px;
|
||||
padding: 0px 30px;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
font-weight: 500;
|
||||
font-size: 22px;
|
||||
padding-bottom: 6px;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-bottom: 35px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
padding-bottom: 4px;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.section-text {
|
||||
font-size: 14px;
|
||||
padding-bottom: 8px;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.section-note {
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
padding-bottom: 2px;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.codeblock {
|
||||
vertical-align: middle;
|
||||
padding: 2px 8px;
|
||||
margin-top: 8px;
|
||||
display: inline-block;
|
||||
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 19px
|
||||
}
|
||||
|
||||
body:not(.tabbing) button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
checkbox {
|
||||
color: var(--vscode-settings-checkboxForeground);
|
||||
background: var(--vscode-settings-checkboxForeground);
|
||||
border: var(--vscode-settings-checkboxBorder);
|
||||
}
|
||||
|
||||
a:focus,
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: -1px
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding-bottom: .3em;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: 400
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: var(--vscode-input-placeholderForeground);
|
||||
}
|
||||
|
||||
input {
|
||||
height: 17px;
|
||||
padding: 6px;
|
||||
border: solid 1px;
|
||||
font-size: 13px;
|
||||
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
|
||||
color: var(--vscode-settings-textInputForeground);
|
||||
background: var(--vscode-settings-textInputBackground);
|
||||
border: 1px solid var(--vscode-settings-textInputBorder);
|
||||
}
|
||||
|
||||
textarea {
|
||||
white-space: nowrap;
|
||||
padding: 4px, 4px;
|
||||
font-size: 13px;
|
||||
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
|
||||
color: var(--vscode-settings-textInputForeground);
|
||||
background: var(--vscode-settings-textInputBackground);
|
||||
border: 1px solid var(--vscode-settings-textInputBorder);
|
||||
}
|
||||
|
||||
button {
|
||||
color: var(--vscode-button-foreground);
|
||||
background-color: var(--vscode-button-background);
|
||||
border: solid 1px var(--vscode-contrastBorder);
|
||||
padding: 6px 14px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: 2px
|
||||
}
|
||||
|
||||
button:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.select-default {
|
||||
width: 300px;
|
||||
height: 27px;
|
||||
font-size: 13px;
|
||||
font-family:sans-serif;
|
||||
color: var(--vscode-settings-dropdownForeground);
|
||||
background: var(--vscode-settings-dropdownBackground);
|
||||
border: 1px solid var(--vscode-settings-dropdownBorder);
|
||||
}
|
||||
|
||||
.select-editable {
|
||||
position: relative;
|
||||
background-color: var(--vscode-settings-textInputBackground);
|
||||
width: 800px;
|
||||
height: 31px;
|
||||
}
|
||||
|
||||
.select-editable select {
|
||||
position: absolute;
|
||||
font-size: 13px;
|
||||
font-family: sans-serif;
|
||||
border: 1px solid var(--vscode-settings-textInputBorder);
|
||||
height: 31px;
|
||||
margin: auto;
|
||||
color: var(--vscode-settings-textInputForeground);
|
||||
background: var(--vscode-settings-textInputBackground);
|
||||
}
|
||||
|
||||
.select-editable input {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
height: 17px;
|
||||
font-size: 13px;
|
||||
border: none;
|
||||
color: var(--vscode-settings-textInputForeground);
|
||||
background: var(--vscode-settings-textInputBackground);
|
||||
}
|
||||
|
||||
.select-editable input:focus {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 7px 0 5px;
|
||||
padding: 0 16px 0 10px;
|
||||
border-left: 5px solid;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
|
||||
line-height: 19px
|
||||
}
|
||||
|
||||
.mac code {
|
||||
line-height: 18px
|
||||
}
|
||||
|
||||
code > div {
|
||||
padding: 16px;
|
||||
border-radius: 3px;
|
||||
overflow: auto
|
||||
}
|
||||
|
||||
.monaco-tokenized-source {
|
||||
white-space: pre
|
||||
}
|
||||
|
||||
/** Theming */
|
||||
|
||||
.vscode-light {
|
||||
color: #1e1e1e
|
||||
}
|
||||
|
||||
.vscode-dark {
|
||||
color: #ddd
|
||||
}
|
||||
|
||||
.vscode-high-contrast {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.vscode-light code {
|
||||
color: #a31515
|
||||
}
|
||||
|
||||
.vscode-dark code {
|
||||
color: #d7ba7d
|
||||
}
|
||||
|
||||
.vscode-light code > div {
|
||||
background-color: rgba(220, 220, 220, .4)
|
||||
}
|
||||
|
||||
.vscode-dark code > div {
|
||||
background-color: rgba(10, 10, 10, .4)
|
||||
}
|
||||
|
||||
.vscode-light .input-disabled {
|
||||
background-color:rgba(255, 255, 255, 0.4);
|
||||
color: rgb(138, 138, 138);
|
||||
border: solid 1px rgb(201, 198, 198);
|
||||
}
|
||||
|
||||
.vscode-dark .input-disabled {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: rgb(167, 167, 167);
|
||||
}
|
||||
|
||||
.vscode-high-contrast .input-disabled {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
border: solid 1px rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.vscode-high-contrast code > div {
|
||||
background-color: #000
|
||||
}
|
||||
|
||||
.vscode-high-contrast h1 {
|
||||
border-color: #000
|
||||
}
|
||||
|
||||
.vscode-light table > thead > tr > th {
|
||||
border-color: rgba(0, 0, 0, .69)
|
||||
}
|
||||
|
||||
.vscode-dark table > thead > tr > th {
|
||||
border-color: rgba(255, 255, 255, .69)
|
||||
}
|
||||
|
||||
.vscode-light h1,
|
||||
.vscode-light hr,
|
||||
.vscode-light table > tbody > tr + tr > td {
|
||||
border-color: rgba(0, 0, 0, .18)
|
||||
}
|
||||
|
||||
.vscode-dark h1,
|
||||
.vscode-dark hr,
|
||||
.vscode-dark table > tbody > tr + tr > td {
|
||||
border-color: rgba(255, 255, 255, 0.18)
|
||||
}
|
||||
|
||||
.vscode-light blockquote,
|
||||
.vscode-dark blockquote {
|
||||
background: rgba(127, 127, 127, .1);
|
||||
border-color: rgba(0, 122, 204, .5)
|
||||
}
|
||||
|
||||
.vscode-high-contrast blockquote {
|
||||
background: transparent;
|
||||
border-color: #fff
|
||||
}
|
||||
|
||||
.vscode-light div.codeblock {
|
||||
background-color: rgba(0, 0, 0, 0.048)
|
||||
}
|
||||
|
||||
.vscode-dark div.codeblock {
|
||||
background-color: rgba(255, 255, 255, 0.1)
|
||||
}
|
||||
|
||||
.vscode-high-contrast div.codeblock {
|
||||
background-color: rgba(255, 255, 255, 0.15)
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 25px;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.vscode-light a {
|
||||
color: #4080D0
|
||||
}
|
||||
|
||||
.vscode-dark a {
|
||||
color: #a2c1e8
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page-margins">
|
||||
|
||||
<!-- sidebar -->
|
||||
<div id="sidebar" class="sidebar">
|
||||
|
||||
<div style="height: 90px; display: block">
|
||||
<table>
|
||||
<td>
|
||||
<img src="{{root}}/LanguageCCPP_color_128x.png" height="76" width="76" alt="Microsoft C/C++ Extension" title="Microsoft C/C++ Extension" style="padding-right: 10px">
|
||||
</td>
|
||||
<td>
|
||||
<div style="font-size: 20px; font-weight: 400; line-height: 24px">Microsoft<br>C/C++ Extension</div>
|
||||
</td>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div style="height: 30px; display: block"></div>
|
||||
|
||||
<div style="padding-right: 10px; color: var(--vscode-foreground);">
|
||||
Open this editor by using the command:<br>
|
||||
<code>C/C++: Edit configurations (UI)</code>
|
||||
|
||||
<div style="height: 30px; display: block"></div>
|
||||
|
||||
Switch to the <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a> file by clicking on the file link or using the command:<br>
|
||||
<code>C/C++: Edit configurations (JSON)</code>
|
||||
</div>
|
||||
|
||||
</div> <!-- sidebar end -->
|
||||
|
||||
<!-- main -->
|
||||
<div id="main" class="main">
|
||||
|
||||
<!-- title -->
|
||||
<div style=" height: 90px; display: inline-block;">
|
||||
<div class="main-title">IntelliSense Configurations</div>
|
||||
<div style="color: var(--vscode-foreground);">
|
||||
Use this editor to edit basic IntelliSense settings defined in the underlying <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a> file.
|
||||
Changes made in this editor only apply to the selected configuration.
|
||||
To edit multiple configurations at once go to <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div style="height: 30px; display: block"></div>
|
||||
|
||||
<!-- sections -->
|
||||
<div class="section">
|
||||
<div class="section-title">Configuration name</div>
|
||||
<div class="section-text">
|
||||
A friendly name that identifies a configuration. <code>Mac</code>, <code>Linux</code>, and <code>Win32</code> are special identifiers for configurations that will be auto-selected on those platforms, but the name of the identifier can be anything.
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-note">Select a configuration set to edit.</div>
|
||||
<table>
|
||||
<tr>
|
||||
<!-- select configuration name -->
|
||||
<td>
|
||||
<div class="select-editable" style="width: 300px; margin-right: 10px">
|
||||
<select id="configSelection" style="width: 300px"></select>
|
||||
<input id=configName style="width: 267px" type="text"/>
|
||||
</div>
|
||||
</td>
|
||||
<!-- input configuration name -->
|
||||
<td style="vertical-align: middle;">
|
||||
<div id=addConfigDiv style="display: block">
|
||||
<button id=addConfigBtn >Add Configuration</button>
|
||||
</div>
|
||||
<div id=addConfigInputDiv style="display: none; width: 400px;">
|
||||
<input id=addConfigName type=text style="width: 200px; margin-right: 6px" placeholder="Configuration name..."/>
|
||||
<button id=addConfigOk style="margin-right: 6px">OK</button>
|
||||
<button id=addConfigCancel>CANCEL</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Compiler path</div>
|
||||
<div class="section-text">
|
||||
The full path of the compiler being used to build, e.g. <code>/usr/bin/gcc</code>, to enable more accurate IntelliSense.
|
||||
Arguments can be added to modify the includes/defines used, e.g. <code>-nostdinc++</code>, <code>-m32</code>, etc., but paths with spaces must be surrounded by double quotes <code>"</code> if arguments are used.
|
||||
</div>
|
||||
<!-- input compilerPath -->
|
||||
<div class="section-note">Specify a compiler path or select a detected compiler path from the drop-down list.</div>
|
||||
<div class="select-editable">
|
||||
<select id="knownCompilers" style="width: 810px"></select>
|
||||
<input name="inputValue" id="compilerPath" style="width: 777px" type="text"/>
|
||||
</div>
|
||||
<div id="compilerPathInvalid" class="error" style="width: 800px"></div>
|
||||
<!-- input compilerPath end -->
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">IntelliSense mode</div>
|
||||
<div class="section-text">
|
||||
The IntelliSense mode used by the IntelliSense engine. The <code>${default}</code> mode will choose the default for that platform.
|
||||
Windows defaults to <code>msvc-x64</code>, Linux defaults to <code>gcc-x64</code>, and Mac defaults to <code>clang-x64</code>.
|
||||
Select a specific IntelliSense mode to override the <code>${default}</code> mode.
|
||||
</div>
|
||||
<div>
|
||||
<select name="inputValue" id="intelliSenseMode" class="select-default">
|
||||
<option value="${default}">${default}</option>
|
||||
<option value="msvc-x64">msvc-x64</option>
|
||||
<option value="gcc-x64">gcc-x64</option>
|
||||
<option value="clang-x64">clang-x64</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="intelliSenseModeInvalid" class="error" style="width: 290px"></div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Include path</div>
|
||||
<div class="section-text">
|
||||
An include path is a folder that contains header files (such as <code>#include "myHeaderFile.h"</code>) that are included in a source file.
|
||||
Specify a list paths for the IntelliSense engine to use while searching for included header files.
|
||||
If a path ends with <code>/**</code> the IntelliSense engine will do a recursive search for header files starting from that directory.
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-note">One include path per line.</div>
|
||||
<textarea name="inputValue" id="includePath" rows="4" cols="93" style="width: 800px"></textarea>
|
||||
<div id="includePathInvalid" class="error" style="margin-top: -4px; width: 794px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Defines</div>
|
||||
<div class="section-text">
|
||||
A list of preprocessor definitions for the IntelliSense engine to use while parsing files. Optionally, use <code>=</code> to set a value, e.g. <code>VERSION=1</code>.
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-note">One definition per line.</div>
|
||||
<textarea name="inputValue" id="defines" rows="4" cols="39"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">C standard</div>
|
||||
<div class="section-text">The version of the C language standard to use for IntelliSense.</div>
|
||||
<div>
|
||||
<select name="inputValue" id="cStandard" class="select-default">
|
||||
<option value="c11">c11</option>
|
||||
<option value="c99">c99</option>
|
||||
<option value="c89">c89</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">C++ standard</div>
|
||||
<div class="section-text">The version of the C++ language standard to use for IntelliSense.</div>
|
||||
<div>
|
||||
<select name="inputValue" id="cppStandard" class="select-default">
|
||||
<option value="c++17">c++17</option>
|
||||
<option value="c++14">c++14</option>
|
||||
<option value="c++11">c++11</option>
|
||||
<option value="c++03">c++03</option>
|
||||
<option value="c++98">c++98</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<button id=showAdvanced class="headerBtn" style="margin-top: 5px; font-size: 20px; font-weight: 500; width: 100%; text-align: left">
|
||||
Advanced Settings
|
||||
</button>
|
||||
<div style="height: 30px; display: block"></div>
|
||||
|
||||
<div id=advancedSection>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Configuration provider</div>
|
||||
<div class="section-text">
|
||||
The ID of a VS Code extension that can provide IntelliSense configuration information for source files.
|
||||
</div>
|
||||
<div>
|
||||
<input name="inputValue" id="configurationProvider" style="width: 290px"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Windows SDK version</div>
|
||||
<div class="section-text">
|
||||
Version of the Windows SDK include path to use on Windows, e.g. <code>10.0.17134.0</code>.
|
||||
</div>
|
||||
<div>
|
||||
<input name="inputValue" id="windowsSdkVersion" style="width: 290px"></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Mac framework path</div>
|
||||
<div class="section-text">
|
||||
A list of paths for the Intellisense engine to use while searching for included headers from Mac frameworks. Only supported on Mac configuration.
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-note">One path per line.</div>
|
||||
<textarea name="inputValue" id="macFrameworkPath" rows="4" cols="93" style="width: 800px"></textarea>
|
||||
<div id="macFrameworkPathInvalid" class="error" style="margin-top: -4px; width: 794px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Forced include</div>
|
||||
<div class="section-text">
|
||||
A list of files that should be included before any other characters in the source file are processed. Files are included in the order listed.
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-note">One file per line.</div>
|
||||
<textarea name="inputValue" id="forcedInclude" rows="4" cols="93" style="width: 800px"></textarea>
|
||||
<div id="forcedIncludeInvalid" class="error" style="margin-top: -4px; width: 794px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Compile commands</div>
|
||||
<div class="section-text">
|
||||
Full path to <code>compile_commands.json</code> file for the workspace.
|
||||
</div>
|
||||
<div>
|
||||
<input name="inputValue" id="compileCommands" style="width: 798px"></input>
|
||||
<div id="compileCommandsInvalid" class="error" style="width: 800px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Browse: path</div>
|
||||
<div class="section-text">
|
||||
A list of paths for the tag parser to use while searching for included headers.
|
||||
Searching on these paths is recursive by default. Specify <code>*</code> to indicate non-recursive search.
|
||||
For example: <code>/usr/include</code> will search through all subdirectories while <code>/usr/include/*</code> will not.
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-note">One browse path per line.</div>
|
||||
<textarea name="inputValue" id="browsePath" rows="4" cols="93" style="width: 800px"></textarea>
|
||||
<div id="browsePathInvalid" class="error" style="margin-top: -4px; width: 794px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Browse: limit symbols to included headers</div>
|
||||
<div>
|
||||
<input type="checkbox" id="limitSymbolsToIncludedHeaders" style="vertical-align: middle; transform: scale(1.5)">
|
||||
Process only those files directly or indirectly included as headers. If not set, process all files under the specified include paths.
|
||||
</input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-title">Browse: database filename</div>
|
||||
<div class="section-text">
|
||||
Path to the generated symbol database. If a relative path is specified,
|
||||
it will be made relative to the workspace's default storage location.
|
||||
</div>
|
||||
<div>
|
||||
<input name="inputValue" id="databaseFilename" style="width: 798px"></input>
|
||||
<div id="databaseFilenameInvalid" class="error" style="width: 800px"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- advanced settings end -->
|
||||
|
||||
<!-- sections end -->
|
||||
|
||||
</div> <!-- main end -->
|
||||
|
||||
<script nonce="{{nonce}}" src="{{root}}/out/ui/settings.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,375 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
const elementId: { [key: string]: string } = {
|
||||
// Basic settings
|
||||
configName: "configName",
|
||||
configSelection: "configSelection",
|
||||
addConfigDiv: "addConfigDiv",
|
||||
addConfigBtn: "addConfigBtn",
|
||||
addConfigInputDiv: "addConfigInputDiv",
|
||||
addConfigOk: "addConfigOk",
|
||||
addConfigCancel: "addConfigCancel",
|
||||
addConfigName: "addConfigName",
|
||||
|
||||
compilerPath: "compilerPath",
|
||||
compilerPathInvalid: "compilerPathInvalid",
|
||||
knownCompilers: "knownCompilers",
|
||||
|
||||
intelliSenseMode: "intelliSenseMode",
|
||||
intelliSenseModeInvalid: "intelliSenseModeInvalid",
|
||||
includePath: "includePath",
|
||||
includePathInvalid: "includePathInvalid",
|
||||
defines: "defines",
|
||||
cStandard: "cStandard",
|
||||
cppStandard: "cppStandard",
|
||||
|
||||
// Advanced settings
|
||||
windowsSdkVersion: "windowsSdkVersion",
|
||||
macFrameworkPath: "macFrameworkPath",
|
||||
macFrameworkPathInvalid: "macFrameworkPathInvalid",
|
||||
compileCommands: "compileCommands",
|
||||
compileCommandsInvalid: "compileCommandsInvalid",
|
||||
configurationProvider: "configurationProvider",
|
||||
forcedInclude: "forcedInclude",
|
||||
forcedIncludeInvalid: "forcedIncludeInvalid",
|
||||
|
||||
// Browse properties
|
||||
browsePath: "browsePath",
|
||||
browsePathInvalid: "browsePathInvalid",
|
||||
limitSymbolsToIncludedHeaders: "limitSymbolsToIncludedHeaders",
|
||||
databaseFilename: "databaseFilename",
|
||||
databaseFilenameInvalid: "databaseFilenameInvalid",
|
||||
|
||||
// Other
|
||||
showAdvanced: "showAdvanced",
|
||||
advancedSection: "advancedSection"
|
||||
};
|
||||
|
||||
interface VsCodeApi {
|
||||
postMessage(msg: {}): void;
|
||||
setState(state: {}): void;
|
||||
getState(): {};
|
||||
}
|
||||
|
||||
declare function acquireVsCodeApi(): VsCodeApi;
|
||||
|
||||
class SettingsApp {
|
||||
private readonly vsCodeApi: VsCodeApi;
|
||||
private updating: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.vsCodeApi = acquireVsCodeApi();
|
||||
|
||||
window.addEventListener("keydown", this.onTabKeyDown.bind(this));
|
||||
window.addEventListener("message", this.onMessageReceived.bind(this));
|
||||
|
||||
// Add event listeners to UI elements
|
||||
this.addEventsToConfigNameChanges();
|
||||
this.addEventsToInputValues();
|
||||
document.getElementById(elementId.knownCompilers).addEventListener("change", this.onKnownCompilerSelect.bind(this));
|
||||
|
||||
// Set view state of advanced settings and add event
|
||||
const oldState: any = this.vsCodeApi.getState();
|
||||
const advancedShown: boolean = (oldState && oldState.advancedShown);
|
||||
document.getElementById(elementId.advancedSection).style.display = advancedShown ? "block" : "none";
|
||||
document.getElementById(elementId.showAdvanced).classList.toggle(advancedShown ? "collapse" : "expand", true);
|
||||
document.getElementById(elementId.showAdvanced).addEventListener("click", this.onShowAdvanced.bind(this));
|
||||
}
|
||||
|
||||
private addEventsToInputValues(): void {
|
||||
const elements: NodeListOf<HTMLElement> = document.getElementsByName("inputValue");
|
||||
elements.forEach(el => {
|
||||
el.addEventListener("change", this.onChanged.bind(this, el.id));
|
||||
});
|
||||
|
||||
// Special case for checkbox element
|
||||
document.getElementById(elementId.limitSymbolsToIncludedHeaders).addEventListener("change", this.onChangedCheckbox.bind(this, elementId.limitSymbolsToIncludedHeaders));
|
||||
}
|
||||
|
||||
private addEventsToConfigNameChanges(): void {
|
||||
document.getElementById(elementId.configName).addEventListener("change", this.onConfigNameChanged.bind(this));
|
||||
document.getElementById(elementId.configSelection).addEventListener("change", this.onConfigSelect.bind(this));
|
||||
document.getElementById(elementId.addConfigBtn).addEventListener("click", this.onAddConfigBtn.bind(this));
|
||||
document.getElementById(elementId.addConfigOk).addEventListener("click", this.OnAddConfigConfirm.bind(this, true));
|
||||
document.getElementById(elementId.addConfigCancel).addEventListener("click", this.OnAddConfigConfirm.bind(this, false));
|
||||
}
|
||||
|
||||
private onTabKeyDown(e: any): void {
|
||||
if (e.keyCode === 9) {
|
||||
document.body.classList.add("tabbing");
|
||||
window.removeEventListener("keydown", this.onTabKeyDown);
|
||||
window.addEventListener("mousedown", this.onMouseDown.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseDown(): void {
|
||||
document.body.classList.remove("tabbing");
|
||||
window.removeEventListener("mousedown", this.onMouseDown);
|
||||
window.addEventListener("keydown", this.onTabKeyDown.bind(this));
|
||||
}
|
||||
|
||||
private onShowAdvanced(): void {
|
||||
const isShown: boolean = (document.getElementById(elementId.advancedSection).style.display === "block");
|
||||
document.getElementById(elementId.advancedSection).style.display = isShown ? "none" : "block";
|
||||
|
||||
// Save view state
|
||||
this.vsCodeApi.setState({ advancedShown: !isShown });
|
||||
|
||||
// Update chevron on button
|
||||
const element: HTMLElement = document.getElementById(elementId.showAdvanced);
|
||||
element.classList.toggle("collapse");
|
||||
element.classList.toggle("expand");
|
||||
}
|
||||
|
||||
private onAddConfigBtn(): void {
|
||||
this.showElement(elementId.addConfigDiv, false);
|
||||
this.showElement(elementId.addConfigInputDiv, true);
|
||||
}
|
||||
|
||||
private OnAddConfigConfirm(request: boolean): void {
|
||||
this.showElement(elementId.addConfigInputDiv, false);
|
||||
this.showElement(elementId.addConfigDiv, true);
|
||||
|
||||
// If request is yes, send message to create new config
|
||||
if (request) {
|
||||
const el: HTMLInputElement = <HTMLInputElement>document.getElementById(elementId.addConfigName);
|
||||
if (el.value !== undefined && el.value !== "") {
|
||||
this.vsCodeApi.postMessage({
|
||||
command: "addConfig",
|
||||
name: el.value
|
||||
});
|
||||
|
||||
el.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onConfigNameChanged(): void {
|
||||
if (this.updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
const configName: HTMLInputElement = <HTMLInputElement>document.getElementById(elementId.configName);
|
||||
let list: HTMLSelectElement = <HTMLSelectElement>document.getElementById(elementId.configSelection);
|
||||
|
||||
if (configName.value === "") {
|
||||
(<HTMLInputElement>document.getElementById(elementId.configName)).value = list.options[list.selectedIndex].value;
|
||||
return;
|
||||
}
|
||||
|
||||
// Update name on selection
|
||||
list.options[list.selectedIndex].value = configName.value;
|
||||
list.options[list.selectedIndex].text = configName.value;
|
||||
|
||||
this.onChanged(elementId.configName);
|
||||
}
|
||||
|
||||
private onConfigSelect(): void {
|
||||
if (this.updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el: HTMLSelectElement = <HTMLSelectElement>document.getElementById(elementId.configSelection);
|
||||
(<HTMLInputElement>document.getElementById(elementId.configName)).value = el.value;
|
||||
|
||||
this.vsCodeApi.postMessage({
|
||||
command: "configSelect",
|
||||
index: el.selectedIndex
|
||||
});
|
||||
}
|
||||
|
||||
private onKnownCompilerSelect(): void {
|
||||
if (this.updating) {
|
||||
return;
|
||||
}
|
||||
const el: HTMLInputElement = <HTMLInputElement>document.getElementById(elementId.knownCompilers);
|
||||
(<HTMLInputElement>document.getElementById(elementId.compilerPath)).value = el.value;
|
||||
this.onChanged(elementId.compilerPath);
|
||||
|
||||
// Post message that this control was used for telemetry
|
||||
this.vsCodeApi.postMessage({
|
||||
command: "knownCompilerSelect"
|
||||
});
|
||||
|
||||
// Reset selection to none
|
||||
el.value = "";
|
||||
}
|
||||
private onChangedCheckbox(id: string): void {
|
||||
if (this.updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el: HTMLInputElement = <HTMLInputElement>document.getElementById(id);
|
||||
this.vsCodeApi.postMessage({
|
||||
command: "change",
|
||||
key: id,
|
||||
value: el.checked
|
||||
});
|
||||
}
|
||||
|
||||
private onChanged(id: string): void {
|
||||
if (this.updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el: HTMLInputElement = <HTMLInputElement>document.getElementById(id);
|
||||
this.vsCodeApi.postMessage({
|
||||
command: "change",
|
||||
key: id,
|
||||
value: el.value
|
||||
});
|
||||
}
|
||||
|
||||
private onMessageReceived(e: MessageEvent): void {
|
||||
const message: any = e.data; // The json data that the extension sent
|
||||
switch (message.command) {
|
||||
case 'updateConfig':
|
||||
this.updateConfig(message.config);
|
||||
break;
|
||||
case 'updateErrors':
|
||||
this.updateErrors(message.errors);
|
||||
break;
|
||||
case 'setKnownCompilers':
|
||||
this.setKnownCompilers(message.compilers);
|
||||
break;
|
||||
case 'updateConfigSelection':
|
||||
this.updateConfigSelection(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private updateConfig(config: any): void {
|
||||
this.updating = true;
|
||||
try {
|
||||
// Basic settings
|
||||
(<HTMLInputElement>document.getElementById(elementId.configName)).value = config.name;
|
||||
(<HTMLInputElement>document.getElementById(elementId.compilerPath)).value = config.compilerPath ? config.compilerPath : "";
|
||||
(<HTMLInputElement>document.getElementById(elementId.intelliSenseMode)).value = config.intelliSenseMode ? config.intelliSenseMode : "${default}";
|
||||
|
||||
(<HTMLInputElement>document.getElementById(elementId.includePath)).value =
|
||||
(config.includePath && config.includePath.length > 0) ? config.includePath.join("\n") : "";
|
||||
|
||||
(<HTMLInputElement>document.getElementById(elementId.defines)).value =
|
||||
(config.defines && config.defines.length > 0 ) ? config.defines.join("\n") : "";
|
||||
|
||||
(<HTMLInputElement>document.getElementById(elementId.cStandard)).value = config.cStandard;
|
||||
(<HTMLInputElement>document.getElementById(elementId.cppStandard)).value = config.cppStandard;
|
||||
|
||||
// Advanced settings
|
||||
(<HTMLInputElement>document.getElementById(elementId.windowsSdkVersion)).value = config.windowsSdkVersion ? config.windowsSdkVersion : "";
|
||||
|
||||
(<HTMLInputElement>document.getElementById(elementId.macFrameworkPath)).value =
|
||||
(config.macFrameworkPath && config.macFrameworkPath.length > 0) ? config.macFrameworkPath.join("\n") : "";
|
||||
|
||||
(<HTMLInputElement>document.getElementById(elementId.compileCommands)).value = config.compileCommands ? config.compileCommands : "";
|
||||
(<HTMLInputElement>document.getElementById(elementId.configurationProvider)).value = config.configurationProvider ? config.configurationProvider : "";
|
||||
|
||||
(<HTMLInputElement>document.getElementById(elementId.forcedInclude)).value =
|
||||
(config.forcedInclude && config.forcedInclude.length > 0) ? config.forcedInclude.join("\n") : "";
|
||||
|
||||
if (config.browse) {
|
||||
(<HTMLInputElement>document.getElementById(elementId.browsePath)).value =
|
||||
(config.browse.path && config.browse.path.length > 0) ? config.browse.path.join("\n") : "";
|
||||
(<HTMLInputElement>document.getElementById(elementId.limitSymbolsToIncludedHeaders)).checked =
|
||||
(config.browse.limitSymbolsToIncludedHeaders && config.browse.limitSymbolsToIncludedHeaders);
|
||||
(<HTMLInputElement>document.getElementById(elementId.databaseFilename)).value = config.browse.databaseFilename ? config.browse.databaseFilename : "";
|
||||
} else {
|
||||
(<HTMLInputElement>document.getElementById(elementId.browsePath)).value = "";
|
||||
(<HTMLInputElement>document.getElementById(elementId.limitSymbolsToIncludedHeaders)).checked = false;
|
||||
(<HTMLInputElement>document.getElementById(elementId.databaseFilename)).value = "";
|
||||
}
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private updateErrors(errors: any): void {
|
||||
this.updating = true;
|
||||
try {
|
||||
this.showErrorWithInfo(elementId.intelliSenseModeInvalid, errors.intelliSenseMode);
|
||||
this.showErrorWithInfo(elementId.compilerPathInvalid, errors.compilerPath);
|
||||
this.showErrorWithInfo(elementId.includePathInvalid, errors.includePath);
|
||||
this.showErrorWithInfo(elementId.macFrameworkPathInvalid, errors.macFrameworkPath);
|
||||
this.showErrorWithInfo(elementId.forcedIncludeInvalid, errors.forcedInclude);
|
||||
this.showErrorWithInfo(elementId.compileCommandsInvalid, errors.compileCommands);
|
||||
this.showErrorWithInfo(elementId.browsePathInvalid, errors.browsePath);
|
||||
this.showErrorWithInfo(elementId.databaseFilenameInvalid, errors.databaseFilename);
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private showErrorWithInfo(elementID: string, errorInfo: string): void {
|
||||
this.showElement(elementID, errorInfo ? true : false);
|
||||
document.getElementById(elementID).innerHTML = errorInfo ? errorInfo : "";
|
||||
}
|
||||
|
||||
private updateConfigSelection(message: any): void {
|
||||
this.updating = true;
|
||||
try {
|
||||
let list: HTMLSelectElement = <HTMLSelectElement>document.getElementById(elementId.configSelection);
|
||||
|
||||
// Clear list before updating
|
||||
list.options.length = 0;
|
||||
|
||||
// Update list
|
||||
for (let name of message.selections) {
|
||||
let option: HTMLOptionElement = document.createElement("option");
|
||||
option.text = name;
|
||||
option.value = name;
|
||||
list.append(option);
|
||||
}
|
||||
|
||||
list.selectedIndex = message.selectedIndex;
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private setKnownCompilers(compilers: string[]): void {
|
||||
this.updating = true;
|
||||
try {
|
||||
let list: HTMLSelectElement = <HTMLSelectElement>document.getElementById(elementId.knownCompilers);
|
||||
|
||||
// No need to add items unless webview is reloaded, in which case it will not have any elements.
|
||||
// Otherwise, add items again.
|
||||
if (list.firstChild) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (compilers.length === 0) {
|
||||
const noCompilers: string = "(No compiler paths detected)";
|
||||
let option: HTMLOptionElement = document.createElement("option");
|
||||
option.text = noCompilers;
|
||||
option.value = noCompilers;
|
||||
list.append(option);
|
||||
|
||||
// Set the selection to this one item so that no selection change event will be fired
|
||||
list.value = noCompilers;
|
||||
return;
|
||||
}
|
||||
|
||||
for (let path of compilers) {
|
||||
let option: HTMLOptionElement = document.createElement("option");
|
||||
option.text = path;
|
||||
option.value = path;
|
||||
list.append(option);
|
||||
}
|
||||
|
||||
// Initialize list with no selected item
|
||||
list.value = "";
|
||||
} finally {
|
||||
this.updating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private showElement(elementID: string, show: boolean): void {
|
||||
document.getElementById(elementID).style.display = show ? "block" : "none";
|
||||
}
|
||||
}
|
||||
|
||||
let app: SettingsApp = new SettingsApp();
|
||||
@@ -0,0 +1,44 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
/**@type {import('webpack').Configuration}*/
|
||||
const config = {
|
||||
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
|
||||
|
||||
entry: './src/main.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
|
||||
output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'main.js',
|
||||
libraryTarget: "commonjs2",
|
||||
devtoolModuleFilenameTemplate: "../[resource-path]",
|
||||
},
|
||||
devtool: 'source-map',
|
||||
externals: {
|
||||
vscode: "commonjs vscode" // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
|
||||
},
|
||||
resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'ts-loader'
|
||||
}]
|
||||
}]
|
||||
},
|
||||
optimization: {
|
||||
minimize: false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = config;
|
||||
@@ -28,4 +28,4 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
||||
|
||||
### Data/Telemetry
|
||||
|
||||
This project collects usage data and sends it to Microsoft to help improve our products and services. Read our [privacy statement](https://privacy.microsoft.com/en-us/privacystatement) to learn more.
|
||||
This extension collects usage data and sends it to Microsoft to help improve our products and services. Collection of telemetry is controlled via the same setting provided by Visual Studio Code: `"telemetry.enableTelemetry"`. Read our [privacy statement](https://privacy.microsoft.com/en-us/privacystatement) to learn more.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
name: $(Date:yyyyMMdd).$(Rev:r)
|
||||
pr:
|
||||
- 'master'
|
||||
jobs:
|
||||
- template: Extension/jobs/build.yml
|
||||
parameters:
|
||||
name: macOS
|
||||
pool:
|
||||
vmImage: 'macOS-10.13'
|
||||
|
||||
- template: Extension/jobs/build.yml
|
||||
parameters:
|
||||
name: Linux
|
||||
pool:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
|
||||
- template: Extension/jobs/build.windows.yml
|
||||
@@ -194,3 +194,23 @@ _Note: core dump debugging is not supported with MinGw._
|
||||
|
||||
* #### `sourceFileMap`
|
||||
This allows mapping of the compile time paths for source to local source locations. It is an object of key/value pairs and will resolve the first string-matched path. (example: `"sourceFileMap": { "/mnt/c": "c:\\" }` will map any path returned by the debugger that begins with `/mnt/c` and convert it to `c:\\`. You can have multiple mappings in the object but they will be handled in the order provided.)
|
||||
|
||||
## Environment variable definitions file
|
||||
|
||||
An environment variable definitions file is a simple text file containing key-value pairs in the form of `environment_variable=value`, with `#` used for comments. Multiline values are not supported.
|
||||
|
||||
The `cppvsdbg` debugger configuration also contains an `envFile` property that allows you to easily set variables for debugging purposes.
|
||||
|
||||
For example:
|
||||
|
||||
**project.env file**
|
||||
|
||||
```bash
|
||||
# project.env
|
||||
|
||||
# Example environment with key as 'MYENVRIONMENTPATH' and value as C:\\Users\\USERNAME\\Project
|
||||
MYENVRIONMENTPATH=C:\\Users\\USERNAME\\Project
|
||||
|
||||
# Variables with spaces
|
||||
SPACED_OUT_PATH="C:\\This Has Spaces\\Project"
|
||||
```
|
||||
Reference in New Issue
Block a user