Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
da277c8593 | ||
|
|
6fc9f7b682 | ||
|
|
b3cce807bb | ||
|
|
a533eb9a43 | ||
|
|
9702eae953 | ||
|
|
a4b51997ff | ||
|
|
ec9270f5a9 | ||
|
|
75f35a1fd7 | ||
|
|
dcc0174133 | ||
|
|
3b8c3143e4 | ||
|
|
33e7d70324 | ||
|
|
703e23a62b | ||
|
|
39ba7fc6ba | ||
|
|
6488a11dc3 | ||
|
|
5ca48e24cf | ||
|
|
de9cc715fc | ||
|
|
c727ceca1b | ||
|
|
f58af4fb2e | ||
|
|
7935b97329 | ||
|
|
bd6f8f0df3 | ||
|
|
4b22333f5c | ||
|
|
968e0d2aae | ||
|
|
8dc8b3bc37 | ||
|
|
bb962b91e8 | ||
|
|
8c53c027ca | ||
|
|
b864126494 | ||
|
|
b78e85619a | ||
|
|
f474ba8539 | ||
|
|
0f1071a5c9 | ||
|
|
f69e6e191b | ||
|
|
230895d6ba | ||
|
|
fa8173076d | ||
|
|
3079fb58ae | ||
|
|
9f1b482de4 | ||
|
|
8f6714254a | ||
|
|
5246cdc527 | ||
|
|
4938f5b2f4 | ||
|
|
21fef3b067 | ||
|
|
71582d1883 | ||
|
|
23fc338f71 | ||
|
|
4a8b143ce0 | ||
|
|
b1274d3c76 | ||
|
|
8f8565dbfd | ||
|
|
7f4614c31c | ||
|
|
eccee49017 | ||
|
|
e231453778 | ||
|
|
8729804dc2 | ||
|
|
c607604b6b | ||
|
|
460b95920f | ||
|
|
1c38b55b9f | ||
|
|
0cf237c839 | ||
|
|
e12bad5172 | ||
|
|
04bb260577 | ||
|
|
ddc1f901c2 | ||
|
|
9ca27af2df | ||
|
|
b964d4ebc4 | ||
|
|
082435ec8b | ||
|
|
324c5f59f4 | ||
|
|
72581c23b7 | ||
|
|
807ff80f56 | ||
|
|
b0e17a1fd9 | ||
|
|
bc64d25a1d | ||
|
|
ed5d8c8fac | ||
|
|
3a9f4c404d | ||
|
|
4330679e23 | ||
|
|
88e9724892 | ||
|
|
acf7b464eb | ||
|
|
78f5a38110 | ||
|
|
31eed4cee2 | ||
|
|
ea8ab1358f | ||
|
|
55558a53e3 | ||
|
|
536685c8a0 | ||
|
|
b6f184744c | ||
|
|
539ecc536f | ||
|
|
e819f36e91 | ||
|
|
140670c371 | ||
|
|
102ffc1616 | ||
|
|
28981f3ce6 | ||
|
|
775aba8650 | ||
|
|
b3fb2558fd | ||
|
|
80716ae228 | ||
|
|
6d71c6dd4f | ||
|
|
da68908e3e | ||
|
|
963ee02117 | ||
|
|
45a1804da4 | ||
|
|
f66eb138f4 | ||
|
|
da862646c3 | ||
|
|
1bcaa540b6 | ||
|
|
96e3386288 | ||
|
|
862a10f3f8 | ||
|
|
2e62382b24 | ||
|
|
5f9ef54c54 | ||
|
|
4575e2840e | ||
|
|
a9a09dcd11 | ||
|
|
e0e7944f3a | ||
|
|
63e18afcf1 | ||
|
|
fcdcd80157 | ||
|
|
126cf7cef6 | ||
|
|
ad451bb438 | ||
|
|
83be111769 | ||
|
|
2f931d930d | ||
|
|
bc6cb3e55f | ||
|
|
f44e9068ca | ||
|
|
c206a4b88c | ||
|
|
9e95e412a8 | ||
|
|
86ce6c6115 | ||
|
|
ecd3eb24f4 | ||
|
|
25e29a01c2 | ||
|
|
e9b8ad66a1 | ||
|
|
3e5a6aae80 | ||
|
|
49fea0249d | ||
|
|
7de9956a92 | ||
|
|
9abf44b7ac | ||
|
|
daaf169c8a | ||
|
|
23d94452bb | ||
|
|
705122a168 | ||
|
|
757f1f94be | ||
|
|
7fe2db1202 | ||
|
|
d8738c3e0c | ||
|
|
b1bd33b8f4 | ||
|
|
436c483d35 | ||
|
|
99bd382707 | ||
|
|
356bb903d0 | ||
|
|
b0fc9427cf | ||
|
|
60b20dce8d | ||
|
|
906fd2d8f0 | ||
|
|
4afadad93b | ||
|
|
3790fa95e7 | ||
|
|
a0882446d9 | ||
|
|
ce59810a6d | ||
|
|
770013d77e | ||
|
|
2388fa97f4 | ||
|
|
3381cde61c | ||
|
|
3a46f10d97 | ||
|
|
2b4b5d397d | ||
|
|
c36eb8e7b1 | ||
|
|
ad46d3887a | ||
|
|
8b704f5972 | ||
|
|
1009b76b22 | ||
|
|
84ff661e15 | ||
|
|
2292e7d762 | ||
|
|
c8e30c70b1 | ||
|
|
7947dd80d6 | ||
|
|
913f740cc2 | ||
|
|
2cbc90d98b | ||
|
|
25a29d0bc3 | ||
|
|
052f4e7b39 | ||
|
|
2b245202b5 | ||
|
|
15c6c0a50e | ||
|
|
a0e0254c73 | ||
|
|
528905326f | ||
|
|
458b2be489 | ||
|
|
95d4724dc8 | ||
|
|
a178faab9b | ||
|
|
25aa8206a0 | ||
|
|
879d880c82 | ||
|
|
16c4defcd0 | ||
|
|
725828c1c5 | ||
|
|
8b188541ba | ||
|
|
28f1bc991e | ||
|
|
aa424f1946 | ||
|
|
130711f4c5 | ||
|
|
863d26451c | ||
|
|
0a85b6c115 | ||
|
|
f2b3bd5a18 | ||
|
|
ab3e498c17 | ||
|
|
bfad3045bd | ||
|
|
842e685a6a | ||
|
|
3b36a23956 | ||
|
|
bf7287e70b | ||
|
|
63ce03573c | ||
|
|
9ddf1098f7 | ||
|
|
56f4be1f65 | ||
|
|
3b6dc61562 | ||
|
|
b8a15ddfe6 | ||
|
|
f3e188c0ce | ||
|
|
d403c8f984 | ||
|
|
35288aad17 | ||
|
|
9604256fb8 | ||
|
|
d3f701823d | ||
|
|
987347c4b6 | ||
|
|
7e7a522603 | ||
|
|
14bc488e5b | ||
|
|
352745754b | ||
|
|
dde3b515db | ||
|
|
cc6d7f3cac | ||
|
|
f8dbe57da7 | ||
|
|
4fe877ed26 | ||
|
|
974ecd3ecb | ||
|
|
7be69a0880 | ||
|
|
d77470f753 | ||
|
|
846cdc3a32 | ||
|
|
17c307a369 | ||
|
|
485d762d70 | ||
|
|
4b90e4c151 | ||
|
|
cc85f3d7c3 | ||
|
|
73c025dcee | ||
|
|
90b1ebd74c | ||
|
|
3027e18968 | ||
|
|
7729d0a700 | ||
|
|
c0e32437df | ||
|
|
b580b7347f | ||
|
|
4b5b086150 | ||
|
|
c5105f0731 | ||
|
|
b5e00c068e | ||
|
|
9b33938293 | ||
|
|
a096ec9c6f | ||
|
|
847a2e3d5a | ||
|
|
7b91a97ba7 | ||
|
|
306a55da2e | ||
|
|
7553bb9358 | ||
|
|
a60c1c51f5 | ||
|
|
891d590562 | ||
|
|
fbbe28458a | ||
|
|
3f5b0b7220 | ||
|
|
baebe0acec | ||
|
|
6d1264e6b1 | ||
|
|
0d80edba3d | ||
|
|
76870c637c | ||
|
|
7cd7d3422c | ||
|
|
a4edf98976 | ||
|
|
bffafc058a | ||
|
|
01efb1a584 | ||
|
|
b5b1ceea98 | ||
|
|
90d28133e4 | ||
|
|
39273f1087 | ||
|
|
8a0fe21176 | ||
|
|
d4e23a6063 | ||
|
|
1b218b2bd9 | ||
|
|
ddd85515fa | ||
|
|
263b69ed15 | ||
|
|
3ca02dac55 | ||
|
|
42698a85cd | ||
|
|
605adb1edd |
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Debugger
|
||||
about: Issues pertaining to debugging such as call stack, breakpoints, watch window,
|
||||
launching or attaching to a debuggee.
|
||||
|
||||
---
|
||||
|
||||
Type: Debugger
|
||||
**Input information below**
|
||||
|
||||
**Please review existing issues and our documentation at https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation prior to filing an issue.**
|
||||
|
||||
**Describe the bug**
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- Other extensions you installed (and if the issue persists after disabling them):
|
||||
- A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
*Please include a code sample and `launch.json` configuration.*
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Additional context**
|
||||
*If applicable, please include logging by adding "logging": { "engineLogging": true, "trace": true, "traceResponse": true } in your `launch.json`*
|
||||
Add any other context about the problem here including log or error messages in your Debug Console or Output windows.
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: General Extension
|
||||
about: Issues pertaining to downloading, installing, or building the extension.
|
||||
|
||||
---
|
||||
|
||||
Type: General
|
||||
**Input information below**
|
||||
|
||||
**Please review existing issues and our documentation at https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation prior to filing an issue.**
|
||||
|
||||
**Describe the bug**
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- Other extensions you installed (and if the issue persists after disabling them):
|
||||
- A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
*Please include code sample and `task.json` files.*
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here including log messages from the Output window.
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Language Service
|
||||
about: 'Issues pertaining to IntelliSense, autocomplete, code editing, etc. '
|
||||
|
||||
---
|
||||
|
||||
**Type: LanguageService**
|
||||
<!----- Input information below ----->
|
||||
|
||||
<!--
|
||||
**Please review existing issues and our documentation at https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation prior to filing an issue.**
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
- OS and Version:
|
||||
- VS Code Version:
|
||||
- C/C++ Extension Version:
|
||||
- Other extensions you installed (and if the issue persists after disabling them):
|
||||
- A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
<!-- Steps to reproduce the behavior: -->
|
||||
<!-- *The most actionable issue reports include a code sample including configuration files such as c_cpp_properties.json* -->
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots**
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**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. 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
|
||||
-41
@@ -1,41 +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 test
|
||||
# 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 |
Vendored
+2
-2
@@ -4,7 +4,7 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "build",
|
||||
"label": "build",
|
||||
"type": "shell",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
@@ -47,4 +47,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
## How to build and debug the Microsoft CppTools Extension
|
||||
|
||||
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.
|
||||
* 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 -g vsce` will install `vsce` globally to create the vsix package.
|
||||
* `npm install` will install the dependencies needed to build the extension.
|
||||
* Set an environment variable `CPPTOOLS_DEV=1`.
|
||||
* This enables the local developer workflow, copying dependencies from the **node_modules** folder.
|
||||
* Open the **Extension** folder in Visual Studio Code and F5.
|
||||
* Read the [contributing guidelines](https://github.com/Microsoft/vscode-cpptools/blob/master/CONTRIBUTING.md).
|
||||
## How to build and debug the Microsoft CppTools Extension
|
||||
|
||||
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 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.
|
||||
* **(optional)** `npm install -g vsce` will install `vsce` globally to create a VSIX package that you can install.
|
||||
* **(optional)** Set an environment variable `CPPTOOLS_DEV=1`.
|
||||
* This enables the local developer workflow when testing the debugger, copying dependencies from the **node_modules** folder. Testing the language server does not require this step.
|
||||
* Open the **Extension** folder in Visual Studio Code and press F5. This will launch a VS Code Extension Host window and activate the TypeScript debugger. You can set breakpoints on the extension source code and debug your scenario.
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# How To Debug MIEngine (Work in Progress)
|
||||
|
||||
*This is a work in progress. Please create a pull request with updates if there is anything wrong with it.*
|
||||
# How To Debug MIEngine
|
||||
|
||||
MIEngine is one of the components used to enable the C/C++ debugging scenario with the Microsoft C/C++ extension with VS Code. This document is to help enable users who want to debug and contribute to MIEngine to fix issues or extend functionality. MIEngine is used to communicate with `gdb`/`lldb` using the MI protocol.
|
||||
|
||||
@@ -15,39 +13,52 @@ You can open the solution file **MIDebugEngine.sln** located under **src** and c
|
||||
* Microsoft.MICore.dll
|
||||
* Microsoft.MICore.XmlSerializers.dll
|
||||
* Microsoft.MIDebugEngine.dll
|
||||
* vscode\OpenDebugAD7.exe
|
||||
* vscode\Microsoft.DebugEngineHost.dll
|
||||
* vscode\Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.dll
|
||||
|
||||
The symbol files are as follows:
|
||||
|
||||
**On Windows**
|
||||
* Microsoft.MICore.pdb
|
||||
* Microsoft.MIDebugEngine.dll
|
||||
* Microsoft.MIDebugEngine.pdb
|
||||
* vscode\OpenDebugAD7.pdb
|
||||
* vscode\Microsoft.DebugEngineHost.pdb
|
||||
|
||||
**On Linux/Mac**
|
||||
* Microsoft.MICore.dll.mdb
|
||||
* Microsoft.MIDebugEngine.dll.mdb
|
||||
* vscode\OpenDebugAD7.exe.mdb
|
||||
* vscode\Microsoft.DebugEngineHost.dll.mdb
|
||||
|
||||
### Debugging On Windows
|
||||
|
||||
On Windows, the easiest way to debug is to use Visual Studio. Locate the **package.json** file in the **Extension** folder and open it in an editor.
|
||||
On Windows, the easiest way to debug is to use Visual Studio. Locate the **src\Debugger\extension.ts** file in the **Extension** folder and open it in an editor.
|
||||
|
||||
Locate the following line:
|
||||
If you are not building the extension, Locate the **out\src\Debugger\extension.ts** file in the **.vscode\extensions\ms-vscode.cpptools** folder and open it in an editor.
|
||||
|
||||
Locate the following lines:
|
||||
```json
|
||||
"program": "./debugAdapters/OpenDebugAD7",
|
||||
return {
|
||||
command: command
|
||||
};
|
||||
```
|
||||
and add the following line below it:
|
||||
and add the following line to the object:
|
||||
```json
|
||||
"args": ["--pauseForDebugger"],
|
||||
args: ["--pauseForDebugger"]
|
||||
```
|
||||
|
||||
This will cause the debugger to look like it has hung once you start debugging, but in reality it is waiting for a debugger to attach. Set your breakpoints and attach your debugger to the `OpenDebugAD7.exe` process. Once the debugger is attached, VS Code should start debugging and you can reproduce your scenario.
|
||||
|
||||
### Debugging MIEngine running on Linux or Mac OS X
|
||||
|
||||
#### With MonoDevelop
|
||||
|
||||
On Linux and Mac OS X, we use `mono` as our framework. You can download Xamarin Studio v5.10.1.6 and remotely attach to your Mac or Linux box to debug there.
|
||||
|
||||
#### Install Prerequisites
|
||||
1. Install [GTK](http://www.mono-project.com/download/)
|
||||
2. Install [Xamarin Studio v5.10.1.6](http://download.xamarin.com/studio/Windows/XamarinStudio-5.10.1.6-0.msi)
|
||||
##### Install Prerequisites
|
||||
1. Install [GTK](http://www.mono-project.com/download/).
|
||||
2. Install [Xamarin Studio v5.10.1.6](http://download.xamarin.com/studio/Windows/XamarinStudio-5.10.1.6-0.msi).
|
||||
|
||||
Remote attach functionality behind a flag. You can run it like this:
|
||||
```PowerShell
|
||||
@@ -56,26 +67,60 @@ set MONODEVELOP_SDB_TEST=1
|
||||
MonoDevelop.exe
|
||||
```
|
||||
|
||||
#### Create an empty project for attaching (one-time setup)
|
||||
##### Create an empty project for attaching (one-time setup)
|
||||
|
||||
1. Launch MonoDevelop
|
||||
2. File -> New Solution
|
||||
3. Misc/Generic Project
|
||||
4. Name project and hit "Create"
|
||||
5. Right-click the project node (blue square) and do "Options"
|
||||
1. Launch MonoDevelop.
|
||||
2. File -> New Solution.
|
||||
3. Misc/Generic Project.
|
||||
4. Name project and hit "Create".
|
||||
5. Right-click the project node (blue square) and do "Options".
|
||||
6. Under Run -> Custom Commands, select "Execute" in the lower dropdown and choose a command (I use `c:\windows\notepad.exe` - it doesn't matter what the command is, but MonoDevelop requires it to exist before it'll light up the Run menu).
|
||||
|
||||
#### Configure the extension to enable remote debugging
|
||||
##### Configure the extension to enable remote debugging
|
||||
|
||||
Open the **~/.vscode/extensions/ms-vscode.cpptools-\<version\>/debugAdapters/OpenDebugAD7** file with a text editor and locate and uncomment the line at the bottom. When you start debugging, it will now hang until the remote debugger is attached from Xamarin Studio.
|
||||
|
||||
#### Attach the remote debugger
|
||||
##### Attach the remote debugger
|
||||
|
||||
In MonoDevelop: Run -> Run With -> Custom Command Mono Soft Debugger
|
||||
Fill in the IP and port of the Linux/Mac OS X machine and hit "Connect" to start debugging
|
||||
In MonoDevelop: Run -> Run With -> Custom Command Mono Soft Debugger.
|
||||
Fill in the IP and port of the Linux/Mac OS X machine and hit "Connect" to start debugging.
|
||||
|
||||
After you've done this once, you can hit the MonoDevelop "Play" button or <kbd>F5</kbd> to bring up the connect dialog again.
|
||||
|
||||
Note: If you are debugging to CentOS, you will need to make an exception in the firewall
|
||||
#### With VS Code + Mono Debug
|
||||
|
||||
##### Install Prerequisites
|
||||
1. Install [VS Code](https://code.visualstudio.com/Download).
|
||||
2. Install Mono Debug extension for VS Code.
|
||||
|
||||
##### Create an empty project (one-time setup)
|
||||
1. Open to a new folder and create `.vscode/launch.json`.
|
||||
2. Create the following configuration in launch.json.
|
||||
```
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach to Mono",
|
||||
"request": "attach",
|
||||
"type": "mono",
|
||||
"address": "<INSERT_MACHINE_IP_ADDRESS_HERE>",
|
||||
"port": 1234
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
##### Configure the extension to enable remote debugging
|
||||
|
||||
Open the **~/.vscode/extensions/ms-vscode.cpptools-\<version\>/debugAdapters/OpenDebugAD7** file with a text editor and locate and uncomment the line at the bottom. When you start debugging, it will now hang until the remote debugger is attached from VS Code.
|
||||
|
||||
##### Attach the remote debugger
|
||||
|
||||
Select the `Attach to Mono` configuration and hit F5.
|
||||
|
||||
#### Additional Notes
|
||||
|
||||
Note: If you are debugging to CentOS, you will need to make an exception in the firewall.
|
||||
* `sudo firewall-cmd --zone=public --add-port=1234/tcp --permanent`
|
||||
* `sudo firewall-cmd --reload`
|
||||
|
||||
+59
-2
@@ -2,8 +2,11 @@
|
||||
|
||||
## 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)
|
||||
* Build: [How to enable debug symbols](#how-to-enable-debug-symbols)
|
||||
* Logging: [How to enable logging](#how-to-enable-logging)
|
||||
|
||||
## Debugging Setup
|
||||
The debugger needs to be configured to know which executable and debugger to use:
|
||||
@@ -14,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
|
||||
@@ -22,7 +43,7 @@ When you start debugging, if it is showing that your breakpoints aren't bound (s
|
||||
|
||||
### Debugging starts but all the lines in my stack trace are grey
|
||||
|
||||
If your debugger is showing a grey stacktrace or won't stop at a breakpoint,or the symbols in the call stack are grey then your executable was compiled without [debug symbols](#how-to-enable-debug-symbols).
|
||||
If your debugger is showing a grey stacktrace or won't stop at a breakpoint, or the symbols in the call stack are grey then your executable was compiled without [debug symbols](#how-to-enable-debug-symbols).
|
||||
|
||||
## How to enable debug symbols?
|
||||
|
||||
@@ -43,3 +64,39 @@ When in doubt, please check your compiler's documentation for the options necess
|
||||
|
||||
* #### cl.exe
|
||||
Symbols are located in the `*.pdb` file.
|
||||
|
||||
## How to enable logging
|
||||
|
||||
Enabling logging will show communication information between VS Code and our extension and between our extension and the debugger.
|
||||
|
||||
### Logging for `MI` debuggers
|
||||
|
||||
The logging block with its defaults is as follows:
|
||||
|
||||
```
|
||||
"logging": {
|
||||
"trace": false,
|
||||
"traceResponse": false,
|
||||
"engineLogging": false
|
||||
}
|
||||
```
|
||||
|
||||
#### VS Code and the CppTools extension
|
||||
|
||||
The logging here is called `trace` logging and can be enabled by setting `trace` and `traceResponse` to `true` in the logging block inside `launch.json`. This will help diagnose issues related to VS Code's communication to our extension and our responses.
|
||||
|
||||
#### CppTools extension and the debugger
|
||||
|
||||
The logging between CppTools and the debugger is called `engineLogging`. When using an `MI` debugger such as `gdb` or `lldb`, this will show the request, response and events using the `mi` interpreter. This logging will help us determine whether the debugger is receiving the right commands and generating the correct responses.
|
||||
|
||||
### Logging for `Visual C++` debugger
|
||||
|
||||
The logging block with its defaults is as follows:
|
||||
|
||||
```
|
||||
"logging": {
|
||||
"engineLogging": false
|
||||
}
|
||||
```
|
||||
|
||||
The `Visual C++` debugger logging will show only the communication to and from VS Code as all communication to the debugger is done internally to the process and is not visible through logging.
|
||||
|
||||
@@ -77,13 +77,13 @@ A new setting will be added that allows you specify the system include path sepa
|
||||
C_Cpp.default.systemIncludePath : string[]
|
||||
```
|
||||
|
||||
### Include Path Resolution Strategies
|
||||
### System Include Path/Defines Resolution Strategies
|
||||
|
||||
The extension determines the includePath to send to the IntelliSense engine in the following manner:
|
||||
The extension determines the system includePath and defines to send to the IntelliSense engine in the following manner:
|
||||
|
||||
1. If `compileCommands` has a valid value and the file open in the editor is in the database, use the compile command in the database entry to determine the include path and defines.
|
||||
* The system include path and defines are determined using the following logic (in order):
|
||||
1. If `systemIncludePath` has a value, use it (continue to the next step to seach for system defines).
|
||||
1. If `systemIncludePath` has a value, use it (continue to the next step to search for system defines).
|
||||
2. If `compilerPath` is valid, query it.
|
||||
3. Interpret the first argument in the command as the compiler and attempt to query it.
|
||||
4. If `compilerPath` is `""`, use an empty array for system include path and defines.
|
||||
@@ -91,7 +91,7 @@ The extension determines the includePath to send to the IntelliSense engine in t
|
||||
|
||||
2. If `compileCommands` is invalid or the current file is not listed in the database, use the `includePath` and `defines` properties in the configuration for IntelliSense.
|
||||
* The system include path and defines are determined using the following logic (in order):
|
||||
1. If `systemIncludePath` has a value, use it (continue to the next step to seach for system defines).
|
||||
1. If `systemIncludePath` has a value, use it (continue to the next step to search for system defines).
|
||||
2. If `compilerPath` is valid, query it.
|
||||
3. If `compilerPath` is `""`, use an empty array for system include path and defines (they are assumed to be in the `includePath` and `defines` for the current config already).
|
||||
4. If `compilerPath` is undefined, look for a compiler on the system and query it.
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
If you are experiencing a problem that we are unable to diagnose based on information in your issue report, we might ask you to enable logging and send us your logs.
|
||||
|
||||
As of version 0.14.0 of the extension, logging information is now delivered directly to the Output window in VSCode. To turn on full logging for an issue report, add `"C_Cpp.loggingLevel": "Information"` to your **settings.json**.
|
||||
As of version 0.14.0 of the extension, logging information is now delivered directly to the Output window in VSCode. To turn on full logging for an issue report, add `"C_Cpp.loggingLevel": "Information"` or `"C_Cpp.loggingLevel": "Debug"` to your **settings.json**.
|
||||
|
||||

|
||||

|
||||
|
||||
VS Code organizes the logging from different extensions to improve readability so you must select the "C/C++" option in the log filter selector to see logging from the C/C++ extension:
|
||||
|
||||
|
||||
@@ -31,7 +31,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**.
|
||||
|
||||
@@ -39,6 +39,6 @@ We recommend using the "Default" engine for the best IntelliSense experience. Ho
|
||||
|
||||
### See Also
|
||||
|
||||
[Configuring includePath for better IntelliSense results](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/Getting%20started.md)
|
||||
[Configuring includePath for better IntelliSense results](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/Getting%20started%20with%20IntelliSense%20configuration.md)
|
||||
|
||||
[**c_cpp_properties.json** reference guide](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/c_cpp_properties.json.md)
|
||||
|
||||
@@ -4,29 +4,28 @@ To use MinGW on Windows, we recommend you add the following configuration to you
|
||||
|
||||
## Extension version 0.17.0 and higher:
|
||||
|
||||
When you set the `compilerPath` property and change `intelliSenseMode` to `clang-x64`, you no longer need to copy the system include path or defines to `includePath`, `browse.path`, or `defines` to enable IntelliSense to work properly. For example:
|
||||
When you set the `compilerPath` property and change `intelliSenseMode` to `clang-x64` (or `gcc-x64` in version 0.18.0 and higher), you no longer need to copy the system include path or defines to `includePath`, `browse.path`, or `defines` to enable IntelliSense to work properly. For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "MinGW",
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"intelliSenseMode": "gcc-x64",
|
||||
"compilerPath": "C:/mingw64/bin/gcc.exe",
|
||||
"includePath": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"defines": [],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
},
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17"
|
||||
}
|
||||
```
|
||||
|
||||
Replace "gcc.exe" with whatever compiler you're using, e.g. "g++.exe", "clang-5.0.exe", etc. -- just make sure the file is a valid Windows executable (not a 0 size symlink).
|
||||
|
||||
For Cygwin, set the `compilerPath` to the appropriate Cygwin path, e.g. "C:/cygwin64/bin/g++.exe".
|
||||
|
||||
If it seems like the `compilerPath` is not getting used, you can debug the issue via [enabling logging](Enabling%20logging.md).
|
||||
|
||||
## Extension version 0.16.1 and earlier:
|
||||
|
||||
If you have an older version of the C/C++ extension installed, use [these instructions](Archive/MinGW.md) instead.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Windows Subsystem for Linux
|
||||
|
||||
> **Note:** If you are on **build 17110 of Windows or higher**, you must use version 0.17.0 or higher for IntelliSense to work. The Windows team turned on case-sensitive folders for the WSL environment and the C/C++ extension doesn't support case-sensitive folders until version 0.17.0.
|
||||
> **Note:** If you are on **build 17110 of Windows or higher**, you must use extension version 0.17.0 or higher for IntelliSense to work. The Windows team turned on case-sensitive folders for the WSL environment and the C/C++ extension doesn't support case-sensitive folders until version 0.17.0.
|
||||
|
||||
To use the Windows Subsystem for Linux with this extension you need to add a configuration to your **c_cpp_properties.json** file which adds the necessary header paths from within the WSL filesystem to the `includePath`.
|
||||
|
||||
@@ -13,22 +13,12 @@ In **c_cpp_properties.json** you can directly address your WSL compiler and incl
|
||||
```json
|
||||
{
|
||||
"name": "WSL",
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"intelliSenseMode": "gcc-x64",
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"includePath": [
|
||||
"${workspaceFolder}",
|
||||
"/mnt/c/libraries/lib1/include",
|
||||
"C:/libraries/lib2/include"
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${workspaceFolder}",
|
||||
"/mnt/c/libraries"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
},
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
```json
|
||||
{
|
||||
"env" : {
|
||||
"defaultIncludePath": [
|
||||
"myDefaultIncludePath": [
|
||||
"${workspaceFolder}",
|
||||
"${workspaceFolder}/include"
|
||||
],
|
||||
@@ -15,9 +15,9 @@
|
||||
},
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"intelliSenseMode": "msvc-x64",
|
||||
"includePath": [ "${defaultIncludePath}", "/another/path" ],
|
||||
"name": "Mac",
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"includePath": [ "${myDefaultIncludePath}", "/another/path" ],
|
||||
"macFrameworkPath": [ "/System/Library/Frameworks" ],
|
||||
"defines": [ "FOO", "BAR=100" ],
|
||||
"forcedInclude": [ "${workspaceFolder}/include/config.h" ],
|
||||
@@ -42,7 +42,7 @@
|
||||
An array of user-defined variables that will be available for substitution in the configurations via the standard environment variable syntax: `${<var>}` or `${env:<var>}`. Strings and arrays of strings are accepted.
|
||||
|
||||
* #### `configurations`
|
||||
An array of configuration objects that provide the IntelliSense engine with information about your project and your preferences. By default, the extension creates 3 configurations for you, one each for Linux, Mac, and Windows, but it is not required to keep them all. You may also add additional configurations if necessary.
|
||||
An array of configuration objects that provide the IntelliSense engine with information about your project and your preferences. By default, the extension creates a configuration for you based on your operating system. You may also add additional configurations.
|
||||
|
||||
* #### `version`
|
||||
We recommend you don't edit this field. It tracks the current version of the **c_cpp_properties.json** file so that the extension knows what properties and settings should be present and how to upgrade this file to the latest version.
|
||||
@@ -53,22 +53,26 @@
|
||||
A friendly name for the configuration. "Linux", "Mac", and "Win32" are special names that instruct the extension to load that configuration by default on the associated operating system unless additional configurations have been created. The status bar in VS Code will show you which configuration is active. You can also click on the label in the status bar to change the active configuration.
|
||||
|
||||
* #### `intelliSenseMode`
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this property determines which mode the IntelliSense engine will run in. `"msvc-x64"` maps to Visual Studio mode with 64-bit pointer sizes. `"clang-x64"` maps to GCC/CLang mode with 64-bit pointer sizes. Windows uses `"msvc-x64"` by default and Linux/Mac use `"clang-x64"` by default.
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this property determines which mode the IntelliSense engine will run in. `"msvc-x64"` maps to Visual Studio mode with 64-bit pointer sizes. `"clang-x64"` maps to CLang mode with 64-bit pointer sizes. `"gcc-x64"` maps to GCC mode with 64-bit pointer sizes. Windows uses `"msvc-x64"` by default, macOS uses `"clang-x64"` by default, and Linux uses `"gcc-x64"` by default.
|
||||
|
||||
* #### `includePath`
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of paths will be used by IntelliSense to search for headers included by your source files. This is basically the same as the list of paths you pass to your compiler with the `-I` switch; the IntelliSense engine will not do a recursive search in these paths for includes. If a GCC/CLang compiler is specified in the `compilerPath` setting, it is not necessary to list the system include paths in this list.
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of paths will be used by IntelliSense to search for headers included by your source files. This is basically the same as the list of paths you pass to your compiler with the `-I` switch. If a path ends with `/**` the IntelliSense engine will do a recursive search for includes starting from that directory. If on Windows with Visual Studio installed, or if a compiler is specified in the `compilerPath` setting, it is not necessary to list the system include paths in this list.
|
||||
|
||||
* #### `macFrameworkPath`
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of paths will be used by IntelliSense to search for framework headers included by your source files. This is basically the same as the list of paths you pass to your compiler with the `-F` switch; the IntelliSense engine will not do a recursive search in these paths for includes.
|
||||
|
||||
* #### `defines`
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of preprocessor symbols will be used by IntelliSense during the compilation of your source files. This is basically the same as the list of symbols you pass to your compiler with the `-D` switch.
|
||||
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of preprocessor symbols will be used by IntelliSense during the compilation of your source files. This is basically the same as the list of symbols you pass to your compiler with the `-D` switch. If on Windows with Visual Studio installed, or if a compiler is specified in the `compilerPath` setting, it is not necessary to list the system include paths in this list.
|
||||
|
||||
* #### `forcedInclude` (optional)
|
||||
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.
|
||||
|
||||
* #### `compilerPath` (optional)
|
||||
The absolute path to the compiler you use to build your project. The extension will query the compiler to determine the system include paths and default defines to use for IntelliSense. Args can be added to modify the includes/defines used, e.g. `-nostdinc++`, `-m32`, etc., but paths with spaces must be surrounded by double quotes (`"`) if args are used.
|
||||
The absolute path to the compiler you use to build your project. The extension will query the compiler to determine the system include paths and default defines to use for IntelliSense.
|
||||
|
||||
Args can be added to modify the includes/defines used, e.g. `-nostdinc++`, `-m32`, `-fno-ms-extensions`, etc., but paths with spaces must be surrounded by double quotes (`"`) if args are used.
|
||||
|
||||
If you want to disable automatic querying of system include paths and defines, set this value to the emptry string `""`. This is generally not recommended, but there are some cases where automatic querying of system includes and defines is undesirable.
|
||||
|
||||
* #### `cStandard`
|
||||
The C standard revision to use for IntelliSense in your project.
|
||||
@@ -87,7 +91,7 @@
|
||||
### Browse properties
|
||||
|
||||
* #### `path`
|
||||
This list of paths will be used by the Tag Parser to search for headers included by your source files. The Tag Parser will automatically search all subfolders in these paths unless the path ends with a `/*` or `\*`. For example, `/usr/include` directs the Tag Parser to search the `include` folder and its subfolders for headers while `/usr/include/*` directs the Tag Parser not to look in any subfolders of `/usr/include`.
|
||||
This list of paths will be used by the Tag Parser to search for headers included by your source files. If omitted, `includePath` will be used as the `path`. The Tag Parser will automatically search all subfolders in these paths unless the path ends with a `/*` or `\*`. For example, `/usr/include` directs the Tag Parser to search the `include` folder and its subfolders for headers while `/usr/include/*` directs the Tag Parser not to look in any subfolders of `/usr/include`.
|
||||
|
||||
* #### `limitSymbolsToIncludedHeaders`
|
||||
When true, the Tag Parser will only parse code files that have been directly or indirectly included by a source file in `${workspaceFolder}`. When false, the Tag Parser will parse all code files found in the paths specified in the **path** list.
|
||||
|
||||
@@ -3,6 +3,7 @@ node_modules
|
||||
|
||||
# ignore compliled typescript
|
||||
out
|
||||
dist
|
||||
|
||||
# ignore downloaded extension files and folders
|
||||
server
|
||||
@@ -17,4 +18,4 @@ install.lock
|
||||
*.vsix
|
||||
|
||||
# ignore vscode test
|
||||
.vscode-test/
|
||||
.vscode-test/
|
||||
|
||||
Vendored
+7
-6
@@ -13,9 +13,9 @@
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "compile",
|
||||
"preLaunchTask": "Compile Dev",
|
||||
},
|
||||
{
|
||||
"name": "Launch Tests",
|
||||
@@ -24,14 +24,14 @@
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test"
|
||||
"--extensionTestsPath=${workspaceFolder}/out/test/unitTests"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/test/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "compile"
|
||||
"preLaunchTask": "TypeScript Compile"
|
||||
},
|
||||
{
|
||||
"name": "Node Attach",
|
||||
@@ -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
+31
-3
@@ -5,7 +5,6 @@
|
||||
"tasks": [
|
||||
{
|
||||
"label": "TypeScript Compile",
|
||||
"identifier": "compile",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
@@ -29,7 +28,6 @@
|
||||
},
|
||||
{
|
||||
"label": "TypeScript Lint",
|
||||
"identifier": "tslint",
|
||||
"group": "build",
|
||||
"isBackground": false,
|
||||
"type": "shell",
|
||||
@@ -53,8 +51,38 @@
|
||||
]
|
||||
},
|
||||
"dependsOn": [
|
||||
"compile"
|
||||
"TypeScript Compile"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Compile Dev",
|
||||
"group": "build",
|
||||
"isBackground": false,
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"compileDev"
|
||||
],
|
||||
"dependsOn": [
|
||||
"TypeScript Compile"
|
||||
],
|
||||
"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
|
||||
+326
-14
@@ -1,5 +1,317 @@
|
||||
# C/C++ for Visual Studio Code Change Log
|
||||
|
||||
## 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)
|
||||
* Add macro expansions to hover. [#1734](https://github.com/Microsoft/vscode-cpptools/issues/1734)
|
||||
* Add support for `__int128_t` and `__uint128_t` types. [#1815](https://github.com/Microsoft/vscode-cpptools/issues/1815)
|
||||
* Add Italian translations for command titles.
|
||||
* Julien Russo (@Dotpys) [PR #2663](https://github.com/Microsoft/vscode-cpptools/pull/2663)
|
||||
* Add icons for operators, structs/unions, enum values, template arguments, and macros. [#2849](https://github.com/Microsoft/vscode-cpptools/issues/2849)
|
||||
* Change `#include` completion to show individual folders instead of the entire paths, fixing previous performance problems. [#2836](https://github.com/Microsoft/vscode-cpptools/issues/2836)
|
||||
* Add text `(declaration)`, `(typedef)`, `(type alias)`, and `(union)` to symbols. [#2851](https://github.com/Microsoft/vscode-cpptools/issues/2851)
|
||||
* Add a refresh button to the `Attach to Process` picker. [#2885](https://github.com/Microsoft/vscode-cpptools/issues/2885)
|
||||
* Matt Bise (@mbise1993) [PR #2895](https://github.com/Microsoft/vscode-cpptools/pull/2895)
|
||||
* Add completion committing for templates after `<`. [#2953](https://github.com/Microsoft/vscode-cpptools/issues/2953)
|
||||
|
||||
### Bug Fixes
|
||||
* Add the Microsoft digital signature to Windows binaries to avoid getting incorrectly flagged by virus scanners. [#1103](https://github.com/Microsoft/vscode-cpptools/issues/1103), [#2970](https://github.com/Microsoft/vscode-cpptools/issues/2970)
|
||||
* Fix bugs when UTF-8 characters > 1 byte are used. [#1504](https://github.com/Microsoft/vscode-cpptools/issues/1504), [#1525](https://github.com/Microsoft/vscode-cpptools/issues/1525), [#2034](https://github.com/Microsoft/vscode-cpptools/issues/2034), [#2082](https://github.com/Microsoft/vscode-cpptools/issues/2082), [#2883](https://github.com/Microsoft/vscode-cpptools/issues/2883)
|
||||
* Fix some IntelliSense process crashes. [#1785](https://github.com/Microsoft/vscode-cpptools/issues/1785), [#2913](https://github.com/Microsoft/vscode-cpptools/issues/2913)
|
||||
* Fix several incorrect IntelliSense error squiggles. [#1942](https://github.com/Microsoft/vscode-cpptools/issues/1942), [#2422](https://github.com/Microsoft/vscode-cpptools/issues/2422), [#2474](https://github.com/Microsoft/vscode-cpptools/issues/2474), [#2478](https://github.com/Microsoft/vscode-cpptools/issues/2478), [#2597](https://github.com/Microsoft/vscode-cpptools/issues/2597), [#2763](https://github.com/Microsoft/vscode-cpptools/issues/2763)
|
||||
* Fix some main process crashes. [#2505](https://github.com/Microsoft/vscode-cpptools/issues/2505), [#2768](https://github.com/Microsoft/vscode-cpptools/issues/2768)
|
||||
* Fix incorrect IntelliSense error with Mac clang 10.0 libraries. [#2608](https://github.com/Microsoft/vscode-cpptools/issues/2608)
|
||||
* Fix completion not working in template specializations. [#2620](https://github.com/Microsoft/vscode-cpptools/issues/2620)
|
||||
* Fix incorrect completions after Enter is used after struct, class, etc. [#2734](https://github.com/Microsoft/vscode-cpptools/issues/2734)
|
||||
* Fix memory "leak" when parsing a large workspace. [#2737](https://github.com/Microsoft/vscode-cpptools/issues/2737)
|
||||
* Fix IntelliSense-based `Go to Definition` with overloads that return a template with a default param (e.g. vector) [#2736](https://github.com/Microsoft/vscode-cpptools/issues/2736)
|
||||
* Fix `Go to Definition` when `__catch()`, `_NO_EXCEPT_DEBUG`, or `_LIBCPP_BEGIN_NAMESPACE_STD` is used. [#2761](https://github.com/Microsoft/vscode-cpptools/issues/2761), [#2766](https://github.com/Microsoft/vscode-cpptools/issues/2766)
|
||||
* Fix `Go to Definition` when `method(void)` is used. [#2802](https://github.com/Microsoft/vscode-cpptools/issues/2802)
|
||||
* Fix error `"TypeError: Cannot read property 'map' of undefined at asCompletionResult"`. [#2807](https://github.com/Microsoft/vscode-cpptools/issues/2807)
|
||||
* Fix quotes around defines not supported for custom configuration providers. [#2820](https://github.com/Microsoft/vscode-cpptools/issues/2820)
|
||||
* Fix PowerShell bug on Win7. [#2822](https://github.com/Microsoft/vscode-cpptools/issues/2822)
|
||||
* Fix Tag Parser completion details missing keywords (i.e. `using`, `class`, `#define`, etc.). [#2850](https://github.com/Microsoft/vscode-cpptools/issues/2850)
|
||||
* Fix problem with empty recursive include paths. [#2855](https://github.com/Microsoft/vscode-cpptools/issues/2855)
|
||||
* Fix `NullReferenceException` on debugger launch with VS Code Insiders. [#2858](https://github.com/Microsoft/vscode-cpptools/issues/2858), [PR Microsoft/MIEngine#810](https://github.com/Microsoft/MIEngine/pull/810)
|
||||
* Fix IntelliSense errors with template argument deduction. [#2907](https://github.com/Microsoft/vscode-cpptools/issues/2907), [#2912](https://github.com/Microsoft/vscode-cpptools/issues/2912)
|
||||
* Retry Insider VSIX downloading with `http.proxySupport` `"off"`. [#2927](https://github.com/Microsoft/vscode-cpptools/issues/2927)
|
||||
* Fix snippet completions being offered when they shouldn't be. [#2942](https://github.com/Microsoft/vscode-cpptools/issues/2942)
|
||||
* Set the `editor.wordBasedSuggestions` to `false` by default to prevent incorrect completions. [#2943](https://github.com/Microsoft/vscode-cpptools/issues/2943)
|
||||
* Fix IntelliSense-based `Go to Definition` for functions with function pointer parameters. [#2981](https://github.com/Microsoft/vscode-cpptools/issues/2981)
|
||||
* Fix `<` incorrectly triggering completions. [#2985](https://github.com/Microsoft/vscode-cpptools/issues/2985)
|
||||
* Fix recursive includes not adding paths used by `forcedInclude` files. [#2986](https://github.com/Microsoft/vscode-cpptools/issues/2986)
|
||||
* Fix crash when `//` is used in a recursive `includePath`. [#2987](https://github.com/Microsoft/vscode-cpptools/issues/2987)
|
||||
* Fix compiler in `compile_commands.json` not taking precedence over the `Cpp.default.compilerPath`. [#2793](https://github.com/Microsoft/vscode-cpptools/issues/2793)
|
||||
* Fix `#include` completion not working for symlinks. [#2843](https://github.com/Microsoft/vscode-cpptools/issues/2843)
|
||||
* Fix IntelliSense-based `Go to Definition` for `const` methods. [#3014](https://github.com/Microsoft/vscode-cpptools/issues/3014)
|
||||
* Support `C_Cpp.updateChannel` for VS Code Exploration builds.
|
||||
|
||||
## Version 0.20.1: October 31, 2018
|
||||
* Fix IntelliSense-based `Go to Declaration` when there's only a definition in a TU. [#2743](https://github.com/Microsoft/vscode-cpptools/issues/2743)
|
||||
* Fix `#include` completion for standalone header files. [#2744](https://github.com/Microsoft/vscode-cpptools/issues/2744)
|
||||
* Fix the highest hitting main process crash.
|
||||
* Fix IntelliSense process crash with completion.
|
||||
|
||||
## Version 0.20.0: October 30, 2018
|
||||
* Add IntegratedTerminal support for Linux and Windows. [#35](https://github.com/microsoft/vscode-cpptools/issues/35)
|
||||
* Unify Visual Studio Code debug protocol parsing by using a shared library with Visual Studio.
|
||||
* Fix IntelliSense-based `Go to Definition` on overloads (in the same TU). [#1071](https://github.com/Microsoft/vscode-cpptools/issues/1071)
|
||||
* Fix inactive regions not being disabled when falling back to the Tag Parser. [#2181](https://github.com/Microsoft/vscode-cpptools/issues/2181)
|
||||
* Fix `#include` completion not working with `compile_commands.json` or custom configuration providers. [#2242](https://github.com/Microsoft/vscode-cpptools/issues/2242)
|
||||
* Fix IntelliSense failing if recursive includes removes all paths. [#2442](https://github.com/Microsoft/vscode-cpptools/issues/2442)
|
||||
* Fix incorrect IntelliSense errors with MinGW (stop using `-fms-extensions` by default). [#2443](https://github.com/Microsoft/vscode-cpptools/issues/2443), [#2623](https://github.com/Microsoft/vscode-cpptools/issues/2623)
|
||||
* Fix error squiggles sometimes not updating after typing. [#2448](https://github.com/Microsoft/vscode-cpptools/issues/2448)
|
||||
* Add support for Mac framework paths in `compile_commands.json`. [#2508](https://github.com/Microsoft/vscode-cpptools/issues/2508)
|
||||
* Fix IntelliSense-based `Go to Definition` falling back to the Tag Parser for definitions not in the TU. [#2536](https://github.com/Microsoft/vscode-cpptools/issues/2536), [#2677](https://github.com/Microsoft/vscode-cpptools/issues/2677)
|
||||
* Fix IntelliSense-based `Go to Definition` on the identifier of a definition with no declaration. [#2573](https://github.com/Microsoft/vscode-cpptools/issues/2573)
|
||||
* Fix IntelliSense-based `Go to Definition` not falling back to the declaration (in certain cases). [#2574](https://github.com/Microsoft/vscode-cpptools/issues/2574)
|
||||
* Fix IntelliSense-based `Go to Definition` going to the wrong location after edits are made. [#2579](https://github.com/Microsoft/vscode-cpptools/issues/2579)
|
||||
* Fix `Go to Definition` when the `intelliSenseEngineFallback` is `Disabled` and `#include`s are missing. [#2583](https://github.com/Microsoft/vscode-cpptools/issues/2583)
|
||||
* Fix empty `C_Cpp.default.*` settings not being used. [#2584](https://github.com/Microsoft/vscode-cpptools/issues/2584)
|
||||
* Fix quoting around `ssh`'s command (for the debugger). [#2585](https://github.com/Microsoft/vscode-cpptools/issues/2585)
|
||||
* Fix crash on hover (and `Go to Definition`) when using the `Tag Parser`. [#2586](https://github.com/Microsoft/vscode-cpptools/issues/2586)
|
||||
* Fix errors when a workspace folder isn't open. [#2613](https://github.com/Microsoft/vscode-cpptools/issues/2613), [#2691](https://github.com/Microsoft/vscode-cpptools/issues/2691)
|
||||
* Fix `-isystem` without a space after getting ignored in `compile_comamands.json`. [#2629](https://github.com/Microsoft/vscode-cpptools/issues/2629)
|
||||
* Fix Insiders update channel installation bugs. [#2636](https://github.com/Microsoft/vscode-cpptools/issues/2636), [#2685](https://github.com/Microsoft/vscode-cpptools/issues/2685)
|
||||
* Fix IntelliSense-based `Go to Declaration` falling back to the Tag Parser if the definition is also in the TU. [#2642](https://github.com/Microsoft/vscode-cpptools/issues/2642)
|
||||
* Fix the `Disabled` `intelliSenseEngine` setting not working with custom configuration providers. [#2656](https://github.com/Microsoft/vscode-cpptools/issues/2656)
|
||||
|
||||
## Version 0.19.0: September 27, 2018
|
||||
* Change the symbol database to update without needing to save. [#202](https://github.com/Microsoft/vscode-cpptools/issues/202)
|
||||
* Enable IntelliSense-based `Go to Definition` for the current translation unit, including local variables and overloaded operators. [#255](https://github.com/Microsoft/vscode-cpptools/issues/255), [#979](https://github.com/Microsoft/vscode-cpptools/issues/979)
|
||||
* Improved the `Go to Definition` performance with large workspaces and files with lots of `#include`s. [#273](https://github.com/Microsoft/vscode-cpptools/issues/273)
|
||||
* Disable `Go to Definition` for invalid tokens, e.g. comments, strings, keywords, etc. [#559](https://github.com/Microsoft/vscode-cpptools/issues/559)
|
||||
* Add `C_Cpp.updateChannel` setting for easier access to Insider builds of the extension. [#1526](https://github.com/Microsoft/vscode-cpptools/issues/1526)
|
||||
* Add support for v2 of the configuration provider API. [#2237](https://github.com/Microsoft/vscode-cpptools/issues/2237)
|
||||
* Fix bug with parsing definitions in `compile_commands.json`. [#2305](https://github.com/Microsoft/vscode-cpptools/issues/2305)
|
||||
* Fix `sh` failure when attaching to a remote Linux process. [#2444](https://github.com/Microsoft/vscode-cpptools/issues/2444)
|
||||
* Fix incorrect default `cl.exe` macro. [PR #2468](https://github.com/Microsoft/vscode-cpptools/issues/2468)
|
||||
* Fix multiple bugs with the symbols in the Outline view not updating correctly. [#2477](https://github.com/Microsoft/vscode-cpptools/issues/2477), [#2500](https://github.com/Microsoft/vscode-cpptools/issues/2500), [#2504](https://github.com/Microsoft/vscode-cpptools/issues/2504)
|
||||
* Add support for `workspaceFolderBasename` expansion. [#2491](https://github.com/Microsoft/vscode-cpptools/issues/2491)
|
||||
* Gabriel Arjones (@g-arjones) [PR #2495](https://github.com/Microsoft/vscode-cpptools/pull/2495), [PR #2503](https://github.com/Microsoft/vscode-cpptools/pull/2503)
|
||||
* Fix bug with variable resolution. [#2532](https://github.com/Microsoft/vscode-cpptools/issues/2532)
|
||||
* Fix off-by-one bug with hover and `Go to Definition`. [#2535](https://github.com/Microsoft/vscode-cpptools/issues/2535)
|
||||
* Fix [Microsoft/vscode#54213](https://github.com/Microsoft/vscode/issues/54213)
|
||||
|
||||
## Version 0.18.1: August 17, 2018
|
||||
* Fix 0.18.0 regression causing non-MinGW compilers to use `-fms-extensions` on Windows. [#2424](https://github.com/Microsoft/vscode-cpptools/issues/2424), [#2425](https://github.com/Microsoft/vscode-cpptools/issues/2425)
|
||||
|
||||
## Version 0.18.0: August 17, 2018
|
||||
### New Features
|
||||
* Add the `C_Cpp.intelliSenseEngine` setting value of `Disabled` (for users who only use the debugger). [#785](https://github.com/Microsoft/vscode-cpptools/issues/785)
|
||||
* Add `C_Cpp.workspaceSymbols` setting with default `Just My Code` to filter out system header symbols. [#1119](https://github.com/Microsoft/vscode-cpptools/issues/1119), [#2320](https://github.com/Microsoft/vscode-cpptools/issues/2320)
|
||||
* Add `C_Cpp.inactiveRegionForegroundColor` and `C_Cpp.inactiveRegionBackgroundColor` settings. [#1620](https://github.com/Microsoft/vscode-cpptools/issues/1620), [#2212](https://github.com/Microsoft/vscode-cpptools/issues/2212)
|
||||
* John Patterson (@john-patterson) [PR #2308](https://github.com/Microsoft/vscode-cpptools/pull/2308)
|
||||
* Add `gcc-x64` `intelliSenseMode` and send the correct clang or gcc version to our parser, fixing various IntelliSense errors. [#2112](https://github.com/Microsoft/vscode-cpptools/issues/2112), [#2175](https://github.com/Microsoft/vscode-cpptools/issues/2175), [#2260](https://github.com/Microsoft/vscode-cpptools/issues/2260), [#2299](https://github.com/Microsoft/vscode-cpptools/issues/2299), [#2317](https://github.com/Microsoft/vscode-cpptools/issues/2317)
|
||||
* Make `Go to Definition` on the definition go to the declaration instead. [#2298](https://github.com/Microsoft/vscode-cpptools/issues/2298)
|
||||
* Add multi-pass environment variable resolution allowing variables defined in terms of other variables. [#2057](https://github.com/Microsoft/vscode-cpptools/issues/2057)
|
||||
* John Patterson (@john-patterson) [PR #2322](https://github.com/Microsoft/vscode-cpptools/pull/2322)
|
||||
* Allow users to use `~` for `${userProfile}` on Windows. [PR #2333](https://github.com/Microsoft/vscode-cpptools/pull/2333)
|
||||
* Add support for compiler flags `-fms-extensions` and `-fno-ms-extensions` on Windows (the default for MinGW-based compilers). [#2363](https://github.com/Microsoft/vscode-cpptools/issues/2363)
|
||||
* Make completion "show more results" (i.e. inaccessible members) when invoked a 2nd time. [#2386](https://github.com/Microsoft/vscode-cpptools/issues/2386)
|
||||
|
||||
### Bug Fixes
|
||||
* Fix attach to process for systems without `bash` by using `sh` instead. [#569](https://github.com/Microsoft/vscode-cpptools/issues/569)
|
||||
* Andy Neff (@andyneff) [PR #2340](https://github.com/Microsoft/vscode-cpptools/pull/2340)
|
||||
* Fix IntelliSense crash after hover or completion with `_Complex` types. [#689](https://github.com/Microsoft/vscode-cpptools/issues/689), [#1112](https://github.com/Microsoft/vscode-cpptools/issues/1112)
|
||||
* Fix `files.exclude` not working to exclude non-workspace folders from symbol parsing. [#1066](https://github.com/Microsoft/vscode-cpptools/issues/1066)
|
||||
* Fix `Switch Header/Source` to give results that match the parent folder name before using just the file name. [#1085](https://github.com/Microsoft/vscode-cpptools/issues/1085)
|
||||
* Fix incorrect IntelliSense errors caused by namespace lookup failure when instantiation template arguments in clang mode. [#1395](https://github.com/Microsoft/vscode-cpptools/issues/1395), [#1559](https://github.com/Microsoft/vscode-cpptools/issues/1559), [#1753](https://github.com/Microsoft/vscode-cpptools/issues/1753), [#2272](https://github.com/Microsoft/vscode-cpptools/issues/2272)
|
||||
* Fix missing parameter help when using { for constructors. [#1667](https://github.com/Microsoft/vscode-cpptools/issues/1667)
|
||||
* Fix Mac framework dependencies not being discovered. [#1913](https://github.com/Microsoft/vscode-cpptools/issues/1913)
|
||||
* Fix `compilerPath` not working with `${workspaceFolder}`. [#1982](https://github.com/Microsoft/vscode-cpptools/issues/1982)
|
||||
* Fix red flame getting stuck after modifying `c_cpp_properties.json`. [#2077](https://github.com/Microsoft/vscode-cpptools/issues/2077)
|
||||
* Don't add empty `windowsSDKVersion` if none exists. [#2300](https://github.com/Microsoft/vscode-cpptools/issues/2300)
|
||||
* Fix IntelliSense crash when the gcc-8 type_traits header is used. [#2323](https://github.com/Microsoft/vscode-cpptools/issues/2323), [#2328](https://github.com/Microsoft/vscode-cpptools/issues/2328)
|
||||
* Limit configuration popups to one at a time. [#2324](https://github.com/Microsoft/vscode-cpptools/issues/2324)
|
||||
* Don't show `includePath` code actions if compile commands or custom configuration providers are used. [#2334](https://github.com/Microsoft/vscode-cpptools/issues/2334)
|
||||
* Fix `C_Cpp.clang_format_path` not accepting environment variables. [#2344](https://github.com/Microsoft/vscode-cpptools/issues/2344)
|
||||
* Fix IntelliSense not working with non-ASCII characters in the WSL install path. [#2351](https://github.com/Microsoft/vscode-cpptools/issues/2351)
|
||||
* Filter out buggy IntelliSense error `"= delete" can only appear on the first declaration of a function`. [#2352](https://github.com/Microsoft/vscode-cpptools/issues/2352)
|
||||
* Fix IntelliSense failing with WSL if gcc is installed bug g++ isn't. [#2360](https://github.com/Microsoft/vscode-cpptools/issues/2360)
|
||||
* Fix WSL paths starting with `/mnt/` failing to get symbols parsed. [#2361](https://github.com/Microsoft/vscode-cpptools/issues/2361)
|
||||
* Fix IntelliSense process crash when hovering over a designated initializer list with an anonymous struct. [#2370](https://github.com/Microsoft/vscode-cpptools/issues/2370)
|
||||
* Stop showing "File: " in completion details for internal compiler defines. [#2387](https://github.com/Microsoft/vscode-cpptools/issues/2387)
|
||||
* Invoke `Edit Configurations...` when the `Configuration Help` button is clicked. [#2408](https://github.com/Microsoft/vscode-cpptools/issues/2408)
|
||||
* Fix provider configuration prompt not showing for newly added workspace folders. [#2415](https://github.com/Microsoft/vscode-cpptools/issues/2415)
|
||||
* Fix to allow SIGINT to be sent using the kill -2 command when using pipeTransport.
|
||||
|
||||
## Version 0.17.7: July 22, 2018
|
||||
* Fix `Go to Definition` for code scoped with an aliased namespace. [#387](https://github.com/Microsoft/vscode-cpptools/issues/387)
|
||||
* Fix incorrect IntelliSense errors with template template-arguments. [#1014](https://github.com/Microsoft/vscode-cpptools/issues/1014)
|
||||
* Fix crash when using designated initializer lists. [#1440](https://github.com/Microsoft/vscode-cpptools/issues/1440)
|
||||
* Add `windowsSdkVersion` to `c_cpp_properties.json`. [#1585](https://github.com/Microsoft/vscode-cpptools/issues/1585)
|
||||
* Add `${vcpkgRoot}` variable. [#1817](https://github.com/Microsoft/vscode-cpptools/issues/1817)
|
||||
* Fix dangling IntelliSense processes. [#2075](https://github.com/Microsoft/vscode-cpptools/issues/2075), [#2169](https://github.com/Microsoft/vscode-cpptools/issues/2169)
|
||||
* Fix incorrect IntelliSense errors when class template argument deduction is used. [#2101](https://github.com/Microsoft/vscode-cpptools/issues/2101)
|
||||
* Skip automatic parsing of source files in Mac system framework paths. [#2156](https://github.com/Microsoft/vscode-cpptools/issues/2156)
|
||||
* Fix `Edit Configurations...` not working after `c_cpp_properties.json` is deleted. [#2214](https://github.com/Microsoft/vscode-cpptools/issues/2214)
|
||||
* Fix indexing of the entire root drive on Windows when no is folder open. [#2216](https://github.com/Microsoft/vscode-cpptools/issues/2216)
|
||||
* Disable the config provider message for headers outside the workspace and when debugging. [#2221](https://github.com/Microsoft/vscode-cpptools/issues/2221)
|
||||
* Add `Change Configuration Provider...` command. [#2224](https://github.com/Microsoft/vscode-cpptools/issues/2224)
|
||||
* Fix out-of-memory crash with `#include` code actions when no folder is open. [#2225](https://github.com/Microsoft/vscode-cpptools/issues/2225)
|
||||
* Fix `intelliSenseMode` with custom config providers on Windows. [#2228](https://github.com/Microsoft/vscode-cpptools/issues/2228)
|
||||
* Fix formatting not working on Windows if the VC++ 2015 redist isn't installed. [#2232](https://github.com/Microsoft/vscode-cpptools/issues/2232)
|
||||
* Fix variables not resolving in `macFrameworkPath`. [#2234](https://github.com/Microsoft/vscode-cpptools/issues/2234)
|
||||
* Fix `Go to Definition` not working for macros followed by `.` or `->`. [#2245](https://github.com/Microsoft/vscode-cpptools/issues/2245)
|
||||
* Fix `#include` autocomplete with Mac framework headers. [#2251](https://github.com/Microsoft/vscode-cpptools/issues/2251)
|
||||
* Fix debugging to support empty arguments for debuggee. [#2258](https://github.com/Microsoft/vscode-cpptools/issues/2258)
|
||||
* Fix `Go to Definition` bug (missing symbols outside the workspace). [#2281](https://github.com/Microsoft/vscode-cpptools/issues/2281)
|
||||
* Fix incorrect hover in enum definitions. [#2286](https://github.com/Microsoft/vscode-cpptools/issues/2286)
|
||||
* Add a setting to silence configuration provider warnings. [#2292](https://github.com/Microsoft/vscode-cpptools/issues/2292)
|
||||
* Fix debugging async Visual C++ causing debugger to hang.
|
||||
* Fix `main` snippet.
|
||||
|
||||
## Version 0.17.6: July 2, 2018
|
||||
* Fix the database icon getting stuck with recursive includes. [#2104](https://github.com/Microsoft/vscode-cpptools/issues/2104)
|
||||
* Fix the red flame appearing late with recursive includes. [#2105](https://github.com/Microsoft/vscode-cpptools/issues/2105)
|
||||
* Fix source files being parsed in system directories. [#2156](https://github.com/Microsoft/vscode-cpptools/issues/2156)
|
||||
* Fix internal document corruption (visible after formatting) when edits are made too soon after activation. [#2162](https://github.com/Microsoft/vscode-cpptools/issues/2162)
|
||||
* Fix a crash when saving with recursive includes. [#2173](https://github.com/Microsoft/vscode-cpptools/issues/2173)
|
||||
* Fix a crash when the `includePath` or `browse.path` is `"**"`. [#2174](https://github.com/Microsoft/vscode-cpptools/issues/2174)
|
||||
* Fix IntelliSense for WSL without g++ installed. [#2178](https://github.com/Microsoft/vscode-cpptools/issues/2178)
|
||||
* Fix random IntelliSense (completion) failures due to edits being delayed. [#2184](https://github.com/Microsoft/vscode-cpptools/issues/2184)
|
||||
* Fix database deletion failure with non-ASCII file paths on Windows. [#2205](https://github.com/Microsoft/vscode-cpptools/issues/2205)
|
||||
* Fix `Go to Definition` results with `var::` and `var->`, and filter out invalid constructor results. [#2207](https://github.com/Microsoft/vscode-cpptools/issues/2207)
|
||||
* Fix a performance bug with recursive includes.
|
||||
* Fixed a CPU usage problem on Mac related to system frameworks parsing.
|
||||
* Keep the IntelliSense process around for 10 seconds after a file is closed in case it's needed again.
|
||||
* Added an API so build system extensions can provide IntelliSense configurations for source files. More details at [npmjs.com](https://www.npmjs.com/package/vscode-cpptools).
|
||||
* Fix automatic argument quoting when debugging with gdb/lldb to include when the argument has a '(' or ')' in it. Also escape existing '"' symbols.
|
||||
* Removed `-` in `ps` call for ProcessPicker and RemoteProcessPicker. [#2183](https://github.com/Microsoft/vscode-cpptools/issues/2183)
|
||||
|
||||
## Version 0.17.5: June 21, 2018
|
||||
* Detect `compile_commands.json` and show prompt to use it. [#1297](https://github.com/Microsoft/vscode-cpptools/issues/1297)
|
||||
* Change inactive regions from gray to translucent. [#1907](https://github.com/Microsoft/vscode-cpptools/issues/1907)
|
||||
* Improve performance of recursive includes paths. [#2068](https://github.com/Microsoft/vscode-cpptools/issues/2068)
|
||||
* Fix IntelliSense client failure due to `No args provider`. [#1908](https://github.com/Microsoft/vscode-cpptools/issues/1908)
|
||||
* Fix `#include` completion with headers in the same directory. [#2031](https://github.com/Microsoft/vscode-cpptools/issues/2031)
|
||||
* Fix non-header files outside the workspace folder not being parsed (i.e. so `Go to Definition` works). [#2053](https://github.com/Microsoft/vscode-cpptools/issues/2053)
|
||||
* Fix some crashes. [#2080](https://github.com/Microsoft/vscode-cpptools/issues/2080)
|
||||
* Support asm clobber registers on Windows. [#2090](https://github.com/Microsoft/vscode-cpptools/issues/2090)
|
||||
* Fix usage of `${config:section.setting}`. [#2165](https://github.com/Microsoft/vscode-cpptools/issues/2165)
|
||||
* `browse.path` now inherits `includePath` if not set in `c_cpp_properties.json`.
|
||||
* On Windows, `compilerPath` now populates with the guessed `cl.exe` path, and the `MSVC` include path is based on the `cl.exe` path.
|
||||
* Fix files under a non-recursive `browse.path` being removed from the database.
|
||||
* Fix `*` not working in `browse.path` with WSL.
|
||||
* Fix -break-insert main returning multiple bind points. [PR Microsoft/MIEngine#729](https://github.com/Microsoft/MIEngine/pull/729)
|
||||
* Use -- instead of -x for gnome-terminal. [PR Microsoft/MIEngine#733](https://github.com/Microsoft/MIEngine/pull/733)
|
||||
* Added `miDebuggerArgs` in order to pass arguments to the program in `miDebuggerPath`. [PR Microsoft/MIEngine#720](https://github.com/Microsoft/MIEngine/pull/720)
|
||||
|
||||
## Version 0.17.4: May 31, 2018
|
||||
* Fix infinite loop (caused by deadlock) when using recursive includes. [#2043](https://github.com/Microsoft/vscode-cpptools/issues/2043)
|
||||
* Stop using recursive includes in the default configuration.
|
||||
* @Hyzeta [PR #2059](https://github.com/Microsoft/vscode-cpptools/pull/2059)
|
||||
* Fix various other potential deadlocks and crashes.
|
||||
* Fix `Go to Definition` on `#include` not filtering out results based on the path. [#1253](https://github.com/Microsoft/vscode-cpptools/issues/1253), [#2033](https://github.com/Microsoft/vscode-cpptools/issues/2033)
|
||||
* Fix database icon getting stuck. [#1917](https://github.com/Microsoft/vscode-cpptools/issues/1917)
|
||||
|
||||
## Version 0.17.3: May 22, 2018
|
||||
* Add support for `${workspaceFolder:folderName}`. [#1774](https://github.com/Microsoft/vscode-cpptools/issues/1774)
|
||||
* Fix infinite loop during initialization on Windows. [#1960](https://github.com/Microsoft/vscode-cpptools/issues/1960)
|
||||
@@ -95,9 +407,9 @@
|
||||
* Add `C_Cpp.exclusionPolicy` default to `checkFolders` to avoid expensive `files.exclude` checking on every file.
|
||||
|
||||
## Version 0.14.5: December 18, 2017
|
||||
* Fix for stackwalk `NullReferenceException`. [#1339](https://github.com/Microsoft/vscode-cpptools/issues/1339)
|
||||
* Fix for `-isystem` (or `-I`) not being used in `compile_commands.json` if there's a space after it. [#1343](https://github.com/Microsoft/vscode-cpptools/issues/1343)
|
||||
* Fix for header switching from `.cc` to `.hpp` files (and other cases). [#1341](https://github.com/Microsoft/vscode-cpptools/issues/1341)
|
||||
* Fix stackwalk `NullReferenceException`. [#1339](https://github.com/Microsoft/vscode-cpptools/issues/1339)
|
||||
* Fix `-isystem` (or `-I`) not being used in `compile_commands.json` if there's a space after it. [#1343](https://github.com/Microsoft/vscode-cpptools/issues/1343)
|
||||
* Fix header switching from `.cc` to `.hpp` files (and other cases). [#1341](https://github.com/Microsoft/vscode-cpptools/issues/1341)
|
||||
* Fix reload prompts not appearing in debugging scenarios (after the initial installation). [#1344](https://github.com/Microsoft/vscode-cpptools/issues/1344)
|
||||
* Add a "wait" message when commands are invoked during download/installation. [#1344](https://github.com/Microsoft/vscode-cpptools/issues/1344)
|
||||
* Prevent blank "C/C++ Configuration" from appearing when debugging is started but the language service is not. [#1353](https://github.com/Microsoft/vscode-cpptools/issues/1353)
|
||||
@@ -116,9 +428,9 @@
|
||||
* Improve performance for fetching call stacks with large arguments. [#363](https://github.com/Microsoft/vscode-cpptools/issues/363)
|
||||
|
||||
## Version 0.14.3: November 27, 2017
|
||||
* Fix for disappearing parameter hints tooltip. [#1165](https://github.com/Microsoft/vscode-cpptools/issues/1165)
|
||||
* Fix for parameter hints only showing up after the opening parenthesis. [#902](https://github.com/Microsoft/vscode-cpptools/issues/902), [#819](https://github.com/Microsoft/vscode-cpptools/issues/819)
|
||||
* Fix for customer reported crashes in the TypeScript extension code. [#1240](https://github.com/Microsoft/vscode-cpptools/issues/1240), [#1245](https://github.com/Microsoft/vscode-cpptools/issues/1245)
|
||||
* Fix disappearing parameter hints tooltip. [#1165](https://github.com/Microsoft/vscode-cpptools/issues/1165)
|
||||
* Fix parameter hints only showing up after the opening parenthesis. [#902](https://github.com/Microsoft/vscode-cpptools/issues/902), [#819](https://github.com/Microsoft/vscode-cpptools/issues/819)
|
||||
* Fix customer reported crashes in the TypeScript extension code. [#1240](https://github.com/Microsoft/vscode-cpptools/issues/1240), [#1245](https://github.com/Microsoft/vscode-cpptools/issues/1245)
|
||||
* Fix .browse.VC-#.db files being unnecessarily created when an shm file exists. [#1234](https://github.com/Microsoft/vscode-cpptools/issues/1234)
|
||||
* Fix language service to only activate after a C/C++ file is opened or a C/Cpp command is used (not onDebug).
|
||||
* Fix database resetting if shutdown got blocked by an IntelliSense operation. [#1260](https://github.com/Microsoft/vscode-cpptools/issues/1260)
|
||||
@@ -172,10 +484,10 @@
|
||||
## Version 0.13.0: September 25, 2017
|
||||
* Reference highlighting is now provided by the extension for both IntelliSense engines.
|
||||
* Parameter help is now provided by both IntelliSense engines.
|
||||
* Light bulbs (code actions) for #include errors now suggest potential paths to add to the `includePath` based on a recursive search of the `browse.path`. [#846](https://github.com/Microsoft/vscode-cpptools/issues/846)
|
||||
* Light bulbs (code actions) for `#include` errors now suggest potential paths to add to the `includePath` based on a recursive search of the `browse.path`. [#846](https://github.com/Microsoft/vscode-cpptools/issues/846)
|
||||
* Browse database now removes old symbols when `browse.path` changes. [#262](https://github.com/Microsoft/vscode-cpptools/issues/262)
|
||||
* Add `*` on new lines after a multiline comment with `/**` is started. [#579](https://github.com/Microsoft/vscode-cpptools/issues/579)
|
||||
* Fix Go to Definition, completion, and parameter hints for partially scoped members. [#635](https://github.com/Microsoft/vscode-cpptools/issues/635)
|
||||
* Fix `Go to Definition`, completion, and parameter hints for partially scoped members. [#635](https://github.com/Microsoft/vscode-cpptools/issues/635)
|
||||
* Fix bug in `macFrameworkPath` not resolving variables.
|
||||
|
||||
## Version 0.12.4: September 12, 2017
|
||||
@@ -186,7 +498,7 @@
|
||||
* Support `${env:VAR}` syntax for environment variables in `c_cpp_properties.json`. [#1000](https://github.com/Microsoft/vscode-cpptools/issues/1000)
|
||||
* Support semicolon delimiters for include paths in `c_cpp_properties.json` to better support environment variables. [#1001](https://github.com/Microsoft/vscode-cpptools/issues/1001)
|
||||
* Add `__LITTLE_ENDIAN__=1` to default defines so that "endian.h" is not needed on Mac projects. [#1005](https://github.com/Microsoft/vscode-cpptools/issues/1005)
|
||||
* Fix for source code files on Windows with incorrect casing. [#984](https://github.com/Microsoft/vscode-cpptools/issues/984)
|
||||
* Fix source code files on Windows with incorrect casing. [#984](https://github.com/Microsoft/vscode-cpptools/issues/984)
|
||||
|
||||
## Version 0.12.3: August 17, 2017
|
||||
* Fix regression for paths containing multibyte characters. [#958](https://github.com/Microsoft/vscode-cpptools/issues/958)
|
||||
@@ -222,7 +534,7 @@
|
||||
* Update Microsoft Visual C++ debugger to Visual Studio 2017 released components.
|
||||
* Fix issue with showing wrong thread. [#550](https://github.com/Microsoft/vscode-cpptools/issues/550)
|
||||
* Fix issue with binaries compiled with /FASTLINK causing debugger to hang. [#484](https://github.com/Microsoft/vscode-cpptools/issues/484)
|
||||
* Fix issue in MinGW/Cygwin debugging where stop debugging causes VS Code to hang. [Microsoft/MIEngine#636](https://github.com/Microsoft/MIEngine/pull/636)
|
||||
* Fix issue in MinGW/Cygwin debugging where stop debugging causes VS Code to hang. [PR Microsoft/MIEngine#636](https://github.com/Microsoft/MIEngine/pull/636)
|
||||
|
||||
## Version 0.12.0: June 26, 2017
|
||||
* The default IntelliSense engine now provides semantic-aware autocomplete suggestions for `.`, `->`, and `::` operators. [#13](https://github.com/Microsoft/vscode-cpptools/issues/13)
|
||||
@@ -239,8 +551,8 @@
|
||||
* Fix `Go to Definition` not working until all `browse.path` files are re-scanned. [#788](https://github.com/Microsoft/vscode-cpptools/issues/788)
|
||||
|
||||
## Version 0.11.4: June 2, 2017
|
||||
* Fix for `System.Xml.Serialization.XmlSerializationReader threw an exception` when debugging on Linux. [#792](https://github.com/Microsoft/vscode-cpptools/issues/792)
|
||||
* Fix for escaping for `${workspaceRoot}` in `launch.json`.
|
||||
* Fix `System.Xml.Serialization.XmlSerializationReader threw an exception` when debugging on Linux. [#792](https://github.com/Microsoft/vscode-cpptools/issues/792)
|
||||
* Fix escaping for `${workspaceRoot}` in `launch.json`.
|
||||
|
||||
## Version 0.11.3: May 31, 2017
|
||||
* Fix `x86_64-pc-linux-gnu` and `x86_64-linux-gnu` paths missing from the default `includePath`.
|
||||
@@ -288,7 +600,7 @@
|
||||
|
||||
## Version 0.10.5: March 21, 2017
|
||||
* Fix a crash that randomly occurred when the size of a document increased. [#430](https://github.com/Microsoft/vscode-cpptools/issues/430)
|
||||
* Fix for browsing not working for Linux/Mac stdlib.h functions. [#578](https://github.com/Microsoft/vscode-cpptools/issues/578)
|
||||
* Fix browsing not working for Linux/Mac stdlib.h functions. [#578](https://github.com/Microsoft/vscode-cpptools/issues/578)
|
||||
* Additional fixes for switch header/source not respecting `files.exclude`. [#485](https://github.com/Microsoft/vscode-cpptools/issues/485)
|
||||
* Made `editor.quickSuggestions` dependent on `C_Cpp.autocomplete`. [#572](https://github.com/Microsoft/vscode-cpptools/issues/572)
|
||||
* We recommend you close and reopen your settings.json file anytime you change the `C_Cpp.autocomplete` setting. [More info here](https://github.com/Microsoft/vscode-cpptools/releases).
|
||||
@@ -368,7 +680,7 @@
|
||||
* Switch between header and source.
|
||||
* Control which files are processed under include path.
|
||||
|
||||
## Version 0.6.1: June 03, 2016
|
||||
## Version 0.6.1: June 3, 2016
|
||||
* Bug fixes.
|
||||
|
||||
## Version 0.6.0: May 24, 2016
|
||||
|
||||
+10
-3
@@ -2,7 +2,7 @@
|
||||
This preview release of the extension adds language support for C/C++ to Visual Studio Code including:
|
||||
* Language service
|
||||
* Code Formatting (clang-format)
|
||||
* Auto-Completion (experimental)
|
||||
* Auto-Completion
|
||||
* Symbol Searching
|
||||
* Go to Definition/Declaration
|
||||
* Peek Definition/Declaration
|
||||
@@ -11,7 +11,7 @@ This preview release of the extension adds language support for C/C++ to Visual
|
||||
* Quick Info (Hover)
|
||||
* Error Squiggles
|
||||
* Debugging
|
||||
* Support for debugging Windows (PDB, Mingw/Cygwin), Linux and OS X applications
|
||||
* Support for debugging Windows (PDB, MinGW/Cygwin), Linux and macOS applications
|
||||
* Line by line code stepping
|
||||
* Breakpoints (including conditional and function breakpoints)
|
||||
* Variable inspection
|
||||
@@ -23,5 +23,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,12 +205,22 @@
|
||||
<tr>
|
||||
<td>
|
||||
<div>
|
||||
<h2 class="caption">April 2018 Update</h2>
|
||||
<div>Thank you for installing the C/C++ extension. In the April update, we added autocomplete suggestions for <code>#include</code> statements.<br/>
|
||||
<h2 class="caption">May 2019 Update</h2>
|
||||
<div>Thank you for installing the C/C++ extension! We're excited to announce the following features in the May update:<br/>
|
||||
<h3 style="font-weight: 600">IntelliSense configuration settings editor UI</h3>
|
||||
The extension now has a UI editor to edit basic IntelliSense configuration settings defined in the underlying <code>c_cpp_properties.json</code> file.<br/>
|
||||
<br/>
|
||||
You can get to the IntelliSense configuration settings editor UI through the command palette (Ctrl+Shift+P) and running the <code>C/C++: Edit configurations (UI)</code> command.
|
||||
The <code>c_cpp_properties.json</code> file can be opened by running the <code>C/C++: Edit configurations (JSON)</code> command.
|
||||
<br/>
|
||||
<br/>
|
||||
<em style="font-weight: 600">Please Note:</em> When configuring IntelliSense for the first time, VS Code will open the UI editor or JSON file based on your <code>workbench.settings.editor</code> setting.
|
||||
If <code>workbench.settings.editor</code> is set to “ui”, then the UI editor will open by default, and if it is set to “json”, then the JSON file will open by default. You can view that setting under VS Code preferences → settings → “Workbench Settings Editor”.<br/>
|
||||
|
||||
<h3 style="font-weight: 600">Log diagnostics command</h3>
|
||||
We added the command <code>C/C++: Log Diagnostics</code> to help diagnose IntelliSense issues. Running the command shows IntelliSense information of the current translation unit that is associated with the active file.<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
We also added settings for configuration defaults and made some changes to improve the automatic configuration experience. If you set the <code>"compilerPath"</code>
|
||||
property in c_cpp_properties.json, you no longer need to add system includes and defines to <code>"includePath"</code> or <code>"defines"</code><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>
|
||||
</td>
|
||||
@@ -234,10 +244,9 @@
|
||||
<td>
|
||||
<div>
|
||||
<h3 class="caption">Blog Posts</h3>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/03/29/visual-studio-code-cc-extension-march-2018-update/">March 2018 Update</a></div>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/02/20/visual-studio-code-cc-extension-feb-2018-update/">February 2018 Update</a></div>
|
||||
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/01/17/visual-studio-code-cc-extension-jan-2018-update/">January 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>
|
||||
|
||||
+3511
-1423
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#F6F6F6"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#424242"/></svg>
|
||||
|
After Width: | Height: | Size: 986 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#2D2D30"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#C5C5C5"/></svg>
|
||||
|
After Width: | Height: | Size: 986 B |
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"defaults": [
|
||||
"--clang",
|
||||
"--pack_alignment",
|
||||
"8"
|
||||
],
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"-D_MSC_FULL_VER=191426428",
|
||||
"-D_MSC_BUILD=0",
|
||||
"-D_M_X64=100",
|
||||
"-D_AMD64=100"
|
||||
"-D_M_AMD64=100"
|
||||
],
|
||||
"defaults_op" : "merge"
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"defaults": [
|
||||
"--clang",
|
||||
"--pack_alignment",
|
||||
"8"
|
||||
],
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"-D_MSC_FULL_VER=191426428",
|
||||
"-D_MSC_BUILD=0",
|
||||
"-D_M_X64=100",
|
||||
"-D_AMD64=100"
|
||||
"-D_M_AMD64=100"
|
||||
],
|
||||
"defaults_op" : "merge"
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"defaults": [
|
||||
"--clang",
|
||||
"--pack_alignment",
|
||||
"8"
|
||||
],
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"-D_MSC_FULL_VER=191426428",
|
||||
"-D_MSC_BUILD=0",
|
||||
"-D_M_X64=100",
|
||||
"-D_AMD64=100"
|
||||
"-D_M_AMD64=100"
|
||||
],
|
||||
"defaults_op" : "merge"
|
||||
}
|
||||
@@ -58,6 +58,11 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"windowsSdkVersion": {
|
||||
"description": "Version of the Windows SDK include path to use on Windows, e.g. '10.0.17134.0'.",
|
||||
"type": "string",
|
||||
"pattern": "^\\d{2}\\.\\d{1}\\.\\d{5}\\.\\d{1}$|^8\\.1$"
|
||||
},
|
||||
"defines": {
|
||||
"description": "A list of preprocessor definitions for the IntelliSense engine to use while parsing files. Optionally, use = to set a value, e.g. VERSION=1.",
|
||||
"type": "array",
|
||||
@@ -66,10 +71,11 @@
|
||||
}
|
||||
},
|
||||
"intelliSenseMode": {
|
||||
"description": "If set, it overrides the default mode used by the IntelliSense engine. Windows defaults to msvc-x64 and Linux/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 default to clang-x64.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"msvc-x64",
|
||||
"gcc-x64",
|
||||
"clang-x64",
|
||||
"${default}"
|
||||
]
|
||||
@@ -81,6 +87,10 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"configurationProvider": {
|
||||
"description": "The id of a VS Code extension that can provide IntelliSense configuration information for source files.",
|
||||
"type": "string"
|
||||
},
|
||||
"browse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -102,16 +112,18 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
"description": "Custom variables that can be reused anywhere in this file using the ${variable} or ${env:variable} syntax.",
|
||||
"patternProperties": {
|
||||
"(?!^workspaceFolder$)(?!^workspaceRoot$)(?!^default$)(^.+$)": {
|
||||
"(?!^workspaceFolder$)(?!^workspaceRoot$)(?!^workspaceFolderBasename$)(?!^default$)(^.+$)": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
@@ -130,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": {
|
||||
@@ -141,10 +158,14 @@
|
||||
},
|
||||
"version": {
|
||||
"$ref": "#/definitions/version"
|
||||
},
|
||||
"enableConfigurationSquiggles": {
|
||||
"$ref": "#/definitions/enableConfigurationSquiggles"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"configurations",
|
||||
"version"
|
||||
]
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
+2
-2574
File diff suppressed because it is too large
Load Diff
@@ -1,140 +0,0 @@
|
||||
{
|
||||
"class": {
|
||||
"prefix": "class",
|
||||
"body": "\nclass ${1:${TM_FILENAME_BASE}}\n{\nprivate:\n\t${2:/* data */}\npublic:\n\t${1}(${3:/* args */});\n\t~${1}();\n};\n\n${1}::${1}(${3})\n{\n}\n\n${1}::~${1}()\n{\n}\n",
|
||||
"description": "Code snippet for class",
|
||||
"scope": "source.c++, source.objc++"
|
||||
},
|
||||
"classi": {
|
||||
"prefix": "classi",
|
||||
"body": "\nclass ${1:${TM_FILENAME_BASE}}\n{\nprivate:\n\t${2:/* data */}\npublic:\n\t${1}(${3:/* args */}) { $0}\n\t~${1}() { }\n};",
|
||||
"description": "Code snippet for class with inlined constructor/destructor",
|
||||
"scope": "source.c++, source.objc++"
|
||||
},
|
||||
"classt": {
|
||||
"prefix": "classt",
|
||||
"body": "\ntemplate<typename T>\nclass ${1:${TM_FILENAME_BASE}}\n{\nprivate:\n\tT ${2:/* data */}\npublic:\n\t${1}(T ${3:/* args */});\n};\n",
|
||||
"description": "Code snippet for class template",
|
||||
"scope": "source.c++, source.objc++"
|
||||
},
|
||||
"struct": {
|
||||
"prefix": "struct",
|
||||
"body": "\nstruct ${1:${TM_FILENAME_BASE}}\n{\n\t${0:/* data */}\n};\n",
|
||||
"description": "Code snippet for struct",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"union": {
|
||||
"prefix": "union",
|
||||
"body": "\nunion ${1:${TM_FILENAME_BASE}}\n{\n\t${0:/* data */}\n};\n",
|
||||
"description": "Code snippet for union",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"if": {
|
||||
"prefix": "if",
|
||||
"body": "\nif (${1:/* condition */}) {\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for if()",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"ifel": {
|
||||
"prefix": "ifel",
|
||||
"body": "\nif (${1:/* condition */}) {\n\t${2:/* code */}\n}\nelse {\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for if() else",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"ifelif": {
|
||||
"prefix": "ifelif",
|
||||
"body": "\nif (${1:/* condition */}) {\n\t${2:/* code */}\n}\nelse if(${3:/* condition */}) {\n\t${4:/* code */}\n}\nelse {\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for if() else if() else",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"else": {
|
||||
"prefix": "else",
|
||||
"body": "\nelse\n{\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for else",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"elif": {
|
||||
"prefix": "elif",
|
||||
"body": "\nelse if (${1:/* condition */})\n{\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for else if ()",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"switch": {
|
||||
"prefix": "switch",
|
||||
"body": "\nswitch (${1:expression})\n{\n\tcase ${2:/* constant-expression */}:\n\t\t${3:/* code */}\n\t\tbreak;\n\n\tdefault:\n\t\tbreak;\n}",
|
||||
"description": "Code snippet for switch",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"main": {
|
||||
"prefix": "main",
|
||||
"body": "\nint main(int argc, char const *argv[])\n{\n\t${1:/* code */}\n\treturn 0;\n}\n",
|
||||
"description": "Code snippet for main()",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"do": {
|
||||
"prefix": "do_",
|
||||
"body": "\ndo\n{\n\t${0:/* code */}\n} while (${1:/* condition */});\n",
|
||||
"description": "Code snippet for do while loop",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"for": {
|
||||
"prefix": "for",
|
||||
"body": "\nfor(${1:size_t} ${2:i} = 0; $2 < ${3:count}; ${4:$2++})\n{\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for for loop",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"forr": {
|
||||
"prefix": "forr",
|
||||
"body": "\nfor(int ${1:i} = ${2:length} - 1; $1 >= 0; ${3:$1--})\n{\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for reverse for loop",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"foreach": {
|
||||
"prefix": "foreach",
|
||||
"body": "\nfor(${1:object} = ${2:var} in ${3:collection})\n{\n\t${0:/* code */}\n}\n",
|
||||
"description": "Code snippet for foreach loop",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"forrange": {
|
||||
"prefix": "forrange",
|
||||
"body": "\nfor(auto&& ${1:i} : ${2:v})\n{\n\t$0\n}\n",
|
||||
"description": "Code snippet for range-based forloop",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"while": {
|
||||
"prefix": "while",
|
||||
"body": "\nwhile(${1:/* condition */}){\n\t${2:/* code */}\n}\n",
|
||||
"description": "Code snippet for while loop",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"ifd": {
|
||||
"prefix": "ifnd",
|
||||
"body": "\n#if defined($1)\n\n${0}\n\n#endif // $1\n",
|
||||
"description": "Code snippet for if defined()",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"ifnd": {
|
||||
"prefix": "ifnd",
|
||||
"body": "\n#if !defined($1)\n#define ${1:MACRO}\n\n${0}\n\n#endif // $1\n",
|
||||
"description": "Code snippet for if !defined()",
|
||||
"scope": "source.c, source.objc, source.c++, source.objc++"
|
||||
},
|
||||
"mitl": {
|
||||
"prefix": "mitl",
|
||||
"body": "\n// The MIT License (MIT)\n\n// Copyright (c) ${1:YEAR} ${2:NAME}\n\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the \"Software\"),\n// to deal in the Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n// and/or sell copies of the Software, and to permit persons to whom the\n// Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n${0:/* code */}\n",
|
||||
"description": "Code snippet for MIT License",
|
||||
"scope": ""
|
||||
},
|
||||
"namesp": {
|
||||
"prefix": "namesp",
|
||||
"body": "\nnamespace ${1:name}\n{\n\t$0\n} // $1\n",
|
||||
"description": "Code snippet for namespace",
|
||||
"scope": "source.c++, source.objc++"
|
||||
},
|
||||
"try": {
|
||||
"prefix": "try",
|
||||
"body": "\ntry\n{\n\t${1:/* code */}\n}\ncatch(${2:const std::exception& e})\n{\n\t${0:std::cerr << e.what() << '\\n';}\n}\n",
|
||||
"description": "Code snippet for try catch block",
|
||||
"scope": "source.c++, source.objc++, source.c++11"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"intelliSenseEngine_default_percentage": 100
|
||||
"intelliSenseEngine_default_percentage": 100,
|
||||
"defaultIntelliSenseEngine": 100,
|
||||
"recursiveIncludes": 100,
|
||||
"gotoDefIntelliSense": 100
|
||||
}
|
||||
+23
-39
@@ -12,47 +12,26 @@ const mocha = require('gulp-mocha');
|
||||
const fs = require('fs');
|
||||
const optionsSchemaGenerator = require('./out/tools/GenerateOptionsSchema');
|
||||
|
||||
gulp.task('allTests', () => {
|
||||
gulp.start('unitTests');
|
||||
gulp.start('integrationTests');
|
||||
});
|
||||
|
||||
gulp.task('unitTests', () => {
|
||||
gulp.src('./out/test/unitTests', {read: false}).pipe(
|
||||
mocha({
|
||||
ui: "tdd"
|
||||
})
|
||||
).once('error', err => {
|
||||
process.exit(1);
|
||||
})
|
||||
.once('end', () => {
|
||||
process.exit();
|
||||
})
|
||||
});
|
||||
|
||||
gulp.task('integrationTests', () => {
|
||||
gulp.task('unitTests', (done) => {
|
||||
env.set({
|
||||
CODE_TESTS_PATH: "./out/test/integrationTests",
|
||||
CODE_TESTS_WORKSPACE: "./test/integrationTests/testAssets/SimpleCppProject"
|
||||
}
|
||||
);
|
||||
gulp.src('./test/runVsCodeTestsWithAbsolutePaths.js', {read: false}).pipe(
|
||||
mocha({
|
||||
ui: "tdd",
|
||||
delay: true
|
||||
CODE_TESTS_PATH: "./out/test/unitTests",
|
||||
});
|
||||
|
||||
return gulp.src('./test/runVsCodeTestsWithAbsolutePaths.js', {read: false})
|
||||
.pipe(mocha({ ui: "tdd" }))
|
||||
.once('error', err => {
|
||||
done();
|
||||
process.exit(1);
|
||||
})
|
||||
).once('error', err => {
|
||||
process.exit(1);
|
||||
})
|
||||
.once('end', () => {
|
||||
process.exit();
|
||||
})
|
||||
.once('end', () => {
|
||||
done();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
|
||||
/// Misc Tasks
|
||||
const allTypeScript = [
|
||||
'src/**/*.ts',
|
||||
'tools/**/*.ts',
|
||||
'!**/*.d.ts',
|
||||
'!**/typings**'
|
||||
];
|
||||
@@ -67,7 +46,7 @@ const lintReporter = (output, file, options) => {
|
||||
};
|
||||
|
||||
gulp.task('tslint', () => {
|
||||
gulp.src(allTypeScript)
|
||||
return gulp.src(allTypeScript)
|
||||
.pipe(tslint({
|
||||
program: require('tslint').Linter.createProgram("./tsconfig.json"),
|
||||
configuration: "./tslint.json"
|
||||
@@ -78,14 +57,19 @@ gulp.task('tslint', () => {
|
||||
}))
|
||||
});
|
||||
|
||||
gulp.task('pr-check', () => {
|
||||
gulp.task('pr-check', (done) => {
|
||||
const packageJson = JSON.parse(fs.readFileSync('./package.json').toString());
|
||||
if (packageJson.activationEvents.length !== 1 && packageJson.activationEvents[0] !== '*') {
|
||||
if (packageJson.activationEvents.length !== 1 && packageJson.activationEvents[0] !== '*') {
|
||||
console.log('Please make sure to not check in package.json that has been rewritten by the extension activation. If you intended to have changes in package.json, please only check-in your changes. If you did not, please run `git checkout -- package.json`.');
|
||||
done();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
gulp.task('generateOptionsSchema', () => {
|
||||
optionsSchemaGenerator.GenerateOptionsSchema();
|
||||
gulp.task('generateOptionsSchema', (done) => {
|
||||
optionsSchemaGenerator.generateOptionsSchema();
|
||||
|
||||
done();
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
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 unitTests'
|
||||
displayName: 'Run unit tests'
|
||||
workingDirectory: '$(Build.SourcesDirectory)\Extension'
|
||||
continueOnError: true
|
||||
|
||||
- script: npm run pretest
|
||||
displayName: "Compile Test Sources"
|
||||
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,58 @@
|
||||
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: 'npm run unitTests'
|
||||
displayName: 'Run unit tests'
|
||||
workingDirectory: '$(Build.SourcesDirectory)/Extension'
|
||||
continueOnError: true
|
||||
|
||||
- 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: '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
|
||||
Generated
+4879
-3003
File diff suppressed because it is too large
Load Diff
+284
-117
@@ -2,7 +2,7 @@
|
||||
"name": "cpptools",
|
||||
"displayName": "C/C++",
|
||||
"description": "C/C++ IntelliSense, debugging, and code browsing.",
|
||||
"version": "0.17.3",
|
||||
"version": "0.23.1",
|
||||
"publisher": "ms-vscode",
|
||||
"preview": true,
|
||||
"icon": "LanguageCCPP_color_128x.png",
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"engines": {
|
||||
"vscode": "^1.22.0"
|
||||
"vscode": "^1.30.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/vscode-cpptools/issues",
|
||||
@@ -41,7 +41,7 @@
|
||||
"activationEvents": [
|
||||
"*"
|
||||
],
|
||||
"main": "./out/src/main",
|
||||
"main": "./dist/main",
|
||||
"contributes": {
|
||||
"problemMatchers": [
|
||||
{
|
||||
@@ -63,7 +63,7 @@
|
||||
],
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "C/C++ Configuration",
|
||||
"title": "C/C++",
|
||||
"properties": {
|
||||
"C_Cpp.clang_format_path": {
|
||||
"type": [
|
||||
@@ -77,13 +77,13 @@
|
||||
"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": {
|
||||
@@ -104,10 +104,11 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Default",
|
||||
"Tag Parser"
|
||||
"Tag Parser",
|
||||
"Disabled"
|
||||
],
|
||||
"default": "Default",
|
||||
"description": "Controls the IntelliSense provider. \"Tag Parser\" provides \"fuzzy\" results that are not context-aware. \"Default\" provides context-aware results and is in preview mode - member list, hover tooltips, and error squiggles are currently implemented. Features not yet implemented in the new default engine will use the tag parser engine instead.",
|
||||
"description": "Controls the IntelliSense provider. \"Tag Parser\" provides \"fuzzy\" results that are not context-aware. \"Default\" provides context-aware results. \"Disabled\" turns off C/C++ language service features.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.intelliSenseEngineFallback": {
|
||||
@@ -116,7 +117,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"
|
||||
},
|
||||
@@ -134,10 +135,11 @@
|
||||
"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": {
|
||||
@@ -146,6 +148,32 @@
|
||||
"description": "Controls whether inactive preprocessor blocks are colored differently than active code. This setting is ignored by the Tag Parser engine.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.inactiveRegionOpacity": {
|
||||
"type:": "number",
|
||||
"default": 0.55,
|
||||
"Description": "Controls the opacity of inactive preprocessor blocks. Scales between 0.1 and 1.0. This setting only applies when inactive region dimming is enabled.",
|
||||
"scope": "resource",
|
||||
"minimum": 0.1,
|
||||
"maximum": 1
|
||||
},
|
||||
"C_Cpp.inactiveRegionForegroundColor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": null,
|
||||
"description": "Controls the font coloring of inactive preprocessor blocks. Input is in the form a hexadecimal color code or a valid Theme Color. If not set, this defaults to the syntax coloring scheme of the editor. This setting only applies when inactive region dimming is enabled.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.inactiveRegionBackgroundColor": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": null,
|
||||
"description": "Controls the background coloring of inactive preprocessor blocks. Input is in the form a hexadecimal color code or a valid Theme Color. If not set, this defaults to transparent. This setting only applies when inactive region dimming is enabled.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.formatting": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -193,6 +221,16 @@
|
||||
"description": "Controls whether parsing of the non-active workspace files uses sleeps to avoid using 100% CPU. The values highest/high/medium/low correspond to approximately 100/75/50/25% CPU usage.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.workspaceSymbols": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"All",
|
||||
"Just My Code"
|
||||
],
|
||||
"default": "Just My Code",
|
||||
"description": "The symbols to include in the query results when 'Go to Symbol in Workspace' is invoked",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.exclusionPolicy": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -242,6 +280,29 @@
|
||||
"description": "Defines the editor behavior for when the Enter key is pressed inside a multiline or single line comment block.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.configurationWarnings": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Enabled",
|
||||
"Disabled"
|
||||
],
|
||||
"default": "Enabled",
|
||||
"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": "${workspaceFolder}/.vscode",
|
||||
"description": "Defines the folder path for cached precompiled headers used by IntelliSense. The default path \"${workspaceFolder}/.vscode\" will be used 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",
|
||||
@@ -278,6 +339,16 @@
|
||||
"description": "The value to use in a configuration if \"macFrameworkPath\" is not specified, or the values to insert if \"${default}\" is present in \"macFrameworkPath\".",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.default.windowsSdkVersion": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": null,
|
||||
"description": "Version of the Windows SDK include path to use on Windows, e.g. '10.0.17134.0'.",
|
||||
"pattern": "^\\d{2}\\.\\d{1}\\.\\d{5}\\.\\d{1}$|^8\\.1$",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.default.compileCommands": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -306,6 +377,7 @@
|
||||
],
|
||||
"enum": [
|
||||
"msvc-x64",
|
||||
"gcc-x64",
|
||||
"clang-x64"
|
||||
],
|
||||
"default": null,
|
||||
@@ -351,6 +423,15 @@
|
||||
"description": "The value to use in a configuration if \"cppStandard\" is either not specified or set to \"${default}\".",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.default.configurationProvider": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"default": null,
|
||||
"description": "The value to use in a configuration if \"configurationProvider\" is either not specified or set to \"${default}\".",
|
||||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.default.browse.path": {
|
||||
"type": [
|
||||
"array",
|
||||
@@ -389,89 +470,134 @@
|
||||
"default": null,
|
||||
"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": [
|
||||
"Default",
|
||||
"Insiders"
|
||||
],
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "C_Cpp.ConfigurationSelect",
|
||||
"title": "Select a Configuration...",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.configurationSelect.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ConfigurationEdit",
|
||||
"title": "Edit Configurations...",
|
||||
"category": "C/Cpp"
|
||||
"command": "C_Cpp.ConfigurationProviderSelect",
|
||||
"title": "%c_cpp.command.configurationProviderSelect.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"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++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.GoToDeclaration",
|
||||
"title": "Go to Declaration",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.goToDeclaration.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.PeekDeclaration",
|
||||
"title": "Peek Declaration",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.peekDeclaration.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.SwitchHeaderSource",
|
||||
"title": "Switch Header/Source",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.switchHeaderSource.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.Navigate",
|
||||
"title": "Navigate...",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.navigate.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ToggleSnippets",
|
||||
"title": "Toggle Snippets",
|
||||
"category": "C/Cpp"
|
||||
"command": "C_Cpp.EnableErrorSquiggles",
|
||||
"title": "%c_cpp.command.enableErrorSquiggles.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ToggleErrorSquiggles",
|
||||
"title": "Toggle Error Squiggles",
|
||||
"category": "C/Cpp"
|
||||
"command": "C_Cpp.DisableErrorSquiggles",
|
||||
"title": "%c_cpp.command.disableErrorSquiggles.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ToggleIncludeFallback",
|
||||
"title": "Toggle IntelliSense Engine Fallback on Include Errors",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.toggleIncludeFallback.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ToggleDimInactiveRegions",
|
||||
"title": "Toggle Inactive Region Colorization",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.toggleDimInactiveRegions.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ShowReleaseNotes",
|
||||
"title": "Show Release Notes",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.showReleaseNotes.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ResetDatabase",
|
||||
"title": "Reset IntelliSense Database",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.resetDatabase.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.PauseParsing",
|
||||
"title": "Pause Parsing",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.pauseParsing.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ResumeParsing",
|
||||
"title": "Resume Parsing",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.resumeParsing.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.ShowParsingCommands",
|
||||
"title": "Show Parsing Commands",
|
||||
"category": "C/Cpp"
|
||||
"title": "%c_cpp.command.showParsingCommands.title%",
|
||||
"category": "C/C++"
|
||||
},
|
||||
{
|
||||
"command": "C_Cpp.TakeSurvey",
|
||||
"title": "Take Survey",
|
||||
"category": "C/Cpp"
|
||||
"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++"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
@@ -526,7 +652,6 @@
|
||||
"cpp"
|
||||
]
|
||||
},
|
||||
"adapterExecutableCommand": "extension.cppdbgAdapterExecutableCommand",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"variables": {
|
||||
"pickProcess": "extension.pickNativeProcess",
|
||||
@@ -535,6 +660,7 @@
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"program"
|
||||
],
|
||||
@@ -572,6 +698,7 @@
|
||||
"description": "One or more GDB/LLDB commands to execute in order to setup the underlying debugger. Example: \"setupCommands\": [ { \"text\": \"-enable-pretty-printing\", \"description\": \"Enable GDB pretty printing\", \"ignoreFailures\": true }].",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
@@ -597,6 +724,7 @@
|
||||
"description": "If provided, this replaces the default commands used to launch a target with some other commands. For example, this can be \"-target-attach\" in order to attach to a target process. An empty command list replaces the launch commands with nothing, which can be useful if the debugger is being provided launch options as command line options. Example: \"customLaunchSetupCommands\": [ { \"text\": \"target-run\", \"description\": \"run target\", \"ignoreFailures\": false }].",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
@@ -641,9 +769,14 @@
|
||||
"description": "Environment variables to add to the environment for the program. Example: [ { \"name\": \"squid\", \"value\": \"clam\" } ].",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"name": "string",
|
||||
"value": "string"
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
@@ -663,6 +796,11 @@
|
||||
"description": "The path to the mi debugger (such as gdb). When unspecified, it will search path first for the debugger.",
|
||||
"default": "/usr/bin/gdb"
|
||||
},
|
||||
"miDebuggerArgs": {
|
||||
"type": "string",
|
||||
"description": "Arguments for the mi debugger (such as gdb) to use. When unspecified.",
|
||||
"default": ""
|
||||
},
|
||||
"miDebuggerServerAddress": {
|
||||
"type": "string",
|
||||
"description": "Network address of the MI Debugger Server to connect to (example: localhost:1234).",
|
||||
@@ -710,7 +848,12 @@
|
||||
},
|
||||
"externalConsole": {
|
||||
"type": "boolean",
|
||||
"description": "If true, a console is launched for the debuggee. If false, no console is launched. Note this option is ignored in some cases for technical reasons.",
|
||||
"description": "If true, a console is launched for the debuggee. If false, on Linux and Windows, it will appear in the Integrated Console.",
|
||||
"default": false
|
||||
},
|
||||
"avoidWindowsConsoleRedirection": {
|
||||
"type": "boolean",
|
||||
"description": "If true, disables debuggee console redirection that is required for Integrated Terminal support.",
|
||||
"default": false
|
||||
},
|
||||
"sourceFileMap": {
|
||||
@@ -804,6 +947,7 @@
|
||||
},
|
||||
"attach": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"program",
|
||||
"processId"
|
||||
@@ -858,12 +1002,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
|
||||
}
|
||||
]
|
||||
@@ -970,6 +1114,7 @@
|
||||
"description": "One or more GDB/LLDB commands to execute in order to setup the underlying debugger. Example: \"setupCommands\": [ { \"text\": \"-enable-pretty-printing\", \"description\": \"Enable GDB pretty printing\", \"ignoreFailures\": true }].",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
@@ -1003,7 +1148,6 @@
|
||||
"cpp"
|
||||
]
|
||||
},
|
||||
"adapterExecutableCommand": "extension.cppvsdbgAdapterExecutableCommand",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"variables": {
|
||||
"pickProcess": "extension.pickNativeProcess"
|
||||
@@ -1011,6 +1155,7 @@
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"program",
|
||||
"cwd"
|
||||
@@ -1044,13 +1189,23 @@
|
||||
"description": "Environment variables to add to the environment for the program. Example: [ { \"name\": \"squid\", \"value\": \"clam\" } ].",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"name": "string",
|
||||
"value": "string"
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"envFile": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a file containing environment variable definitions. These file has key value pairs sepearted 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\".",
|
||||
@@ -1083,6 +1238,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.",
|
||||
@@ -1114,6 +1274,7 @@
|
||||
},
|
||||
"attach": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"processId"
|
||||
],
|
||||
@@ -1132,12 +1293,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
|
||||
}
|
||||
]
|
||||
@@ -1217,109 +1378,115 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configurationDefaults": {
|
||||
"[cpp]": {
|
||||
"editor.autoIndent": false
|
||||
"editor.wordBasedSuggestions": false
|
||||
},
|
||||
"[c]": {
|
||||
"editor.autoIndent": false
|
||||
"editor.wordBasedSuggestions": false
|
||||
}
|
||||
},
|
||||
"snippets": [
|
||||
{
|
||||
"language": "cpp",
|
||||
"path": "./cpp_snippets.json"
|
||||
},
|
||||
{
|
||||
"language": "c",
|
||||
"path": "./cpp_snippets.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "npm run vscode:prepublish",
|
||||
"compileDev": "webpack --mode development",
|
||||
"generateOptionsSchema": "gulp generateOptionsSchema",
|
||||
"integrationTests": "gulp integrationTests",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install",
|
||||
"pretest": "tsc -p ./",
|
||||
"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": "node ./tools/prepublish.js && webpack --mode production",
|
||||
"watch": "webpack --watch --mode development"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^2.2.43",
|
||||
"@types/node": "^8.0.46",
|
||||
"gulp": "3.9.1",
|
||||
"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.17"
|
||||
"@types/mocha": "^5.2.6",
|
||||
"@types/node": "^12.0.0",
|
||||
"async-child-process": "^1.1.1",
|
||||
"await-notify": "^1.0.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-env": "^0.4.0",
|
||||
"gulp-mocha": "^6.0.0",
|
||||
"gulp-tslint": "^8.1.4",
|
||||
"tslint": "^5.16.0",
|
||||
"tslint-microsoft-contrib": "^6.1.1",
|
||||
"tslint-no-unused-expression-chai": "^0.1.4",
|
||||
"ts-loader": "^6.0.0",
|
||||
"typescript": "^3.4.5",
|
||||
"vrsource-tslint-rules": "^6.0.0",
|
||||
"vscode": "^1.1.34",
|
||||
"webpack": "^4.30.0",
|
||||
"webpack-cli": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"http-proxy-agent": "~2.0.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-debugadapter": "~1.24.0",
|
||||
"vscode-debugprotocol": "~1.24.0",
|
||||
"vscode-extension-telemetry": "~0.0.11",
|
||||
"vscode-languageclient": "3.5.1",
|
||||
"yauzl": "~2.8.0"
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"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",
|
||||
"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=874519",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092043",
|
||||
"platforms": [
|
||||
"linux"
|
||||
],
|
||||
@@ -1333,7 +1500,7 @@
|
||||
},
|
||||
{
|
||||
"description": "C/C++ language components (Linux / x86)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=874520",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092112",
|
||||
"platforms": [
|
||||
"linux"
|
||||
],
|
||||
@@ -1349,7 +1516,7 @@
|
||||
},
|
||||
{
|
||||
"description": "C/C++ language components (OS X)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=874521",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092042",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
@@ -1360,7 +1527,7 @@
|
||||
},
|
||||
{
|
||||
"description": "C/C++ language components (Windows)",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=874522",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2092111",
|
||||
"platforms": [
|
||||
"win32"
|
||||
],
|
||||
@@ -1414,7 +1581,7 @@
|
||||
},
|
||||
{
|
||||
"description": "Mono Framework Assemblies",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=816539",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=2027135",
|
||||
"platforms": [
|
||||
"linux",
|
||||
"darwin"
|
||||
@@ -1423,7 +1590,7 @@
|
||||
},
|
||||
{
|
||||
"description": "Mono Runtime (Linux / x86)",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=816540",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=2027410",
|
||||
"platforms": [
|
||||
"linux"
|
||||
],
|
||||
@@ -1438,7 +1605,7 @@
|
||||
},
|
||||
{
|
||||
"description": "Mono Runtime (Linux / x86_64)",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=816541",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=2027416",
|
||||
"platforms": [
|
||||
"linux"
|
||||
],
|
||||
@@ -1451,7 +1618,7 @@
|
||||
},
|
||||
{
|
||||
"description": "Mono Runtime (OS X)",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=816542",
|
||||
"url": "https://go.microsoft.com/fwlink/?LinkId=2027403",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
@@ -1474,7 +1641,7 @@
|
||||
},
|
||||
{
|
||||
"description": "Visual Studio Windows Debugger",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=872985",
|
||||
"url": "https://go.microsoft.com/fwlink/?linkid=2082216",
|
||||
"platforms": [
|
||||
"win32"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"c_cpp.command.configurationSelect.title": "Scegli una configurazione...",
|
||||
"c_cpp.command.configurationProviderSelect.title": "Cambia provider 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.navigate.title": "Naviga...",
|
||||
"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",
|
||||
"c_cpp.command.resetDatabase.title": "Reimposta il database di IntelliSense",
|
||||
"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.buildAndDebugActiveFile.title": "Compila ed Esegui il debug del file attivo",
|
||||
"c_cpp.command.logDiagnostics.title": "Registra Diagnostica"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"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.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"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"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": "记录诊断"
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as util from '../common';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
class RefreshButton implements vscode.QuickInputButton {
|
||||
get iconPath(): { dark: vscode.Uri; light: vscode.Uri } {
|
||||
const refreshImagePathDark: string = util.getExtensionFilePath("assets/Refresh_inverse.svg");
|
||||
const refreshImagePathLight: string = util.getExtensionFilePath("assets/Refresh.svg");
|
||||
|
||||
return {
|
||||
dark: vscode.Uri.file(refreshImagePathDark),
|
||||
light: vscode.Uri.file(refreshImagePathLight)
|
||||
};
|
||||
}
|
||||
|
||||
get tooltip(): string {
|
||||
return "Refresh process list";
|
||||
}
|
||||
}
|
||||
|
||||
export interface AttachItem extends vscode.QuickPickItem {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export function showQuickPick(getAttachItems: () => Promise<AttachItem[]>): Promise<string> {
|
||||
return getAttachItems().then(processEntries => {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
let quickPick: vscode.QuickPick<AttachItem> = vscode.window.createQuickPick<AttachItem>();
|
||||
quickPick.title = "Attach to process";
|
||||
quickPick.canSelectMany = false;
|
||||
quickPick.matchOnDescription = true;
|
||||
quickPick.matchOnDetail = true;
|
||||
quickPick.placeholder = "Select the process to attach to";
|
||||
quickPick.items = processEntries;
|
||||
quickPick.buttons = [new RefreshButton()];
|
||||
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
quickPick.onDidTriggerButton(button => {
|
||||
getAttachItems().then(processEntries => quickPick.items = processEntries);
|
||||
}, undefined, disposables);
|
||||
|
||||
quickPick.onDidAccept(() => {
|
||||
if (quickPick.selectedItems.length !== 1) {
|
||||
reject(new Error("Process not selected"));
|
||||
}
|
||||
|
||||
let selectedId: string = quickPick.selectedItems[0].id;
|
||||
|
||||
disposables.forEach(item => item.dispose());
|
||||
quickPick.dispose();
|
||||
|
||||
resolve(selectedId);
|
||||
}, undefined, disposables);
|
||||
|
||||
quickPick.onDidHide(() => {
|
||||
disposables.forEach(item => item.dispose());
|
||||
quickPick.dispose();
|
||||
|
||||
reject(new Error("Process not selected."));
|
||||
}, undefined, disposables);
|
||||
|
||||
quickPick.show();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import { execChildProcess } from '../common';
|
||||
import { PsProcessParser } from './nativeAttach';
|
||||
import { AttachItem, showQuickPick } from './attachQuickPick';
|
||||
|
||||
import * as debugUtils from './utils';
|
||||
import * as fs from 'fs';
|
||||
@@ -13,10 +14,6 @@ import * as path from 'path';
|
||||
import * as util from '../common';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export interface AttachItem extends vscode.QuickPickItem {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface AttachItemsProvider {
|
||||
getAttachItems(): Promise<AttachItem[]>;
|
||||
}
|
||||
@@ -29,19 +26,7 @@ export class AttachPicker {
|
||||
if (!ready) {
|
||||
util.displayExtensionNotReadyPrompt();
|
||||
} else {
|
||||
return this.attachItemsProvider.getAttachItems()
|
||||
.then(processEntries => {
|
||||
let attachPickOptions: vscode.QuickPickOptions = {
|
||||
matchOnDescription: true,
|
||||
matchOnDetail: true,
|
||||
placeHolder: "Select the process to attach to"
|
||||
};
|
||||
|
||||
return vscode.window.showQuickPick(processEntries, attachPickOptions)
|
||||
.then(chosenProcess => {
|
||||
return chosenProcess ? chosenProcess.id : Promise.reject<string>(new Error("Process not selected."));
|
||||
});
|
||||
});
|
||||
return showQuickPick(() => this.attachItemsProvider.getAttachItems());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -74,7 +59,7 @@ export class RemoteAttachPicker {
|
||||
!fs.existsSync(pipeTransport.pipeProgram)) {
|
||||
const pipeProgramStr: string = pipeTransport.pipeProgram.toLowerCase().trim();
|
||||
const expectedArch: debugUtils.ArchType = debugUtils.ArchType[process.arch];
|
||||
|
||||
|
||||
// Check for pipeProgram
|
||||
if (!fs.existsSync(config.pipeTransport.pipeProgram)) {
|
||||
pipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(pipeProgramStr, expectedArch);
|
||||
@@ -84,7 +69,7 @@ export class RemoteAttachPicker {
|
||||
if (!pipeProgram && config.pipeTransport.pipeCwd) {
|
||||
const pipeCwdStr: string = config.pipeTransport.pipeCwd.toLowerCase().trim();
|
||||
const newPipeProgramStr: string = path.join(pipeCwdStr, pipeProgramStr);
|
||||
|
||||
|
||||
if (!fs.existsSync(newPipeProgramStr)) {
|
||||
pipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(newPipeProgramStr, expectedArch);
|
||||
}
|
||||
@@ -120,10 +105,11 @@ export class RemoteAttachPicker {
|
||||
|
||||
private getRemoteOSAndProcesses(pipeCmd: string): Promise<AttachItem[]> {
|
||||
// Commands to get OS and processes
|
||||
const command: string = `bash -c 'uname && if [ $(uname) == "Linux" ] ; then ${PsProcessParser.psLinuxCommand} ; elif [ $(uname) == "Darwin" ] ; ` +
|
||||
`then ${PsProcessParser.psDarwinCommand}; fi'`;
|
||||
const command: string = `sh -c "uname && if [ $(uname) = \\\"Linux\\\" ] ; then ${PsProcessParser.psLinuxCommand} ; elif [ $(uname) = \\\"Darwin\\\" ] ; ` +
|
||||
`then ${PsProcessParser.psDarwinCommand}; fi"`;
|
||||
|
||||
return execChildProcess(`${pipeCmd} "${command}"`, null, this._channel).then(output => {
|
||||
// Must use single quotes around ${command}. Linux systems evaluate $() within double-quotes.
|
||||
return execChildProcess(`${pipeCmd} '${command}'`, null, this._channel).then(output => {
|
||||
// OS will be on first line
|
||||
// Processess will follow if listed
|
||||
let lines: string[] = output.split(/\r?\n/);
|
||||
|
||||
@@ -7,11 +7,82 @@ 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 { 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,45 +94,166 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to add all missing attributes to the debug configuration being launched.
|
||||
*/
|
||||
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
|
||||
// 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) {
|
||||
if (config.type === 'cppvsdbg') {
|
||||
// Fail if cppvsdbg type is running on non-Windows
|
||||
if (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;
|
||||
}
|
||||
|
||||
// Modify WSL config for OpenDebugAD7
|
||||
if (os.platform() === 'win32' &&
|
||||
config.pipeTransport &&
|
||||
config.pipeTransport.pipeProgram) {
|
||||
let replacedPipeProgram: string = null;
|
||||
const pipeProgramStr: string = config.pipeTransport.pipeProgram.toLowerCase().trim();
|
||||
// Disable debug heap by default, enable if 'enableDebugHeap' is set.
|
||||
if (!config.enableDebugHeap) {
|
||||
const disableDebugHeapEnvSetting : Environment = {"name" : "_NO_DEBUG_HEAP", "value" : "1"};
|
||||
|
||||
// OpenDebugAD7 is a 32-bit process. Make sure the WSL pipe transport is using the correct program.
|
||||
replacedPipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(pipeProgramStr, debugUtils.ArchType.ia32);
|
||||
if (config.environment && util.isArray(config.environment)) {
|
||||
config.environment.push(disableDebugHeapEnvSetting);
|
||||
} else {
|
||||
config.environment = [disableDebugHeapEnvSetting];
|
||||
}
|
||||
}
|
||||
|
||||
// If pipeProgram does not get replaced and there is a pipeCwd, concatenate with pipeProgramStr and attempt to replace.
|
||||
if (!replacedPipeProgram && !path.isAbsolute(pipeProgramStr) && config.pipeTransport.pipeCwd) {
|
||||
const pipeCwdStr: string = config.pipeTransport.pipeCwd.toLowerCase().trim();
|
||||
const newPipeProgramStr: string = path.join(pipeCwdStr, pipeProgramStr);
|
||||
|
||||
replacedPipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(newPipeProgramStr, debugUtils.ArchType.ia32);
|
||||
// Add environment variables from .env file
|
||||
if (config.envFile) {
|
||||
try {
|
||||
const parsedFile: ParsedEnvironmentFile = ParsedEnvironmentFile.CreateFromFile(config.envFile.replace(/\${workspaceFolder}/g, folder.uri.path), 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("Can't parse envFile " + config.envFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (replacedPipeProgram) {
|
||||
config.pipeTransport.pipeProgram = replacedPipeProgram;
|
||||
// Modify WSL config for OpenDebugAD7
|
||||
if (os.platform() === 'win32' &&
|
||||
config.pipeTransport &&
|
||||
config.pipeTransport.pipeProgram) {
|
||||
let replacedPipeProgram: string = null;
|
||||
const pipeProgramStr: string = config.pipeTransport.pipeProgram.toLowerCase().trim();
|
||||
|
||||
// OpenDebugAD7 is a 32-bit process. Make sure the WSL pipe transport is using the correct program.
|
||||
replacedPipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(pipeProgramStr, debugUtils.ArchType.ia32);
|
||||
|
||||
// If pipeProgram does not get replaced and there is a pipeCwd, concatenate with pipeProgramStr and attempt to replace.
|
||||
if (!replacedPipeProgram && !path.isAbsolute(pipeProgramStr) && config.pipeTransport.pipeCwd) {
|
||||
const pipeCwdStr: string = config.pipeTransport.pipeCwd.toLowerCase().trim();
|
||||
const newPipeProgramStr: string = path.join(pipeCwdStr, pipeProgramStr);
|
||||
|
||||
replacedPipeProgram = debugUtils.ArchitectureReplacer.checkAndReplaceWSLPipeProgram(newPipeProgramStr, debugUtils.ArchType.ia32);
|
||||
}
|
||||
|
||||
if (replacedPipeProgram) {
|
||||
config.pipeTransport.pipeProgram = replacedPipeProgram;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
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 {
|
||||
@@ -71,7 +263,7 @@ export class CppVsDbgConfigurationProvider extends CppConfigurationProvider {
|
||||
}
|
||||
|
||||
export class CppDbgConfigurationProvider extends CppConfigurationProvider {
|
||||
public constructor(provider: IConfigurationAssetProvider) {
|
||||
public constructor(provider: IConfigurationAssetProvider) {
|
||||
super(provider, DebuggerType.cppdbg);
|
||||
}
|
||||
}
|
||||
@@ -101,12 +293,12 @@ abstract class DefaultConfigurationProvider implements IConfigurationAssetProvid
|
||||
|
||||
public getInitialConfigurations(debuggerType: DebuggerType): any {
|
||||
let configurationSnippet: IConfigurationSnippet[] = [];
|
||||
|
||||
|
||||
// Only launch configurations are initial configurations
|
||||
this.configurations.forEach(configuration => {
|
||||
configurationSnippet.push(configuration.GetLaunchConfiguration());
|
||||
configurationSnippet.push(configuration.GetLaunchConfiguration());
|
||||
});
|
||||
|
||||
|
||||
let initialConfigurations: any = configurationSnippet.filter(snippet => snippet.debuggerType === debuggerType && snippet.isInitialConfiguration)
|
||||
.map(snippet => JSON.parse(snippet.bodyText));
|
||||
|
||||
@@ -141,7 +333,7 @@ class WindowsConfigurationProvider extends DefaultConfigurationProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.configurations = [
|
||||
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
new PipeTransportConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
new WindowsConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
new WSLConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
@@ -157,7 +349,7 @@ class OSXConfigurationProvider extends DefaultConfigurationProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.configurations = [
|
||||
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram),
|
||||
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -177,7 +369,7 @@ class LinuxConfigurationProvider extends DefaultConfigurationProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.configurations = [
|
||||
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
|
||||
new PipeTransportConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock)
|
||||
];
|
||||
}
|
||||
@@ -220,7 +412,7 @@ export class ConfigurationSnippetProvider implements vscode.CompletionItemProvid
|
||||
|
||||
items.map((item) => {
|
||||
item.insertText = item.insertText + ','; // Add comma
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve(new vscode.CompletionList(items, true));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as child_process from 'child_process';
|
||||
import * as os from 'os';
|
||||
import { AttachItem, AttachItemsProvider } from './attachToProcess';
|
||||
import { AttachItemsProvider } from './attachToProcess';
|
||||
import { AttachItem } from './attachQuickPick';
|
||||
|
||||
class Process {
|
||||
constructor(public name: string, public pid: string, public commandLine: string) { }
|
||||
@@ -111,8 +112,8 @@ export class PsProcessParser {
|
||||
// Note that comm on Linux systems is truncated to 16 characters:
|
||||
// https://bugzilla.redhat.com/show_bug.cgi?id=429565
|
||||
// Since 'args' contains the full path to the executable, even if truncated, searching will work as desired.
|
||||
public static get psLinuxCommand(): string { return `ps -axww -o pid=,comm=${PsProcessParser.commColumnTitle},args=`; }
|
||||
public static get psDarwinCommand(): string { return `ps -axww -o pid=,comm=${PsProcessParser.commColumnTitle},args= -c`; }
|
||||
public static get psLinuxCommand(): string { return `ps axww -o pid=,comm=${PsProcessParser.commColumnTitle},args=`; }
|
||||
public static get psDarwinCommand(): string { return `ps axww -o pid=,comm=${PsProcessParser.commColumnTitle},args= -c`; }
|
||||
|
||||
// Only public for tests.
|
||||
public static ParseProcessFromPs(processes: string): Process[] {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@ import * as util from '../common';
|
||||
import * as telemetry from '../telemetry';
|
||||
import * as cpptools from './client';
|
||||
import * as path from 'path';
|
||||
import { getCustomConfigProviders } from './customProviders';
|
||||
|
||||
const defaultClientKey: string = "@@default@@";
|
||||
export interface ClientKey {
|
||||
@@ -118,7 +119,7 @@ export class ClientCollection {
|
||||
this.languageClients.set(key, cpptools.createNullClient());
|
||||
}
|
||||
|
||||
if (this.activeClient === client) {
|
||||
if (this.activeClient === client && this.activeDocument) {
|
||||
this.activeClient = this.getClientFor(this.activeDocument.uri);
|
||||
this.activeClient.activeDocumentChanged(this.activeDocument);
|
||||
}
|
||||
@@ -153,12 +154,12 @@ export class ClientCollection {
|
||||
client.TrackedDocuments.forEach(document => this.transferOwnership(document, client));
|
||||
client.TrackedDocuments.clear();
|
||||
|
||||
if (this.activeClient === client) {
|
||||
if (this.activeClient === client && this.activeDocument) {
|
||||
// Need to make a different client the active client.
|
||||
this.activeClient = this.getClientFor(this.activeDocument.uri);
|
||||
this.activeClient.activeDocumentChanged(this.activeDocument);
|
||||
// may not need this, the navigation UI should not have changed.
|
||||
// this.activeClient.selectionChanged(vscode.window.activeTextEditor.selection.start);
|
||||
// this.activeClient.selectionChanged(Range.create(vscode.window.activeTextEditor.selection.start, vscode.window.activeTextEditor.selection.end);
|
||||
}
|
||||
|
||||
client.dispose();
|
||||
@@ -174,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);
|
||||
}
|
||||
@@ -187,7 +189,9 @@ export class ClientCollection {
|
||||
} else {
|
||||
let key: string = util.asFolder(folder.uri);
|
||||
if (!this.languageClients.has(key)) {
|
||||
this.languageClients.set(key, cpptools.createClient(this, folder));
|
||||
let newClient: cpptools.Client = cpptools.createClient(this, folder);
|
||||
this.languageClients.set(key, newClient);
|
||||
getCustomConfigProviders().forEach(provider => newClient.onRegisterCustomConfigurationProvider(provider));
|
||||
}
|
||||
return this.languageClients.get(key);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { CustomConfigurationProvider, Version, SourceFileConfigurationItem, WorkspaceBrowseConfiguration } from 'vscode-cpptools';
|
||||
import { CppSettings } from './settings';
|
||||
|
||||
/**
|
||||
* An interface that is guaranteed to be backward compatible with version 0
|
||||
*/
|
||||
export interface CustomConfigurationProvider1 extends CustomConfigurationProvider {
|
||||
isReady: boolean;
|
||||
readonly isValid: boolean;
|
||||
readonly version: Version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the incoming CustomConfigurationProvider so that we can treat all of them as if they were the same version (e.g. latest)
|
||||
*/
|
||||
class CustomProviderWrapper implements CustomConfigurationProvider1 {
|
||||
private provider: CustomConfigurationProvider;
|
||||
private _isReady: boolean;
|
||||
private _version: Version;
|
||||
|
||||
constructor(provider: CustomConfigurationProvider, version: Version) {
|
||||
this._isReady = version < Version.v2;
|
||||
this.provider = provider;
|
||||
if (provider.extensionId && version === Version.v0) {
|
||||
version = Version.v1; // provider implemented the new API but is interfacing with the extension using the old API version.
|
||||
}
|
||||
this._version = version;
|
||||
}
|
||||
|
||||
public get isReady(): boolean {
|
||||
return this._isReady;
|
||||
}
|
||||
|
||||
public set isReady(ready: boolean) {
|
||||
this._isReady = ready;
|
||||
}
|
||||
|
||||
public get isValid(): boolean {
|
||||
let valid: boolean = !!(this.provider.name && this.provider.canProvideConfiguration && this.provider.provideConfigurations);
|
||||
if (valid && this._version > Version.v0) {
|
||||
valid = !!(this.provider.extensionId && this.provider.dispose);
|
||||
}
|
||||
if (valid && this._version > Version.v1) {
|
||||
valid = !!(this.provider.canProvideBrowseConfiguration && this.provider.provideBrowseConfiguration);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public get version(): Version {
|
||||
return this._version;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this.provider.name;
|
||||
}
|
||||
|
||||
public get extensionId(): string {
|
||||
return this._version === Version.v0 ? this.provider.name : this.provider.extensionId;
|
||||
}
|
||||
|
||||
public canProvideConfiguration(uri: vscode.Uri, token?: vscode.CancellationToken): Thenable<boolean> {
|
||||
return this.provider.canProvideConfiguration(uri, token);
|
||||
}
|
||||
|
||||
public provideConfigurations(uris: vscode.Uri[], token?: vscode.CancellationToken): Thenable<SourceFileConfigurationItem[]> {
|
||||
return this.provider.provideConfigurations(uris, token);
|
||||
}
|
||||
|
||||
public canProvideBrowseConfiguration(token?: vscode.CancellationToken): Thenable<boolean> {
|
||||
return this._version < Version.v2 ? Promise.resolve(false) : this.provider.canProvideBrowseConfiguration(token);
|
||||
}
|
||||
|
||||
public provideBrowseConfiguration(token?: vscode.CancellationToken): Thenable<WorkspaceBrowseConfiguration> {
|
||||
console.assert(this._version >= Version.v2);
|
||||
return this._version < Version.v2 ? Promise.resolve({browsePath: []}) : this.provider.provideBrowseConfiguration(token);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this._version !== Version.v0) {
|
||||
this.provider.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class CustomConfigurationProviderCollection {
|
||||
private providers: Map<string, CustomProviderWrapper> = new Map<string, CustomProviderWrapper>();
|
||||
|
||||
private logProblems(provider: CustomConfigurationProvider, version: Version): void {
|
||||
let missing: string[] = [];
|
||||
if (!provider.name) {
|
||||
missing.push("'name'");
|
||||
}
|
||||
if (version !== Version.v0 && !provider.extensionId) {
|
||||
missing.push("'extensionId'");
|
||||
}
|
||||
if (!provider.canProvideConfiguration) {
|
||||
missing.push("'canProvideConfiguration'");
|
||||
}
|
||||
if (!provider.provideConfigurations) {
|
||||
missing.push("'canProvideConfiguration'");
|
||||
}
|
||||
if (version !== Version.v0 && !provider.dispose) {
|
||||
missing.push("'dispose'");
|
||||
}
|
||||
if (version >= Version.v2 && !provider.canProvideBrowseConfiguration) {
|
||||
missing.push("'canProvideBrowseConfiguration'");
|
||||
}
|
||||
if (version >= Version.v2 && !provider.provideBrowseConfiguration) {
|
||||
missing.push("'provideBrowseConfiguration'");
|
||||
}
|
||||
console.error(`CustomConfigurationProvider was not registered. The following properties are missing from the implementation: ${missing.join(", ")}.`);
|
||||
}
|
||||
|
||||
private getId(provider: string|CustomConfigurationProvider): string {
|
||||
if (typeof provider === "string") {
|
||||
return provider;
|
||||
} else if (provider.extensionId) {
|
||||
return provider.extensionId;
|
||||
} else if (provider.name) {
|
||||
return provider.name;
|
||||
} else {
|
||||
console.error(`invalid provider: ${provider}`);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public get size(): number {
|
||||
return this.providers.size;
|
||||
}
|
||||
|
||||
public add(provider: CustomConfigurationProvider, version: Version): boolean {
|
||||
if (new CppSettings().intelliSenseEngine === "Disabled") {
|
||||
console.warn("IntelliSense is disabled. Provider will not be registered.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let wrapper: CustomProviderWrapper = new CustomProviderWrapper(provider, version);
|
||||
if (!wrapper.isValid) {
|
||||
this.logProblems(provider, version);
|
||||
return false;
|
||||
}
|
||||
|
||||
let exists: boolean = this.providers.has(wrapper.extensionId);
|
||||
if (exists) {
|
||||
let existing: CustomProviderWrapper = this.providers.get(wrapper.extensionId);
|
||||
exists = (existing.version === Version.v0 && wrapper.version === Version.v0);
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
this.providers.set(wrapper.extensionId, wrapper);
|
||||
} else {
|
||||
console.error(`CustomConfigurationProvider '${wrapper.extensionId}' has already been registered.`);
|
||||
}
|
||||
return !exists;
|
||||
}
|
||||
|
||||
public get(provider: string|CustomConfigurationProvider): CustomConfigurationProvider1|null {
|
||||
let id: string = this.getId(provider);
|
||||
|
||||
if (this.providers.has(id)) {
|
||||
return this.providers.get(id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public forEach(func: (provider: CustomConfigurationProvider1) => void): void {
|
||||
this.providers.forEach(provider => func(provider));
|
||||
}
|
||||
|
||||
public remove(provider: CustomConfigurationProvider): void {
|
||||
let id: string = this.getId(provider);
|
||||
if (this.providers.has(id)) {
|
||||
this.providers.delete(id);
|
||||
} else {
|
||||
console.warn(`${id} is not registered`);
|
||||
}
|
||||
}
|
||||
|
||||
public checkId(providerId?: string): string {
|
||||
if (!providerId) {
|
||||
return providerId;
|
||||
}
|
||||
let found: CustomConfigurationProvider1[] = [];
|
||||
let noUpdate: boolean = false;
|
||||
this.forEach(provider => {
|
||||
if (provider.extensionId === providerId) {
|
||||
noUpdate = true;
|
||||
} else if (provider.name === providerId && provider.version !== Version.v0) {
|
||||
found.push(provider);
|
||||
}
|
||||
});
|
||||
if (noUpdate) {
|
||||
return providerId;
|
||||
}
|
||||
if (found.length === 1) {
|
||||
return found[0].extensionId;
|
||||
} else if (found.length > 1) {
|
||||
console.warn("duplicate provider name found. Not upgrading.");
|
||||
}
|
||||
return providerId;
|
||||
}
|
||||
}
|
||||
|
||||
let providerCollection: CustomConfigurationProviderCollection = new CustomConfigurationProviderCollection();
|
||||
|
||||
export function getCustomConfigProviders(): CustomConfigurationProviderCollection {
|
||||
return providerCollection;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as util from '../common';
|
||||
import * as telemetry from '../telemetry';
|
||||
@@ -13,9 +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 * as os from 'os';
|
||||
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, BuildInfo } from '../githubAPI';
|
||||
import * as configs from './configurations';
|
||||
import { PackageVersion } from '../packageVersion';
|
||||
import { getTemporaryCommandRegistrarInstance } from '../commands';
|
||||
|
||||
let prevCrashFile: string;
|
||||
let clients: ClientCollection;
|
||||
@@ -24,15 +33,24 @@ let ui: UI;
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let languageConfigurations: vscode.Disposable[] = [];
|
||||
let intervalTimer: NodeJS.Timer;
|
||||
let insiderUpdateTimer: NodeJS.Timer;
|
||||
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.
|
||||
@@ -41,9 +59,10 @@ export function activate(activationEventOccurred: boolean): void {
|
||||
activatedPreviously.Value = false;
|
||||
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) {
|
||||
@@ -51,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) {
|
||||
@@ -74,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();
|
||||
@@ -97,6 +288,22 @@ function onActivationEvent(): void {
|
||||
}
|
||||
|
||||
function realActivation(): void {
|
||||
if (new CppSettings().intelliSenseEngine === "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;
|
||||
console.log("starting language server");
|
||||
clients = new ClientCollection();
|
||||
@@ -108,6 +315,12 @@ function realActivation(): void {
|
||||
onDidChangeActiveTextEditor(vscode.window.activeTextEditor);
|
||||
}
|
||||
|
||||
// There may have already been registered CustomConfigurationProviders.
|
||||
// Request for configurations from those providers.
|
||||
clients.forEach(client => {
|
||||
getCustomConfigProviders().forEach(provider => client.onRegisterCustomConfigurationProvider(provider));
|
||||
});
|
||||
|
||||
disposables.push(vscode.workspace.onDidChangeConfiguration(onDidChangeSettings));
|
||||
disposables.push(vscode.workspace.onDidSaveTextDocument(onDidSaveTextDocument));
|
||||
disposables.push(vscode.window.onDidChangeActiveTextEditor(onDidChangeActiveTextEditor));
|
||||
@@ -117,6 +330,15 @@ function realActivation(): void {
|
||||
updateLanguageConfigurations();
|
||||
|
||||
reportMacCrashes();
|
||||
|
||||
const settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
|
||||
|
||||
if (settings.updateChannel === 'Default') {
|
||||
suggestInsidersChannel();
|
||||
} else if (settings.updateChannel === 'Insiders') {
|
||||
insiderUpdateTimer = setInterval(checkAndApplyUpdate, insiderUpdateTimerInterval, settings.updateChannel);
|
||||
checkAndApplyUpdate(settings.updateChannel);
|
||||
}
|
||||
|
||||
intervalTimer = setInterval(onInterval, 2500);
|
||||
}
|
||||
@@ -134,7 +356,19 @@ export function updateLanguageConfigurations(): void {
|
||||
*********************************************/
|
||||
|
||||
function onDidChangeSettings(): void {
|
||||
const changedActiveClientSettings: { [key: string] : string } = clients.ActiveClient.onDidChangeSettings();
|
||||
clients.forEach(client => client.onDidChangeSettings());
|
||||
|
||||
const newUpdateChannel: string = changedActiveClientSettings['updateChannel'];
|
||||
if (newUpdateChannel) {
|
||||
if (newUpdateChannel === 'Default') {
|
||||
clearInterval(insiderUpdateTimer);
|
||||
} else if (newUpdateChannel === 'Insiders') {
|
||||
insiderUpdateTimer = setInterval(checkAndApplyUpdate, insiderUpdateTimerInterval);
|
||||
}
|
||||
|
||||
checkAndApplyUpdate(newUpdateChannel);
|
||||
}
|
||||
}
|
||||
|
||||
let saveMessageShown: boolean = false;
|
||||
@@ -162,7 +396,7 @@ function onDidChangeActiveTextEditor(editor: vscode.TextEditor): void {
|
||||
} else {
|
||||
activeDocument = editor.document.uri.toString();
|
||||
clients.activeDocumentChanged(editor.document);
|
||||
clients.ActiveClient.selectionChanged(editor.selection.start);
|
||||
clients.ActiveClient.selectionChanged(Range.create(editor.selection.start, editor.selection.end));
|
||||
}
|
||||
ui.activeDocumentChanged();
|
||||
}
|
||||
@@ -172,7 +406,7 @@ function onDidChangeTextEditorSelection(event: vscode.TextEditorSelectionChangeE
|
||||
if (!event.textEditor || !vscode.window.activeTextEditor || event.textEditor.document.uri !== vscode.window.activeTextEditor.document.uri ||
|
||||
(event.textEditor.document.languageId !== "cpp" && event.textEditor.document.languageId !== "c")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (activeDocument !== event.textEditor.document.uri.toString()) {
|
||||
// For some strange (buggy?) reason we don't reliably get onDidChangeActiveTextEditor callbacks.
|
||||
@@ -180,7 +414,7 @@ function onDidChangeTextEditorSelection(event: vscode.TextEditorSelectionChangeE
|
||||
clients.activeDocumentChanged(event.textEditor.document);
|
||||
ui.activeDocumentChanged();
|
||||
}
|
||||
clients.ActiveClient.selectionChanged(event.selections[0].start);
|
||||
clients.ActiveClient.selectionChanged(Range.create(event.selections[0].start, event.selections[0].end));
|
||||
}
|
||||
|
||||
function onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
|
||||
@@ -192,21 +426,266 @@ function onInterval(): void {
|
||||
clients.ActiveClient.onInterval();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a VSIX package. This helper function will exist until VSCode offers a command to do so.
|
||||
* @param updateChannel The user's updateChannel setting.
|
||||
*/
|
||||
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) => {
|
||||
const vsCodeScriptPath: string = function(platformInfo): string {
|
||||
if (platformInfo.platform === 'win32') {
|
||||
const vsCodeBinName: string = path.basename(process.execPath);
|
||||
let cmdFile: string; // Windows VS Code Insiders/Exploration breaks VS Code naming conventions
|
||||
if (vsCodeBinName === 'Code - Insiders.exe') {
|
||||
cmdFile = 'code-insiders.cmd';
|
||||
} else if (vsCodeBinName === 'Code - Exploration.exe') {
|
||||
cmdFile = 'code-exploration.cmd';
|
||||
} else {
|
||||
cmdFile = 'code.cmd';
|
||||
}
|
||||
const vsCodeExeDir: string = path.dirname(process.execPath);
|
||||
return path.join(vsCodeExeDir, 'bin', cmdFile);
|
||||
} else if (platformInfo.platform === 'darwin') {
|
||||
return path.join(process.execPath, '..', '..', '..', '..', '..',
|
||||
'Resources', 'app', 'bin', 'code');
|
||||
} else {
|
||||
const vsCodeBinName: string = path.basename(process.execPath);
|
||||
try {
|
||||
const stdout: Buffer = execSync('which ' + vsCodeBinName);
|
||||
return stdout.toString().trim();
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}(platformInfo);
|
||||
if (!vsCodeScriptPath) {
|
||||
return Promise.reject(new Error('Failed to find VS Code script'));
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to launch VS Code script process for installation'));
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
let process: ChildProcess;
|
||||
try {
|
||||
process = spawn(vsCodeScriptPath, ['--install-extension', vsixLocation]);
|
||||
if (process.pid === undefined) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (error) {
|
||||
reject(new Error('Failed to launch VS Code script process for installation'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// If downgrading, the VS Code CLI will prompt whether the user is sure they would like to downgrade.
|
||||
// Respond to this by writing 0 to stdin (the option to override and install the VSIX package)
|
||||
let sentOverride: boolean = false;
|
||||
process.stdout.on('data', () => {
|
||||
if (sentOverride) {
|
||||
return;
|
||||
}
|
||||
process.stdin.write('0\n');
|
||||
sentOverride = true;
|
||||
clearInterval(timer);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
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();
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error(`${cppInstallVsixStr}${error.message}`);
|
||||
if (error.message.indexOf('/') !== -1 || error.message.indexOf('\\') !== -1) {
|
||||
error.message = "Potential PII hidden";
|
||||
}
|
||||
telemetry.logLanguageServerEvent('installVsix', { 'error': error.message, 'success': 'false' });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
disposables.push(vscode.commands.registerCommand('C_Cpp.SwitchHeaderSource', onSwitchHeaderSource));
|
||||
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.ToggleSnippets', onToggleSnippets));
|
||||
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));
|
||||
@@ -214,6 +693,9 @@ 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('cpptools.activeConfigName', onGetActiveConfigName));
|
||||
getTemporaryCommandRegistrarInstance().executeDelayedCommands();
|
||||
}
|
||||
|
||||
function onNavigate(): void {
|
||||
@@ -318,6 +800,35 @@ function onSelectConfiguration(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function onSelectConfigurationProvider(): void {
|
||||
onActivationEvent();
|
||||
if (!isFolderOpen()) {
|
||||
vscode.window.showInformationMessage('Open a folder first to select a configuration provider');
|
||||
} else {
|
||||
selectClient().then(client => client.handleConfigurationProviderSelectCommand(), rejected => {});
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
@@ -337,54 +848,20 @@ 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 onToggleSnippets(): void {
|
||||
function onDisableSquiggles(): void {
|
||||
onActivationEvent();
|
||||
|
||||
// This will apply to all clients as it's a global toggle. It will require a reload.
|
||||
const snippetsCatName: string = "Snippets";
|
||||
let newPackageJson: any = util.getRawPackageJson();
|
||||
|
||||
if (newPackageJson.categories.findIndex(cat => cat === snippetsCatName) === -1) {
|
||||
// Add the Snippet category and snippets node.
|
||||
|
||||
newPackageJson.categories.push(snippetsCatName);
|
||||
newPackageJson.contributes.snippets = [{"language": "cpp", "path": "./cpp_snippets.json"}, {"language": "c", "path": "./cpp_snippets.json"}];
|
||||
|
||||
fs.writeFile(util.getPackageJsonPath(), util.stringifyPackageJson(newPackageJson), () => {
|
||||
showReloadPrompt("Reload Window to finish enabling C++ snippets");
|
||||
});
|
||||
|
||||
} else {
|
||||
// Remove the category and snippets node.
|
||||
let ndxCat: number = newPackageJson.categories.indexOf(snippetsCatName);
|
||||
if (ndxCat !== -1) {
|
||||
newPackageJson.categories.splice(ndxCat, 1);
|
||||
}
|
||||
|
||||
delete newPackageJson.contributes.snippets;
|
||||
|
||||
fs.writeFile(util.getPackageJsonPath(), util.stringifyPackageJson(newPackageJson), () => {
|
||||
showReloadPrompt("Reload Window to finish disabling C++ snippets");
|
||||
});
|
||||
}
|
||||
// This only applies to the active client.
|
||||
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
|
||||
settings.update<string>("errorSquiggles", "Disabled");
|
||||
}
|
||||
|
||||
function showReloadPrompt(msg: string): void {
|
||||
let reload: string = "Reload";
|
||||
vscode.window.showInformationMessage(msg, reload).then(value => {
|
||||
if (value === reload) {
|
||||
vscode.commands.executeCommand("workbench.action.reloadWindow");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onToggleIncludeFallback(): void {
|
||||
onActivationEvent();
|
||||
// This only applies to the active client.
|
||||
@@ -426,6 +903,15 @@ 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 reportMacCrashes(): void {
|
||||
if (process.platform === "darwin") {
|
||||
prevCrashFile = "";
|
||||
@@ -471,39 +957,97 @@ function reportMacCrashes(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function handleCrashFileRead(err: NodeJS.ErrnoException, data: string): void {
|
||||
function logCrashTelemetry(data: string): void {
|
||||
let crashObject: { [key: string]: string } = {};
|
||||
if (err) {
|
||||
crashObject["readFile: err.code"] = err.code;
|
||||
telemetry.logLanguageServerEvent("MacCrash", crashObject, null);
|
||||
return;
|
||||
}
|
||||
let startCrash: number = data.indexOf(" Crashed:");
|
||||
if (startCrash < 0) {
|
||||
startCrash = 0;
|
||||
}
|
||||
let endCrash: number = data.indexOf("Thread ", startCrash);
|
||||
if (endCrash < startCrash) {
|
||||
endCrash = data.length - 1;
|
||||
}
|
||||
data = data.substr(startCrash, endCrash - startCrash);
|
||||
if (data.length > 16384) {
|
||||
data = data.substr(0, 16384) + "...";
|
||||
}
|
||||
crashObject["CrashingThreadCallStack"] = data;
|
||||
telemetry.logLanguageServerEvent("MacCrash", crashObject, null);
|
||||
}
|
||||
|
||||
function handleCrashFileRead(err: NodeJS.ErrnoException, data: string): void {
|
||||
if (err) {
|
||||
return logCrashTelemetry("readFile: " + err.code);
|
||||
}
|
||||
|
||||
// Extract the crashing thread's call stack.
|
||||
const crashStart: string = " Crashed:";
|
||||
let startCrash: number = data.indexOf(crashStart);
|
||||
if (startCrash < 0) {
|
||||
return logCrashTelemetry("No crash start");
|
||||
}
|
||||
startCrash += crashStart.length + 1; // Skip past crashStart.
|
||||
let endCrash: number = data.indexOf("Thread ", startCrash);
|
||||
if (endCrash < 0) {
|
||||
endCrash = data.length - 1; // Not expected, but just in case.
|
||||
}
|
||||
if (endCrash <= startCrash) {
|
||||
return logCrashTelemetry("No crash end");
|
||||
}
|
||||
data = data.substr(startCrash, endCrash - startCrash);
|
||||
|
||||
// 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;
|
||||
} else if (data.includes(process2)) {
|
||||
data = data.replace(new RegExp(process2, "g"), "");
|
||||
data = process2 + "\n" + data;
|
||||
} else {
|
||||
return logCrashTelemetry("No process"); // Not expected, but just in case.
|
||||
}
|
||||
|
||||
// Remove runtime lines because they can be different on different machines.
|
||||
let lines: string[] = data.split("\n");
|
||||
data = "";
|
||||
lines.forEach((line: string) => {
|
||||
if (!line.includes(".dylib") && !line.includes("???")) {
|
||||
line = line.replace(/^\d+\s+/, ""); // Remove <numbers><spaces> from the start of the line.
|
||||
line = line.replace(/std::__1::/g, "std::"); // __1:: is not helpful.
|
||||
data += (line + "\n");
|
||||
}
|
||||
});
|
||||
data = data.trimRight();
|
||||
|
||||
if (data.length > 8192) { // The API has an 8k limit.
|
||||
data = data.substr(0, 8189) + "...";
|
||||
}
|
||||
|
||||
logCrashTelemetry(data);
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> {
|
||||
console.log("deactivating extension");
|
||||
telemetry.logLanguageServerEvent("LanguageServerShutdown");
|
||||
clearInterval(intervalTimer);
|
||||
clearInterval(insiderUpdateTimer);
|
||||
disposables.forEach(d => d.dispose());
|
||||
languageConfigurations.forEach(d => d.dispose());
|
||||
ui.dispose();
|
||||
if (taskProvider) {
|
||||
taskProvider.dispose();
|
||||
}
|
||||
return clients.dispose();
|
||||
}
|
||||
|
||||
export function isFolderOpen(): boolean {
|
||||
return vscode.workspace.workspaceFolders !== undefined && vscode.workspace.workspaceFolders.length > 0;
|
||||
}
|
||||
|
||||
export function getClients(): ClientCollection {
|
||||
if (!realActivationOccurred) {
|
||||
realActivation();
|
||||
}
|
||||
return clients;
|
||||
}
|
||||
|
||||
export function getActiveClient(): Client {
|
||||
if (!realActivationOccurred) {
|
||||
realActivation();
|
||||
}
|
||||
return clients.ActiveClient;
|
||||
}
|
||||
|
||||
@@ -12,32 +12,41 @@ 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 {
|
||||
return this.defaultvalue;
|
||||
}
|
||||
}
|
||||
|
||||
// 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';
|
||||
@@ -11,26 +12,38 @@ import { Client } from './client';
|
||||
export function createProtocolFilter(me: Client, clients: ClientCollection): Middleware {
|
||||
// Disabling lint for invoke handlers
|
||||
/* tslint:disable */
|
||||
let defaultHandler: (data: any, callback: (data: any) => void) => void = (data, callback: (data) => void) => { if (clients.ActiveClient === me) { callback(data); } };
|
||||
let invoke1 = (a, callback: (a) => any) => { if (clients.ActiveClient === me) { return callback(a); } return null; };
|
||||
let invoke2 = (a, b, callback: (a, b) => any) => { if (clients.ActiveClient === me) { return callback(a, b); } return null; };
|
||||
let invoke3 = (a, b, c, callback: (a, b, c) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c); } return null; };
|
||||
let invoke4 = (a, b, c, d, callback: (a, b, c, d) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c, d); } return null; };
|
||||
let invoke5 = (a, b, c, d, e, callback: (a, b, c, d, e) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c, d, e); } return null; };
|
||||
let defaultHandler: (data: any, callback: (data: any) => void) => void = (data, callback: (data) => void) => { if (clients.ActiveClient === me) {me.notifyWhenReady(() => callback(data));}};
|
||||
let invoke1 = (a, callback: (a) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(() => callback(a)); } return null; };
|
||||
let invoke2 = (a, b, callback: (a, b) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(() => callback(a, b)); } return null; };
|
||||
let invoke3 = (a, b, c, callback: (a, b, c) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(() => callback(a, b, c)); } return null; };
|
||||
let invoke4 = (a, b, c, d, callback: (a, b, c, d) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(() => callback(a, b, c, d)); } return null; };
|
||||
let invoke5 = (a, b, c, d, e, callback: (a, b, c, d, e) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(() => callback(a, b, c, d, e)); } return null; };
|
||||
/* tslint:enable */
|
||||
|
||||
return {
|
||||
didOpen: (document, sendMessage) => {
|
||||
if (clients.checkOwnership(me, document)) {
|
||||
me.TrackedDocuments.add(document);
|
||||
sendMessage(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.provideCustomConfiguration(document).then(() => {
|
||||
sendMessage(document);
|
||||
}, () => {
|
||||
sendMessage(document);
|
||||
});
|
||||
}
|
||||
},
|
||||
didChange: defaultHandler,
|
||||
willSave: defaultHandler,
|
||||
willSaveWaitUntil: (event, sendMessage) => {
|
||||
if (clients.ActiveClient === me) {
|
||||
return sendMessage(event);
|
||||
return me.requestWhenReady(() => sendMessage(event));
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
},
|
||||
@@ -39,13 +52,18 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid
|
||||
if (clients.ActiveClient === me) {
|
||||
console.assert(me.TrackedDocuments.has(document));
|
||||
me.TrackedDocuments.delete(document);
|
||||
sendMessage(document);
|
||||
me.notifyWhenReady(() => sendMessage(document));
|
||||
}
|
||||
},
|
||||
|
||||
provideCompletionItem: invoke3,
|
||||
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,31 +36,43 @@ 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"); }
|
||||
public get autoComplete(): string { return super.Section.get<string>("autocomplete"); }
|
||||
public get loggingLevel(): string { return super.Section.get<string>("loggingLevel"); }
|
||||
public get navigationLength(): number { return super.Section.get<number>("navigation.length", 60); }
|
||||
public get autoAddFileAssociations(): boolean { return super.Section.get<boolean>("autoAddFileAssociations"); }
|
||||
public get workspaceParsingPriority(): boolean { return super.Section.get<boolean>("workspaceParsingPriority"); }
|
||||
public get workspaceSymbols(): string { return super.Section.get<string>("workspaceSymbols"); }
|
||||
public get exclusionPolicy(): boolean { return super.Section.get<boolean>("exclusionPolicy"); }
|
||||
public get commentContinuationPatterns(): (string | CommentPattern)[] { return super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); }
|
||||
public get configurationWarnings(): string { return super.Section.get<string>("configurationWarnings"); }
|
||||
public get preferredPathSeparator(): string { return super.Section.get<string>("preferredPathSeparator"); }
|
||||
public get updateChannel(): string { return super.Section.get<string>("updateChannel"); }
|
||||
public get defaultIncludePath(): string[] { return super.Section.get<string[]>("default.includePath"); }
|
||||
public get defaultDefines(): string[] { return super.Section.get<string[]>("default.defines"); }
|
||||
public get defaultMacFrameworkPath(): string[] { return super.Section.get<string[]>("default.macFrameworkPath"); }
|
||||
public get defaultWindowsSdkVersion(): string { return super.Section.get<string>("default.windowsSdkVersion"); }
|
||||
public get defaultCompileCommands(): string { return super.Section.get<string>("default.compileCommands"); }
|
||||
public get defaultForcedInclude(): string[] { return super.Section.get<string[]>("default.forcedInclude"); }
|
||||
public get defaultIntelliSenseMode(): string { return super.Section.get<string>("default.intelliSenseMode"); }
|
||||
public get defaultCompilerPath(): string { return super.Section.get<string>("default.compilerPath"); }
|
||||
public get defaultCStandard(): string { return super.Section.get<string>("default.cStandard"); }
|
||||
public get defaultCppStandard(): string { return super.Section.get<string>("default.cppStandard"); }
|
||||
public get defaultConfigurationProvider(): string { return super.Section.get<string>("default.configurationProvider"); }
|
||||
public get defaultBrowsePath(): string[] { return super.Section.get<string[]>("default.browse.path"); }
|
||||
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 toggleSetting(name: string, value1: string, value2: string): void {
|
||||
let value: string = super.Section.get<string>(name);
|
||||
@@ -81,10 +93,11 @@ 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 set filesAssociations(value: any) {
|
||||
vscode.workspace.getConfiguration("files", null).update("associations", value, vscode.ConfigurationTarget.Workspace);
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 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';
|
||||
|
||||
// TODO: share ElementId between SettingsPanel and SettingsApp. Investigate why SettingsApp cannot import/export
|
||||
const elementId: { [key: string]: string } = {
|
||||
activeConfig: "activeConfig",
|
||||
compilerPath: "compilerPath",
|
||||
intelliSenseMode: "intelliSenseMode",
|
||||
includePath: "includePath",
|
||||
defines: "defines",
|
||||
cStandard: "cStandard",
|
||||
cppStandard: "cppStandard"
|
||||
};
|
||||
|
||||
export class SettingsPanel {
|
||||
private configValues: config.Configuration;
|
||||
private isIntelliSenseModeDefined: boolean = false;
|
||||
private settingsPanelActivated = new vscode.EventEmitter<void>();
|
||||
private configValuesChanged = new vscode.EventEmitter<void>();
|
||||
private panel: vscode.WebviewPanel;
|
||||
private disposable: vscode.Disposable = undefined;
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
public createOrShow(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(activeConfiguration, errors);
|
||||
}
|
||||
|
||||
public get SettingsPanelActivated(): vscode.Event<void> {
|
||||
return this.settingsPanelActivated.event;
|
||||
}
|
||||
|
||||
public get ConfigValuesChanged(): vscode.Event<void> {
|
||||
return this.configValuesChanged.event;
|
||||
}
|
||||
|
||||
public getLastValuesFromConfigUI(): config.Configuration {
|
||||
return this.configValues;
|
||||
}
|
||||
|
||||
public updateConfigUI(configuration: config.Configuration, errors: config.ConfigurationErrors): void {
|
||||
if (this.panel) {
|
||||
this.updateWebview(configuration, errors);
|
||||
}
|
||||
}
|
||||
|
||||
public updateErrors(errors: config.ConfigurationErrors): void {
|
||||
if (this.panel) {
|
||||
this.panel.webview.postMessage({ command: 'updateErrors', errors: errors});
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
// 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(configuration: config.Configuration, errors: config.ConfigurationErrors): void {
|
||||
this.configValues = Object.assign({}, configuration); // Copy configuration values
|
||||
this.isIntelliSenseModeDefined = (this.configValues.intelliSenseMode !== undefined);
|
||||
if (this.panel) {
|
||||
// Send a message to the webview to update the values and errors
|
||||
this.panel.webview.postMessage({ command: 'updateConfig', config: this.configValues});
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private updateConfig(message: any): void {
|
||||
let entries: string[];
|
||||
|
||||
switch (message.key) {
|
||||
case elementId.activeConfig:
|
||||
this.configValues.name = message.value;
|
||||
break;
|
||||
case elementId.compilerPath:
|
||||
this.configValues.compilerPath = message.value;
|
||||
break;
|
||||
case elementId.includePath:
|
||||
entries = message.value.split("\n");
|
||||
this.configValues.includePath = entries.filter(e => e);
|
||||
break;
|
||||
case elementId.defines:
|
||||
entries = message.value.split("\n");
|
||||
this.configValues.defines = entries.filter(e => e);
|
||||
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;
|
||||
}
|
||||
|
||||
this.configValuesChanged.fire();
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { Client } from './client';
|
||||
import { getCustomConfigProviders, CustomConfigurationProviderCollection } from './customProviders';
|
||||
|
||||
let ui: UI;
|
||||
|
||||
@@ -16,11 +17,24 @@ interface KeyedQuickPickItem extends vscode.QuickPickItem {
|
||||
key: string;
|
||||
}
|
||||
|
||||
// Higher numbers mean greater priority.
|
||||
enum ConfigurationPriority {
|
||||
IncludePath = 1,
|
||||
CompileCommands = 2,
|
||||
CustomProvider = 3,
|
||||
}
|
||||
|
||||
interface ConfigurationResult {
|
||||
configured: boolean;
|
||||
priority: ConfigurationPriority;
|
||||
}
|
||||
|
||||
export class UI {
|
||||
private navigationStatusBarItem: vscode.StatusBarItem;
|
||||
private configStatusBarItem: vscode.StatusBarItem;
|
||||
private browseEngineStatusBarItem: vscode.StatusBarItem;
|
||||
private intelliSenseStatusBarItem: vscode.StatusBarItem;
|
||||
private configurationUIPromise: Thenable<ConfigurationResult>;
|
||||
|
||||
constructor() {
|
||||
// 1000 = priority, it needs to be high enough to be on the left of the Ln/Col.
|
||||
@@ -157,15 +171,43 @@ 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 => {
|
||||
if (!selection) {
|
||||
return -1;
|
||||
}
|
||||
return selection.index;
|
||||
});
|
||||
.then(selection => (selection) ? selection.index : -1);
|
||||
}
|
||||
|
||||
public showConfigurationProviders(currentProvider: string|null): Thenable<string|undefined> {
|
||||
let options: vscode.QuickPickOptions = {};
|
||||
options.placeHolder = "Select a Configuration Provider...";
|
||||
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
|
||||
|
||||
let items: KeyedQuickPickItem[] = [];
|
||||
providers.forEach(provider => {
|
||||
let label: string = provider.name;
|
||||
if (provider.extensionId === currentProvider) {
|
||||
label += " (active)";
|
||||
}
|
||||
items.push({ label: label, description: "", key: provider.extensionId });
|
||||
});
|
||||
items.push({ label: "(none)", description: "Disable the active configuration provider, if applicable.", key: "" });
|
||||
|
||||
return vscode.window.showQuickPick(items, options)
|
||||
.then(selection => (selection) ? selection.key : undefined);
|
||||
}
|
||||
|
||||
public showCompileCommands(paths: string[]): Thenable<number> {
|
||||
let options: vscode.QuickPickOptions = {};
|
||||
options.placeHolder = "Select a compile_commands.json...";
|
||||
|
||||
let items: IndexableQuickPickItem[] = [];
|
||||
for (let i: number = 0; i < paths.length; i++) {
|
||||
items.push({label: paths[i], description: "", index: i});
|
||||
}
|
||||
|
||||
return vscode.window.showQuickPick(items, options)
|
||||
.then(selection => (selection) ? selection.index : -1);
|
||||
}
|
||||
|
||||
public showWorkspaces(workspaceNames: { name: string; key: string }[]): Thenable<string> {
|
||||
@@ -176,12 +218,7 @@ export class UI {
|
||||
workspaceNames.forEach(name => items.push({ label: name.name, description: "", key: name.key }));
|
||||
|
||||
return vscode.window.showQuickPick(items, options)
|
||||
.then(selection => {
|
||||
if (!selection) {
|
||||
return "";
|
||||
}
|
||||
return selection.key;
|
||||
});
|
||||
.then(selection => (selection) ? selection.key : "");
|
||||
}
|
||||
|
||||
public showParsingCommands(): Thenable<number> {
|
||||
@@ -197,12 +234,50 @@ export class UI {
|
||||
}
|
||||
|
||||
return vscode.window.showQuickPick(items, options)
|
||||
.then(selection => {
|
||||
if (!selection) {
|
||||
return -1;
|
||||
}
|
||||
return selection.index;
|
||||
.then(selection => (selection) ? selection.index : -1);
|
||||
}
|
||||
|
||||
public showConfigureIncludePathMessage(prompt: () => Thenable<boolean>, onSkip: () => void): void {
|
||||
setTimeout(() => {
|
||||
this.showConfigurationPrompt(ConfigurationPriority.IncludePath, prompt, onSkip);
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
public showConfigureCompileCommandsMessage(prompt: () => Thenable<boolean>, onSkip: () => void): void {
|
||||
setTimeout(() => {
|
||||
this.showConfigurationPrompt(ConfigurationPriority.CompileCommands, prompt, onSkip);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
public showConfigureCustomProviderMessage(prompt: () => Thenable<boolean>, onSkip: () => void): void {
|
||||
this.showConfigurationPrompt(ConfigurationPriority.CustomProvider, prompt, onSkip);
|
||||
}
|
||||
|
||||
private showConfigurationPrompt(priority: ConfigurationPriority, prompt: () => Thenable<boolean>, onSkip: () => void): void {
|
||||
let showPrompt: () => Thenable<ConfigurationResult> = async () => {
|
||||
let configured: boolean = await prompt();
|
||||
return Promise.resolve({
|
||||
priority: priority,
|
||||
configured: configured
|
||||
});
|
||||
};
|
||||
|
||||
if (this.configurationUIPromise) {
|
||||
this.configurationUIPromise = this.configurationUIPromise.then(result => {
|
||||
if (priority > result.priority) {
|
||||
return showPrompt();
|
||||
} else if (!result.configured) {
|
||||
return showPrompt();
|
||||
}
|
||||
onSkip();
|
||||
return Promise.resolve({
|
||||
priority: result.priority,
|
||||
configured: true
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.configurationUIPromise = showPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
|
||||
+92
-78
@@ -4,93 +4,107 @@
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as url from 'url';
|
||||
import * as https from 'https';
|
||||
import { ClientRequest } from 'http';
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as util from './common';
|
||||
|
||||
import * as Telemetry from './telemetry';
|
||||
import { PersistentState } from './LanguageServer/persistentState';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const userBucketMax: number = 100;
|
||||
const userBucketString: string = "CPP.UserBucket";
|
||||
const localConfigFile: string = "cpptools.json";
|
||||
|
||||
export function activate(context: vscode.ExtensionContext): void {
|
||||
if (context.globalState.get<number>(userBucketString, -1) === -1) {
|
||||
let bucket: number = Math.floor(Math.random() * userBucketMax) + 1; // Range is [1, userBucketMax].
|
||||
context.globalState.update(userBucketString, bucket);
|
||||
}
|
||||
interface Settings {
|
||||
defaultIntelliSenseEngine?: number;
|
||||
recursiveIncludes?: number;
|
||||
gotoDefIntelliSense?: number;
|
||||
}
|
||||
|
||||
export class ABTestSettings {
|
||||
private settings: Settings;
|
||||
private intelliSenseEngineDefault: PersistentState<number>;
|
||||
private recursiveIncludesDefault: PersistentState<number>;
|
||||
private gotoDefIntelliSenseDefault: 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.settings = {
|
||||
defaultIntelliSenseEngine: this.intelliSenseEngineDefault.Value,
|
||||
recursiveIncludes: this.recursiveIncludesDefault.Value,
|
||||
gotoDefIntelliSense: this.gotoDefIntelliSenseDefault.Value
|
||||
};
|
||||
this.bucket = new PersistentState<number>(userBucketString, -1);
|
||||
if (this.bucket.Value === -1) {
|
||||
this.bucket.Value = Math.floor(Math.random() * userBucketMax) + 1; // Range is [1, userBucketMax].
|
||||
}
|
||||
|
||||
this.updateSettings();
|
||||
// Redownload cpptools.json after initialization so it's not blocked.
|
||||
// It'll be used the next time the extension reloads.
|
||||
this.downloadCpptoolsJsonPkgAsync();
|
||||
|
||||
setInterval(() => {
|
||||
// Redownload occasionally to prevent an extra reload during long sessions.
|
||||
downloadCpptoolsJsonPkg();
|
||||
}, 30 * 60 * 1000); // 30 minutes.
|
||||
}
|
||||
setInterval(() => { this.downloadCpptoolsJsonPkgAsync(); }, 30 * 60 * 1000); // 30 minutes.
|
||||
}
|
||||
|
||||
// NOTE: Code is copied from DownloadPackage in packageManager.ts, but with ~75% fewer lines.
|
||||
function downloadCpptoolsJson(urlString): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
let parsedUrl: url.Url = url.parse(urlString);
|
||||
let request: ClientRequest = https.request({
|
||||
host: parsedUrl.host,
|
||||
path: parsedUrl.path,
|
||||
agent: util.getHttpsProxyAgent(),
|
||||
rejectUnauthorized: vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true)
|
||||
}, (response) => {
|
||||
if (response.statusCode === 301 || response.statusCode === 302) {
|
||||
let redirectUrl: string | string[];
|
||||
if (typeof response.headers.location === "string") {
|
||||
redirectUrl = response.headers.location;
|
||||
} else {
|
||||
redirectUrl = response.headers.location[0];
|
||||
}
|
||||
return resolve(downloadCpptoolsJson(redirectUrl)); // Redirect - download from new location
|
||||
public get UseDefaultIntelliSenseEngine(): boolean {
|
||||
return util.isNumber(this.settings.defaultIntelliSenseEngine) ? this.settings.defaultIntelliSenseEngine >= this.bucket.Value : true;
|
||||
}
|
||||
|
||||
public get UseRecursiveIncludes(): boolean {
|
||||
return util.isNumber(this.settings.recursiveIncludes) ? this.settings.recursiveIncludes >= this.bucket.Value : true;
|
||||
}
|
||||
|
||||
public get UseGoToDefIntelliSense(): boolean {
|
||||
return util.isNumber(this.settings.gotoDefIntelliSense) ? this.settings.gotoDefIntelliSense >= this.bucket.Value : true;
|
||||
}
|
||||
|
||||
private updateSettings(): void {
|
||||
const cpptoolsJsonFile: string = util.getExtensionFilePath(localConfigFile);
|
||||
|
||||
try {
|
||||
const exists: boolean = fs.existsSync(cpptoolsJsonFile);
|
||||
if (exists) {
|
||||
const fileContent: string = fs.readFileSync(cpptoolsJsonFile).toString();
|
||||
let newSettings: Settings = <Settings>JSON.parse(fileContent);
|
||||
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.settings = {
|
||||
defaultIntelliSenseEngine: this.intelliSenseEngineDefault.Value,
|
||||
recursiveIncludes: this.recursiveIncludesDefault.Value,
|
||||
gotoDefIntelliSense: this.gotoDefIntelliSenseDefault.Value
|
||||
};
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
return reject();
|
||||
}
|
||||
let downloadedBytes = 0; // tslint:disable-line
|
||||
let cppToolsJsonFile: fs.WriteStream = fs.createWriteStream(util.getExtensionFilePath("cpptools.json"));
|
||||
response.on('data', (data) => { downloadedBytes += data.length; });
|
||||
response.on('end', () => { cppToolsJsonFile.close(); });
|
||||
cppToolsJsonFile.on('close', () => { resolve(); });
|
||||
response.on('error', (error) => { reject(); });
|
||||
response.pipe(cppToolsJsonFile, { end: false });
|
||||
});
|
||||
request.on('error', (error) => { reject(); });
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
export function downloadCpptoolsJsonPkg(): Promise<void> {
|
||||
let hasError: boolean = false;
|
||||
let telemetryProperties: { [key: string]: string } = {};
|
||||
return downloadCpptoolsJson("https://go.microsoft.com/fwlink/?linkid=852750")
|
||||
.catch((error) => {
|
||||
// More specific error info is not likely to be helpful, and we get detailed download data from the initial install.
|
||||
hasError = true;
|
||||
})
|
||||
.then(() => {
|
||||
telemetryProperties['success'] = (!hasError).toString();
|
||||
Telemetry.logDebuggerEvent("cpptoolsJsonDownload", telemetryProperties);
|
||||
});
|
||||
}
|
||||
|
||||
export function processCpptoolsJson(cpptoolsString: string): Promise<void> {
|
||||
let cpptoolsObject: any = JSON.parse(cpptoolsString);
|
||||
let intelliSenseEnginePercentage: number = cpptoolsObject.intelliSenseEngine_default_percentage;
|
||||
let packageJson: any = util.getRawPackageJson();
|
||||
|
||||
if (!packageJson.extensionFolderPath.includes(".vscode-insiders")) {
|
||||
let prevIntelliSenseEngineDefault: any = packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default;
|
||||
if (util.extensionContext.globalState.get<number>(userBucketString, userBucketMax + 1) <= intelliSenseEnginePercentage) {
|
||||
packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default = "Default";
|
||||
} else {
|
||||
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));
|
||||
} catch (error) {
|
||||
// Ignore any cpptoolsJsonFile errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private downloadCpptoolsJsonPkgAsync(): Promise<void> {
|
||||
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)
|
||||
.catch((error) => {
|
||||
// More specific error info is not likely to be helpful, and we get detailed download data from the initial install.
|
||||
hasError = true;
|
||||
})
|
||||
.then(() => {
|
||||
this.updateSettings();
|
||||
telemetryProperties['success'] = (!hasError).toString();
|
||||
Telemetry.logDebuggerEvent("cpptoolsJsonDownload", telemetryProperties);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let settings: ABTestSettings;
|
||||
|
||||
export function getABTestSettings(): ABTestSettings {
|
||||
if (!settings) {
|
||||
settings = new ABTestSettings();
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -6,29 +6,35 @@
|
||||
|
||||
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 = 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.ToggleSnippets",
|
||||
"C_Cpp.ShowReleaseNotes",
|
||||
"C_Cpp.ResetDatabase",
|
||||
"C_Cpp.PauseParsing",
|
||||
"C_Cpp.ResumeParsing",
|
||||
"C_Cpp.ShowParsingCommands",
|
||||
"C_Cpp.TakeSurvey"
|
||||
"C_Cpp.TakeSurvey",
|
||||
"C_Cpp.LogDiagnostics"
|
||||
];
|
||||
|
||||
constructor() {
|
||||
@@ -36,26 +42,44 @@ 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 {
|
||||
this.tempCommands.push(vscode.commands.registerCommand(command, () => {
|
||||
if (this.isLanguageServerDisabled) {
|
||||
vscode.window.showInformationMessage("The command is disabled because \"C_Cpp.intelliSenseEngine\" is set to \"Disabled\".");
|
||||
return;
|
||||
}
|
||||
this.delayedCommandsToExecute.add(command);
|
||||
if (this.isActivationReady) {
|
||||
LanguageServer.activate(true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public disableLanguageServer(): void {
|
||||
this.isLanguageServerDisabled = true;
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
+393
-59
@@ -14,11 +14,22 @@ import * as url from 'url';
|
||||
import { PlatformInformation } from './platform';
|
||||
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;
|
||||
@@ -34,6 +45,64 @@ 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);
|
||||
}
|
||||
|
||||
// This function is used to stringify the rawPackageJson.
|
||||
// Do not use with util.packageJson or else the expanded
|
||||
// package.json will be written back.
|
||||
@@ -42,13 +111,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");
|
||||
@@ -57,6 +135,32 @@ export function getVcpkgPathDescriptorFile(): string {
|
||||
}
|
||||
}
|
||||
|
||||
let vcpkgRoot: string;
|
||||
export function getVcpkgRoot(): string {
|
||||
if (!vcpkgRoot && vcpkgRoot !== "") {
|
||||
vcpkgRoot = "";
|
||||
// Check for vcpkg instance.
|
||||
if (fs.existsSync(getVcpkgPathDescriptorFile())) {
|
||||
let vcpkgRootTemp: string = fs.readFileSync(getVcpkgPathDescriptorFile()).toString();
|
||||
vcpkgRootTemp = vcpkgRootTemp.trim();
|
||||
if (fs.existsSync(vcpkgRootTemp)) {
|
||||
vcpkgRoot = path.join(vcpkgRootTemp, "/installed").replace(/\\/g, "/");
|
||||
}
|
||||
}
|
||||
}
|
||||
return vcpkgRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a fuzzy determination of whether a uri represents a header file.
|
||||
* 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(uri: vscode.Uri): boolean {
|
||||
let ext: string = path.extname(uri.fsPath);
|
||||
return !ext || ext.startsWith(".h") || ext.startsWith(".H");
|
||||
}
|
||||
|
||||
// Extension is ready if install.lock exists and debugAdapters folder exist.
|
||||
export async function isExtensionReady(): Promise<boolean> {
|
||||
const doesInstallLockFileExist: boolean = await checkInstallLockFile();
|
||||
@@ -96,15 +200,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;
|
||||
@@ -121,7 +225,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;
|
||||
@@ -139,8 +243,48 @@ export function getProgressExecutableSuccess(): number { return progressExecutab
|
||||
export function getProgressParseRootSuccess(): number { return progressParseRootSuccess; } // Parse root was successful (i.e. not blocked by processing taking too long).
|
||||
export function getProgressIntelliSenseNoSquiggles(): number { return progressIntelliSenseNoSquiggles; } // IntelliSense was successful and the user got no squiggles.
|
||||
|
||||
export function showReleaseNotes(): void {
|
||||
vscode.commands.executeCommand('vscode.previewHtml', vscode.Uri.file(getExtensionFilePath("ReleaseNotes.html")), vscode.ViewColumn.One, "C/C++ Extension Release Notes");
|
||||
let releaseNotesPanel: vscode.WebviewPanel = undefined;
|
||||
|
||||
export async function showReleaseNotes(): Promise<void> {
|
||||
if (releaseNotesPanel) {
|
||||
releaseNotesPanel.reveal();
|
||||
} else {
|
||||
releaseNotesPanel = vscode.window.createWebviewPanel('releaseNotes', "C/C++ Extension Release Notes", vscode.ViewColumn.One);
|
||||
releaseNotesPanel.webview.html = await readFileText(getExtensionFilePath("ReleaseNotes.html"));
|
||||
releaseNotesPanel.onDidDispose(() => releaseNotesPanel = undefined, null, extensionContext.subscriptions);
|
||||
}
|
||||
}
|
||||
|
||||
export function isUri(input: any): input is vscode.Uri {
|
||||
return input && input instanceof vscode.Uri;
|
||||
}
|
||||
|
||||
export function isString(input: any): input is string {
|
||||
return typeof(input) === "string";
|
||||
}
|
||||
|
||||
export function isNumber(input: any): input is number {
|
||||
return typeof(input) === "number";
|
||||
}
|
||||
|
||||
export function isBoolean(input: any): input is boolean {
|
||||
return typeof(input) === "boolean";
|
||||
}
|
||||
|
||||
export function isArray(input: any): input is any[] {
|
||||
return input instanceof Array;
|
||||
}
|
||||
|
||||
export function isOptionalString(input: any): input is string|undefined {
|
||||
return input === undefined || isString(input);
|
||||
}
|
||||
|
||||
export function isArrayOfString(input: any): input is string[] {
|
||||
return isArray(input) && input.every(item => isString(item));
|
||||
}
|
||||
|
||||
export function isOptionalArrayOfString(input: any): input is string[]|undefined {
|
||||
return input === undefined || isArrayOfString(input);
|
||||
}
|
||||
|
||||
export function resolveVariables(input: string, additionalEnvironment: {[key: string]: string | string[]}): string {
|
||||
@@ -152,55 +296,60 @@ export function resolveVariables(input: string, additionalEnvironment: {[key: st
|
||||
}
|
||||
|
||||
// Replace environment and configuration variables.
|
||||
let regexp: RegExp = /\$\{((env|config|workspaceFolder)(.|:))?(.*?)\}/g;
|
||||
let ret: string = input.replace(regexp, (match: string, ignored1: string, varType: string, ignored2: string, name: string) => {
|
||||
// Historically, if the variable didn't have anything before the "." or ":"
|
||||
// it was assumed to be an environment variable
|
||||
if (varType === undefined) {
|
||||
varType = "env";
|
||||
}
|
||||
let newValue: string = undefined;
|
||||
switch (varType) {
|
||||
case "env": {
|
||||
let v: string | string[] = additionalEnvironment[name];
|
||||
if (typeof v === "string") {
|
||||
newValue = v;
|
||||
} else if (input === match && v instanceof Array) {
|
||||
newValue = v.join(";");
|
||||
}
|
||||
if (!newValue) {
|
||||
newValue = process.env[name];
|
||||
}
|
||||
break;
|
||||
let regexp: () => RegExp = () => /\$\{((env|config|workspaceFolder)(\.|:))?(.*?)\}/g;
|
||||
let ret: string = input;
|
||||
let cycleCache: Set<string> = new Set();
|
||||
while (!cycleCache.has(ret)) {
|
||||
cycleCache.add(ret);
|
||||
ret = ret.replace(regexp(), (match: string, ignored1: string, varType: string, ignored2: string, name: string) => {
|
||||
// Historically, if the variable didn't have anything before the "." or ":"
|
||||
// it was assumed to be an environment variable
|
||||
if (varType === undefined) {
|
||||
varType = "env";
|
||||
}
|
||||
case "config": {
|
||||
let config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
|
||||
let keys: string[] = name.split('.');
|
||||
keys.forEach((key: string) => { config = (config) ? config.get(key) : config; });
|
||||
newValue = (config) ? config.toString() : undefined;
|
||||
break;
|
||||
}
|
||||
case "workspaceFolder": {
|
||||
// Only replace ${workspaceFolder:name} variables for now.
|
||||
// We may consider doing replacement of ${workspaceFolder} here later, but we would have to update the language server and also
|
||||
// intercept messages with paths in them and add the ${workspaceFolder} variable back in (e.g. for light bulb suggestions)
|
||||
if (name && vscode.workspace && vscode.workspace.workspaceFolders) {
|
||||
let folder: vscode.WorkspaceFolder = vscode.workspace.workspaceFolders.find(folder => folder.name.toLocaleLowerCase() === name.toLocaleLowerCase());
|
||||
if (folder) {
|
||||
newValue = folder.uri.fsPath;
|
||||
let newValue: string;
|
||||
switch (varType) {
|
||||
case "env": {
|
||||
let v: string | string[] = additionalEnvironment[name];
|
||||
if (isString(v)) {
|
||||
newValue = v;
|
||||
} else if (input === match && isArrayOfString(v)) {
|
||||
newValue = v.join(";");
|
||||
}
|
||||
if (!isString(newValue)) {
|
||||
newValue = process.env[name];
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "config": {
|
||||
let config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
|
||||
if (config) {
|
||||
newValue = config.get<string>(name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "workspaceFolder": {
|
||||
// Only replace ${workspaceFolder:name} variables for now.
|
||||
// We may consider doing replacement of ${workspaceFolder} here later, but we would have to update the language server and also
|
||||
// intercept messages with paths in them and add the ${workspaceFolder} variable back in (e.g. for light bulb suggestions)
|
||||
if (name && vscode.workspace && vscode.workspace.workspaceFolders) {
|
||||
let folder: vscode.WorkspaceFolder = vscode.workspace.workspaceFolders.find(folder => folder.name.toLocaleLowerCase() === name.toLocaleLowerCase());
|
||||
if (folder) {
|
||||
newValue = folder.uri.fsPath;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { assert.fail("unknown varType matched"); }
|
||||
}
|
||||
default: { assert.fail("unknown varType matched"); }
|
||||
}
|
||||
return (newValue) ? newValue : match;
|
||||
});
|
||||
return (isString(newValue)) ? newValue : match;
|
||||
});
|
||||
}
|
||||
|
||||
// Resolve '~' at the start of the path.
|
||||
regexp = /^\~/g;
|
||||
ret = ret.replace(regexp, (match: string, name: string) => {
|
||||
let newValue: string = process.env.HOME;
|
||||
regexp = () => /^\~/g;
|
||||
ret = ret.replace(regexp(), (match: string, name: string) => {
|
||||
let newValue: string = (process.platform === 'win32') ? process.env.USERPROFILE : process.env.HOME;
|
||||
return (newValue) ? newValue : match;
|
||||
});
|
||||
|
||||
@@ -277,7 +426,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);
|
||||
}
|
||||
@@ -313,6 +462,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) => {
|
||||
@@ -333,10 +499,9 @@ export function readFileText(filePath: string, encoding: string = "utf8"): Promi
|
||||
fs.readFile(filePath, encoding, (err, data) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -347,14 +512,29 @@ export function writeFileText(filePath: string, content: string, encoding: strin
|
||||
fs.writeFile(filePath, content, { encoding }, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteFile(filePath: string): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlink(filePath, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get the path of the lock file. This is used to indicate that the platform-specific dependencies have been downloaded.
|
||||
export function getInstallLockPath(): string {
|
||||
return getExtensionFilePath("install.lock");
|
||||
@@ -362,7 +542,7 @@ export function getInstallLockPath(): string {
|
||||
|
||||
export function getReadmeMessage(): string {
|
||||
const readmePath: string = getExtensionFilePath("README.md");
|
||||
const readmeMessage: string = `Please refer to ${readmePath} for troubleshooting information. Issues can be created at https://github.com/Microsoft/vscppsamples/issues`;
|
||||
const readmeMessage: string = `Please refer to ${readmePath} for troubleshooting information. Issues can be created at https://github.com/Microsoft/vscode-cpptools/issues`;
|
||||
return readmeMessage;
|
||||
}
|
||||
|
||||
@@ -502,4 +682,158 @@ export async function renamePromise(oldName: string, newName: string): Promise<v
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function promptForReloadWindowDueToSettingsChange(): void {
|
||||
promptReloadWindow("Reload the workspace for the settings change to take effect.");
|
||||
}
|
||||
|
||||
export function promptReloadWindow(message: string): void {
|
||||
let reload: string = "Reload";
|
||||
vscode.window.showInformationMessage(message, reload).then((value: string) => {
|
||||
if (value === reload) {
|
||||
vscode.commands.executeCommand("workbench.action.reloadWindow");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function downloadFileToDestination(urlStr: string, destinationPath: string, headers?: OutgoingHttpHeaders): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
let parsedUrl: url.Url = url.parse(urlStr);
|
||||
let request: ClientRequest = https.request({
|
||||
host: parsedUrl.host,
|
||||
path: parsedUrl.path,
|
||||
agent: getHttpsProxyAgent(),
|
||||
rejectUnauthorized: vscode.workspace.getConfiguration().get('http.proxyStrictSSL', true),
|
||||
headers: headers
|
||||
}, (response) => {
|
||||
if (response.statusCode === 301 || response.statusCode === 302) { // If redirected
|
||||
// Download from new location
|
||||
let redirectUrl: string;
|
||||
if (typeof response.headers.location === 'string') {
|
||||
redirectUrl = response.headers.location;
|
||||
} else {
|
||||
redirectUrl = response.headers.location[0];
|
||||
}
|
||||
return resolve(downloadFileToDestination(redirectUrl, destinationPath, headers));
|
||||
}
|
||||
if (response.statusCode !== 200) { // If request is not successful
|
||||
return reject();
|
||||
}
|
||||
// Write file using downloaded data
|
||||
let createdFile: fs.WriteStream = fs.createWriteStream(destinationPath);
|
||||
createdFile.on('finish', () => { resolve(); });
|
||||
response.on('error', (error) => { reject(error); });
|
||||
response.pipe(createdFile);
|
||||
});
|
||||
request.on('error', (error) => { reject(error); });
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
export function downloadFileToStr(urlStr: string, headers?: OutgoingHttpHeaders): Promise<any> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
let parsedUrl: url.Url = url.parse(urlStr);
|
||||
let request: ClientRequest = https.request({
|
||||
host: parsedUrl.host,
|
||||
path: parsedUrl.path,
|
||||
agent: getHttpsProxyAgent(),
|
||||
rejectUnauthorized: vscode.workspace.getConfiguration().get('http.proxyStrictSSL', true),
|
||||
headers: headers
|
||||
}, (response) => {
|
||||
if (response.statusCode === 301 || response.statusCode === 302) { // If redirected
|
||||
// Download from new location
|
||||
let redirectUrl: string;
|
||||
if (typeof response.headers.location === 'string') {
|
||||
redirectUrl = response.headers.location;
|
||||
} else {
|
||||
redirectUrl = response.headers.location[0];
|
||||
}
|
||||
return resolve(downloadFileToStr(redirectUrl, headers));
|
||||
}
|
||||
if (response.statusCode !== 200) { // If request is not successful
|
||||
return reject();
|
||||
}
|
||||
let downloadedData: string = '';
|
||||
response.on('data', (data) => { downloadedData += data; });
|
||||
response.on('error', (error) => { reject(error); });
|
||||
response.on('end', () => { resolve(downloadedData); });
|
||||
});
|
||||
request.on('error', (error) => { reject(error); });
|
||||
request.end();
|
||||
});
|
||||
}
|
||||
|
||||
export interface CompilerPathAndArgs {
|
||||
compilerPath: string;
|
||||
additionalArgs: string[];
|
||||
}
|
||||
|
||||
export function extractCompilerPathAndArgs(inputCompilerPath: string): CompilerPathAndArgs {
|
||||
let compilerPath: string = inputCompilerPath;
|
||||
let additionalArgs: string[];
|
||||
let isWindows: boolean = os.platform() === 'win32';
|
||||
if (compilerPath) {
|
||||
if (compilerPath.startsWith("\"")) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return { compilerPath, 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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import { CustomConfigurationProvider, Version } from 'vscode-cpptools';
|
||||
import { CppToolsTestApi, CppToolsTestHook } from 'vscode-cpptools/out/testApi';
|
||||
import { CustomConfigurationProvider1, getCustomConfigProviders, CustomConfigurationProviderCollection } from './LanguageServer/customProviders';
|
||||
import { getOutputChannel } from './logger';
|
||||
import * as LanguageServer from './LanguageServer/extension';
|
||||
import * as test from './testHook';
|
||||
|
||||
export class CppTools implements CppToolsTestApi {
|
||||
private version: Version;
|
||||
private providers: CustomConfigurationProvider1[] = [];
|
||||
private failedRegistrations: CustomConfigurationProvider[] = [];
|
||||
private timers = new Map<string, NodeJS.Timer>();
|
||||
|
||||
constructor(version: Version) {
|
||||
if (version > Version.latest) {
|
||||
console.warn(`version ${version} is not supported by this version of cpptools`);
|
||||
console.warn(` using ${Version.latest} instead`);
|
||||
version = Version.latest;
|
||||
}
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
private addNotifyReadyTimer(provider: CustomConfigurationProvider1): void {
|
||||
if (this.version >= Version.v2) {
|
||||
const timeout: number = 30;
|
||||
let timer: NodeJS.Timer = setTimeout(() => {
|
||||
console.warn(`registered provider ${provider.extensionId} did not call 'notifyReady' within ${timeout} seconds`);
|
||||
}, timeout * 1000);
|
||||
this.timers.set(provider.extensionId, timer);
|
||||
}
|
||||
}
|
||||
|
||||
private removeNotifyReadyTimer(provider: CustomConfigurationProvider1): void {
|
||||
if (this.version >= Version.v2) {
|
||||
let timer: NodeJS.Timer = this.timers.get(provider.extensionId);
|
||||
if (timer) {
|
||||
this.timers.delete(provider.extensionId);
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getVersion(): Version {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public registerCustomConfigurationProvider(provider: CustomConfigurationProvider): void {
|
||||
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
|
||||
if (providers.add(provider, this.version)) {
|
||||
let added: CustomConfigurationProvider1 = providers.get(provider);
|
||||
getOutputChannel().appendLine(`Custom configuration provider '${added.name}' registered`);
|
||||
this.providers.push(added);
|
||||
LanguageServer.getClients().forEach(client => client.onRegisterCustomConfigurationProvider(added));
|
||||
this.addNotifyReadyTimer(added);
|
||||
} else {
|
||||
this.failedRegistrations.push(provider);
|
||||
}
|
||||
}
|
||||
|
||||
public notifyReady(provider: CustomConfigurationProvider): void {
|
||||
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
|
||||
let p: CustomConfigurationProvider1 = providers.get(provider);
|
||||
|
||||
if (p) {
|
||||
this.removeNotifyReadyTimer(p);
|
||||
p.isReady = true;
|
||||
LanguageServer.getClients().forEach(client => {
|
||||
client.updateCustomConfigurations(p);
|
||||
client.updateCustomBrowseConfiguration(p);
|
||||
});
|
||||
} else if (this.failedRegistrations.find(p => p === provider)) {
|
||||
console.warn("provider not successfully registered, 'notifyReady' ignored");
|
||||
} else {
|
||||
console.warn("provider should be registered before signaling it's ready to provide configurations");
|
||||
}
|
||||
}
|
||||
|
||||
public didChangeCustomConfiguration(provider: CustomConfigurationProvider): void {
|
||||
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
|
||||
let p: CustomConfigurationProvider1 = providers.get(provider);
|
||||
|
||||
if (p) {
|
||||
if (!p.isReady) {
|
||||
console.warn("didChangeCustomConfiguration was invoked before notifyReady");
|
||||
}
|
||||
LanguageServer.getClients().forEach(client => client.updateCustomConfigurations(p));
|
||||
} else if (this.failedRegistrations.find(p => p === provider)) {
|
||||
console.warn("provider not successfully registered, 'didChangeCustomConfiguration' ignored");
|
||||
} else {
|
||||
console.warn("provider should be registered before sending config change messages");
|
||||
}
|
||||
}
|
||||
|
||||
public didChangeCustomBrowseConfiguration(provider: CustomConfigurationProvider): void {
|
||||
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
|
||||
let p: CustomConfigurationProvider1 = providers.get(provider);
|
||||
|
||||
if (p) {
|
||||
LanguageServer.getClients().forEach(client => client.updateCustomBrowseConfiguration(p));
|
||||
} else if (this.failedRegistrations.find(p => p === provider)) {
|
||||
console.warn("provider not successfully registered, 'didChangeCustomBrowseConfiguration' ignored");
|
||||
} else {
|
||||
console.warn("provider should be registered before sending config change messages");
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.providers.forEach(provider => {
|
||||
getCustomConfigProviders().remove(provider);
|
||||
provider.dispose();
|
||||
});
|
||||
this.providers = [];
|
||||
}
|
||||
|
||||
public getTestHook(): CppToolsTestHook {
|
||||
return test.getTestHook();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import { CustomConfigurationProvider, Version, CppToolsApi } from 'vscode-cpptools';
|
||||
import { CppToolsTestApi, CppToolsTestHook, CppToolsTestExtension } from 'vscode-cpptools/out/testApi';
|
||||
import { CppTools } from './cppTools';
|
||||
|
||||
/**
|
||||
* This class implements both interfaces since the extension returned CppToolsApi for v0,
|
||||
* but returns CppToolsTestExtension for v1 and later.
|
||||
*/
|
||||
export class CppTools1 implements CppToolsTestApi, CppToolsTestExtension {
|
||||
private backupApi: CppTools;
|
||||
|
||||
private get BackupApi(): CppToolsTestApi {
|
||||
if (!this.backupApi) {
|
||||
this.backupApi = new CppTools(Version.v0);
|
||||
}
|
||||
return this.backupApi;
|
||||
}
|
||||
|
||||
getApi(version: Version): CppToolsApi {
|
||||
switch (version) {
|
||||
case Version.v0:
|
||||
return this.BackupApi;
|
||||
|
||||
default:
|
||||
return new CppTools(version);
|
||||
}
|
||||
}
|
||||
|
||||
getTestApi(version: Version): CppToolsTestApi {
|
||||
return <CppToolsTestApi>this.getApi(version);
|
||||
}
|
||||
|
||||
getVersion(): Version {
|
||||
return this.BackupApi.getVersion();
|
||||
}
|
||||
|
||||
registerCustomConfigurationProvider(provider: CustomConfigurationProvider): void {
|
||||
this.BackupApi.registerCustomConfigurationProvider(provider);
|
||||
}
|
||||
|
||||
notifyReady(provider: CustomConfigurationProvider): void {
|
||||
this.BackupApi.notifyReady(provider);
|
||||
}
|
||||
|
||||
didChangeCustomConfiguration(provider: CustomConfigurationProvider): void {
|
||||
this.BackupApi.didChangeCustomConfiguration(provider);
|
||||
}
|
||||
|
||||
didChangeCustomBrowseConfiguration(provider: CustomConfigurationProvider): void {
|
||||
this.BackupApi.didChangeCustomBrowseConfiguration(provider);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
}
|
||||
|
||||
getTestHook(): CppToolsTestHook {
|
||||
return this.BackupApi.getTestHook();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import { PackageVersion } from './packageVersion';
|
||||
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.
|
||||
*/
|
||||
interface Asset {
|
||||
name: string;
|
||||
browser_download_url: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The object representation of a release in the GitHub API's release JSON.
|
||||
* Named Build so as to reduce confusion between a "Release" release and "Insiders" release.
|
||||
*/
|
||||
interface Build {
|
||||
name: string;
|
||||
assets: Asset[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search each Asset by name to retrieve the download URL for a VSIX package
|
||||
* @param vsixName The name of the VSIX to search for
|
||||
* @return The download URL of the VSIX
|
||||
*/
|
||||
function getVsixDownloadUrl(build: Build, vsixName: string): string {
|
||||
const downloadUrl: string = build.assets.find(asset => {
|
||||
return asset.name === vsixName;
|
||||
}).browser_download_url;
|
||||
if (!downloadUrl) {
|
||||
throw new Error('Failed to find VSIX: ' + vsixName + ' in build: ' + build.name);
|
||||
}
|
||||
return downloadUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an object is of type Asset.
|
||||
* @param input Incoming object.
|
||||
* @return Whether input is of type Asset.
|
||||
*/
|
||||
function isAsset(input: any): input is Asset {
|
||||
return input && input.name && typeof(input.name) === "string" &&
|
||||
input.browser_download_url && typeof(input.browser_download_url) === "string";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an object is of type Build. Note that earlier releases of the extension
|
||||
* do not have 4 or greater Assets (Mac, Win, Linux 32/64). Only call this on more recent Builds.
|
||||
* @param input Incoming object.
|
||||
* @return Whether input is of type Build.
|
||||
*/
|
||||
function isBuild(input: any): input is Build {
|
||||
return input && input.name && typeof(input.name) === "string" && isArrayOfAssets(input.assets) && input.assets.length >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an object is of type Asset[].
|
||||
* @param input Incoming object.
|
||||
* @return Whether input is of type Asset[].
|
||||
*/
|
||||
function isArrayOfAssets(input: any): input is Asset[] {
|
||||
return input instanceof Array && input.every(item => isAsset(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an object is of type Build[].
|
||||
* @param input Incoming object.
|
||||
* @return Whether input is of type Build[].
|
||||
*/
|
||||
function isArrayOfBuilds(input: any): input is Build[] {
|
||||
if (!input || !(input instanceof Array) || input.length === 0) {
|
||||
return false;
|
||||
}
|
||||
// Only check the five most recent builds for validity -- no need to check all of them
|
||||
for (let i: number = 0; i < 5 && i < input.length; i++) {
|
||||
if (!isBuild(input[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the user's platform information to the VSIX name relevant to them.
|
||||
* @param info Information about the user's operating system.
|
||||
* @return VSIX filename for the extension's releases matched to the user's platform.
|
||||
*/
|
||||
function vsixNameForPlatform(info: PlatformInformation): string {
|
||||
const vsixName: string = function(platformInfo): string {
|
||||
switch (platformInfo.platform) {
|
||||
case 'win32': return 'cpptools-win32.vsix';
|
||||
case 'darwin': return 'cpptools-osx.vsix';
|
||||
default: {
|
||||
switch (platformInfo.architecture) {
|
||||
case 'x86_64': return 'cpptools-linux.vsix';
|
||||
case 'x86':
|
||||
case 'i386':
|
||||
case 'i686': return 'cpptools-linux32.vsix';
|
||||
}
|
||||
}
|
||||
}
|
||||
}(info);
|
||||
if (!vsixName) {
|
||||
throw new Error('Failed to match VSIX name for: ' + info.platform + ':' + info.architecture);
|
||||
}
|
||||
return vsixName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for return value of getTargetBuildInfo containing the download URL and version of a Build.
|
||||
*/
|
||||
export interface BuildInfo {
|
||||
downloadUrl: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the GitHub API to retrieve the download URL of the extension version the user should update to, if any.
|
||||
* @param updateChannel The user's updateChannel setting.
|
||||
* @return Download URL for the extension VSIX package that the user should install. If the user
|
||||
* does not need to update, resolves to undefined.
|
||||
*/
|
||||
export async function getTargetBuildInfo(updateChannel: string): Promise<BuildInfo> {
|
||||
return getReleaseJson()
|
||||
.then(builds => {
|
||||
if (!builds || builds.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// If the user version is greater than or incomparable to the latest available verion then there is no need to update
|
||||
// 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 (!testingInsidersVsixInstall && (userVersion.isGreaterThan(latestVersion) || (userVersion.suffix && userVersion.suffix !== 'insiders'))) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getTargetBuild(builds, userVersion, updateChannel);
|
||||
})
|
||||
.then(async build => {
|
||||
if (!build) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
try {
|
||||
const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation();
|
||||
const vsixName: string = vsixNameForPlatform(platformInfo);
|
||||
const downloadUrl: string = getVsixDownloadUrl(build, vsixName);
|
||||
return { downloadUrl: downloadUrl, name: build.name };
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether there exists a Build in the given Build[] that should be installed.
|
||||
* @param builds The GitHub release list parsed as an array of Builds.
|
||||
* @param userVersion The verion of the extension that the user is running.
|
||||
* @param updateChannel The user's updateChannel setting.
|
||||
* @return The Build if the user should update to it, otherwise undefined.
|
||||
*/
|
||||
function getTargetBuild(builds: Build[], userVersion: PackageVersion, updateChannel: string): Build {
|
||||
// Get predicates to determine the build to install, if any
|
||||
let needsUpdate: (installed: PackageVersion, target: PackageVersion) => boolean;
|
||||
let useBuild: (build: Build) => boolean;
|
||||
if (updateChannel === 'Insiders') {
|
||||
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); };
|
||||
useBuild = (build: Build): boolean => { return build.name.indexOf('-') === -1; };
|
||||
} else {
|
||||
throw new Error('Incorrect updateChannel setting provided');
|
||||
}
|
||||
|
||||
// Get the build to install
|
||||
const targetBuild: Build = builds.find((build) => useBuild(build));
|
||||
if (!targetBuild) {
|
||||
throw new Error('Failed to determine installation candidate');
|
||||
}
|
||||
|
||||
// Check current version against target's version to determine if the installation should happen
|
||||
const targetVersion: PackageVersion = new PackageVersion(targetBuild.name);
|
||||
if (needsUpdate(userVersion, targetVersion)) {
|
||||
return targetBuild;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
interface Rate {
|
||||
remaining: number;
|
||||
}
|
||||
|
||||
interface RateLimit {
|
||||
rate: Rate;
|
||||
}
|
||||
|
||||
function isRate(input: any): input is Rate {
|
||||
return input && util.isNumber(input.remaining);
|
||||
}
|
||||
|
||||
function isRateLimit(input: any): input is RateLimit {
|
||||
return input && isRate(input.rate);
|
||||
}
|
||||
|
||||
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 && error.code && error.code !== "ENOENT") {
|
||||
// Only throw if the user is connected to the Internet.
|
||||
throw new Error('Failed to download rate limit JSON');
|
||||
}
|
||||
});
|
||||
if (!data) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let rateLimit: any;
|
||||
try {
|
||||
rateLimit = JSON.parse(data);
|
||||
} catch (error) {
|
||||
throw new Error('Failed to parse rate limit JSON');
|
||||
}
|
||||
|
||||
if (isRateLimit(rateLimit)) {
|
||||
return Promise.resolve(rateLimit);
|
||||
} else {
|
||||
throw new Error('Rate limit JSON is not of type RateLimit');
|
||||
}
|
||||
}
|
||||
|
||||
async function rateLimitExceeded(): Promise<boolean> {
|
||||
const rateLimit: RateLimit = await getRateLimit();
|
||||
return rateLimit && rateLimit.rate.remaining <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download and parse the release list JSON from the GitHub API into a Build[].
|
||||
* @return Information about the released builds of the C/C++ extension.
|
||||
*/
|
||||
async function getReleaseJson(): Promise<Build[]> {
|
||||
if (await rateLimitExceeded()) {
|
||||
throw new Error('Failed to stay within GitHub API rate limit');
|
||||
}
|
||||
|
||||
// Download release JSON
|
||||
const releaseUrl: string = 'https://api.github.com/repos/Microsoft/vscode-cpptools/releases';
|
||||
const header: OutgoingHttpHeaders = { 'User-Agent': 'vscode-cpptools' };
|
||||
|
||||
const data: string = await util.downloadFileToStr(releaseUrl, header)
|
||||
.catch((error) => {
|
||||
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');
|
||||
}
|
||||
});
|
||||
if (!data) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// Parse the file
|
||||
let releaseJson: any;
|
||||
try {
|
||||
releaseJson = JSON.parse(data);
|
||||
} catch (error) {
|
||||
throw new Error('Failed to parse release JSON');
|
||||
}
|
||||
|
||||
// Type check
|
||||
if (isArrayOfBuilds(releaseJson)) {
|
||||
return releaseJson;
|
||||
} else {
|
||||
throw new Error('Release JSON is not of type Build[]');
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,14 @@
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
export class InstallationInformation {
|
||||
export enum InstallationType {
|
||||
Online,
|
||||
Offline
|
||||
}
|
||||
|
||||
export class InstallationInformation {
|
||||
stage: string;
|
||||
type: InstallationType;
|
||||
hasError: boolean;
|
||||
telemetryProperties: { [key: string]: string };
|
||||
|
||||
@@ -14,19 +20,19 @@ export class InstallationInformation {
|
||||
}
|
||||
}
|
||||
|
||||
let installBlob: InstallationInformation ;
|
||||
let installBlob: InstallationInformation;
|
||||
|
||||
export function initializeInstallationInformation(): void {
|
||||
installBlob = new InstallationInformation ();
|
||||
}
|
||||
|
||||
export function getInstallationInformationInstance(): InstallationInformation {
|
||||
export function getInstallationInformation(): InstallationInformation {
|
||||
if (!installBlob) {
|
||||
installBlob = new InstallationInformation();
|
||||
}
|
||||
return installBlob;
|
||||
}
|
||||
|
||||
export function setInstallationStage(stage: string): void {
|
||||
if (!installBlob) {
|
||||
initializeInstallationInformation();
|
||||
}
|
||||
installBlob.stage = stage;
|
||||
getInstallationInformation().stage = stage;
|
||||
}
|
||||
|
||||
export function setInstallationType(type: InstallationType): void {
|
||||
getInstallationInformation().type = type;
|
||||
}
|
||||
+80
-40
@@ -13,32 +13,43 @@ import * as Telemetry from './telemetry';
|
||||
import * as util from './common';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { CppToolsApi, CppToolsExtension } from 'vscode-cpptools';
|
||||
import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistrar } from './commands';
|
||||
import { PlatformInformation } from './platform';
|
||||
import { PackageManager, PackageManagerError, PackageManagerWebResponseError, IPackage } from './packageManager';
|
||||
import { PackageManager, PackageManagerError, IPackage } from './packageManager';
|
||||
import { PersistentState } from './LanguageServer/persistentState';
|
||||
import { initializeInstallationInformation, getInstallationInformationInstance, 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 function activate(context: vscode.ExtensionContext): void | Promise<void> {
|
||||
initializeTemporaryCommandRegistrar();
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<CppToolsApi & CppToolsExtension> {
|
||||
util.setExtensionContext(context);
|
||||
initializeTemporaryCommandRegistrar();
|
||||
Telemetry.activate();
|
||||
util.setProgress(0);
|
||||
cpptoolsJsonUtils.activate(context);
|
||||
initializeInstallationInformation();
|
||||
|
||||
// Initialize the DebuggerExtension and register the related commands and providers.
|
||||
DebuggerExtension.initialize();
|
||||
DebuggerExtension.initialize(context);
|
||||
|
||||
return processRuntimeDependencies();
|
||||
await processRuntimeDependencies();
|
||||
|
||||
return cppTools;
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> {
|
||||
DebuggerExtension.dispose();
|
||||
Telemetry.deactivate();
|
||||
disposables.forEach(d => d.dispose());
|
||||
|
||||
if (languageServiceDisabled) {
|
||||
return;
|
||||
}
|
||||
return LanguageServer.deactivate();
|
||||
}
|
||||
|
||||
@@ -53,6 +64,9 @@ async function processRuntimeDependencies(): Promise<void> {
|
||||
} catch (error) {
|
||||
getOutputChannelLogger().showErrorMessage('The installation of the C/C++ extension failed. Please see the output window for more information.');
|
||||
showOutputChannel();
|
||||
|
||||
// Send the failure telemetry since postInstall will not be called.
|
||||
sendTelemetry(await PlatformInformation.GetPlatformInformation());
|
||||
}
|
||||
// The extension have been installed and activated before.
|
||||
} else {
|
||||
@@ -64,12 +78,16 @@ async function processRuntimeDependencies(): Promise<void> {
|
||||
await onlineInstallation();
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
|
||||
// Send the failure telemetry since postInstall will not be called.
|
||||
sendTelemetry(await PlatformInformation.GetPlatformInformation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function offlineInstallation(): Promise<void> {
|
||||
setInstallationStage('getPlatformInfo');
|
||||
setInstallationType(InstallationType.Offline);
|
||||
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
|
||||
|
||||
setInstallationStage('makeBinariesExecutable');
|
||||
@@ -90,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);
|
||||
@@ -169,23 +188,12 @@ function touchInstallLockFile(): Promise<void> {
|
||||
}
|
||||
|
||||
function handleError(error: any): void {
|
||||
let installationInformation: InstallationInformation = getInstallationInformationInstance();
|
||||
let installationInformation: InstallationInformation = getInstallationInformation();
|
||||
installationInformation.hasError = true;
|
||||
installationInformation.telemetryProperties['stage'] = installationInformation.stage;
|
||||
let errorMessage: string;
|
||||
|
||||
if (error instanceof PackageManagerError) {
|
||||
// If this is a WebResponse error, log the IP that it resolved from the package URL
|
||||
if (error instanceof PackageManagerWebResponseError) {
|
||||
let webRequestPackageError: PackageManagerWebResponseError = error;
|
||||
if (webRequestPackageError.socket) {
|
||||
let address: any = webRequestPackageError.socket.address();
|
||||
if (address) {
|
||||
installationInformation.telemetryProperties['error.targetIP'] = address.address + ':' + address.port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let packageError: PackageManagerError = error;
|
||||
|
||||
installationInformation.telemetryProperties['error.methodName'] = packageError.methodName;
|
||||
@@ -224,10 +232,11 @@ function handleError(error: any): void {
|
||||
}
|
||||
|
||||
function sendTelemetry(info: PlatformInformation): boolean {
|
||||
let installBlob: InstallationInformation = getInstallationInformationInstance();
|
||||
let installBlob: InstallationInformation = getInstallationInformation();
|
||||
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;
|
||||
@@ -238,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;
|
||||
}
|
||||
}
|
||||
@@ -270,23 +281,48 @@ async function postInstall(info: PlatformInformation): Promise<void> {
|
||||
}
|
||||
|
||||
async function finalizeExtensionActivation(): Promise<void> {
|
||||
const cpptoolsJsonFile: string = util.getExtensionFilePath("cpptools.json");
|
||||
|
||||
try {
|
||||
const exists: boolean = await util.checkFileExists(cpptoolsJsonFile);
|
||||
if (exists) {
|
||||
const cpptoolsString: string = await util.readFileText(cpptoolsJsonFile);
|
||||
await cpptoolsJsonUtils.processCpptoolsJson(cpptoolsString);
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore any cpptoolsJsonFile errors
|
||||
if (vscode.workspace.getConfiguration("C_Cpp", null).get<string>("intelliSenseEngine") === "Disabled") {
|
||||
languageServiceDisabled = true;
|
||||
getTemporaryCommandRegistrarInstance().disableLanguageServer();
|
||||
disposables.push(vscode.workspace.onDidChangeConfiguration(() => {
|
||||
if (!reloadMessageShown && vscode.workspace.getConfiguration("C_Cpp", null).get<string>("intelliSenseEngine") !== "Disabled") {
|
||||
reloadMessageShown = true;
|
||||
util.promptForReloadWindowDueToSettingsChange();
|
||||
}
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
disposables.push(vscode.workspace.onDidChangeConfiguration(() => {
|
||||
if (!reloadMessageShown && vscode.workspace.getConfiguration("C_Cpp", null).get<string>("intelliSenseEngine") === "Disabled") {
|
||||
reloadMessageShown = true;
|
||||
util.promptForReloadWindowDueToSettingsChange();
|
||||
}
|
||||
}));
|
||||
getTemporaryCommandRegistrarInstance().activateLanguageServer();
|
||||
|
||||
// Redownload cpptools.json after activation so it's not blocked.
|
||||
// It'll be used after the extension reloads.
|
||||
cpptoolsJsonUtils.downloadCpptoolsJsonPkg();
|
||||
// Update default for C_Cpp.intelliSenseEngine based on A/B testing settings.
|
||||
// (this may result in rewriting the package.json file)
|
||||
|
||||
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";
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rewriteManifest(): Promise<void> {
|
||||
@@ -298,22 +334,26 @@ 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.ToggleSnippets",
|
||||
"onCommand:C_Cpp.ShowReleaseNotes",
|
||||
"onCommand:C_Cpp.ResetDatabase",
|
||||
"onCommand:C_Cpp.PauseParsing",
|
||||
"onCommand:C_Cpp.ResumeParsing",
|
||||
"onCommand:C_Cpp.ShowParsingCommands",
|
||||
"onCommand:C_Cpp.TakeSurvey",
|
||||
"onCommand:C_Cpp.LogDiagnostics",
|
||||
"onDebug",
|
||||
"workspaceContains:/.vscode/c_cpp_properties.json"
|
||||
];
|
||||
|
||||
@@ -183,11 +183,10 @@ export class PackageManager {
|
||||
} catch (error) {
|
||||
retryCount += 1;
|
||||
lastError = error;
|
||||
if (retryCount >= MAX_RETRIES) {
|
||||
if (retryCount > MAX_RETRIES) {
|
||||
this.AppendChannel(` Failed to download ` + pkg.url);
|
||||
throw error;
|
||||
} else {
|
||||
// This will skip the success = true.
|
||||
this.AppendChannel(` Failed. Retrying...`);
|
||||
continue;
|
||||
}
|
||||
@@ -198,7 +197,7 @@ export class PackageManager {
|
||||
if (retryCount !== 0) {
|
||||
// Log telemetry to see if retrying helps.
|
||||
let telemetryProperties: { [key: string]: string } = {};
|
||||
telemetryProperties["success"] = `OnRetry${retryCount}`;
|
||||
telemetryProperties["success"] = success ? `OnRetry${retryCount}` : 'false';
|
||||
if (lastError instanceof PackageManagerError) {
|
||||
let packageError: PackageManagerError = lastError;
|
||||
telemetryProperties['error.methodName'] = packageError.methodName;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
export class PackageVersion {
|
||||
major: number;
|
||||
minor: number;
|
||||
patch: number;
|
||||
suffix?: string;
|
||||
suffixVersion: number;
|
||||
|
||||
constructor(version: string) {
|
||||
const tokens: string[] = version.split(new RegExp('[-\\.]', 'g')); // Match against dots and dashes
|
||||
if (tokens.length < 3) {
|
||||
throw new Error('Failed to parse version string: ' + version);
|
||||
}
|
||||
|
||||
this.major = parseInt(tokens[0]);
|
||||
this.minor = parseInt(tokens[1]);
|
||||
this.patch = parseInt(tokens[2]);
|
||||
|
||||
if (tokens.length > 3) {
|
||||
const firstDigitOffset: number = tokens[3].search(new RegExp(/(\d)/)); // Find first occurrence of 0-9
|
||||
if (firstDigitOffset !== -1) {
|
||||
this.suffix = tokens[3].substring(0, firstDigitOffset);
|
||||
this.suffixVersion = parseInt(tokens[3].substring(firstDigitOffset));
|
||||
} else {
|
||||
this.suffix = tokens[3];
|
||||
this.suffixVersion = 1;
|
||||
}
|
||||
} else {
|
||||
this.suffix = undefined;
|
||||
this.suffixVersion = 0;
|
||||
}
|
||||
|
||||
if (this.major === undefined || this.minor === undefined || this.patch === undefined) {
|
||||
throw new Error('Failed to parse version string: ' + version);
|
||||
}
|
||||
}
|
||||
|
||||
public isGreaterThan(other: PackageVersion, suffixStr: string = 'insiders'): boolean {
|
||||
if ((this.suffix && !this.suffix.startsWith(suffixStr)) || (other.suffix && !other.suffix.startsWith(suffixStr))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let diff: number = this.major - other.major;
|
||||
if (diff) {
|
||||
return diff > 0;
|
||||
} else if (diff = this.minor - other.minor) {
|
||||
return diff > 0;
|
||||
} else if (diff = this.patch - other.patch) {
|
||||
return diff > 0;
|
||||
} else if (this.suffix) {
|
||||
return (other.suffix && this.suffixVersion > other.suffixVersion);
|
||||
} else {
|
||||
return other.suffix ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,38 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import { CppToolsTestHook, Status } from 'vscode-cpptools/out/testApi';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class TestHook implements CppToolsTestHook {
|
||||
private statusChangedEvent: vscode.EventEmitter<Status> = new vscode.EventEmitter<Status>();
|
||||
|
||||
public get StatusChanged(): vscode.Event<Status> {
|
||||
return this.statusChangedEvent.event;
|
||||
}
|
||||
|
||||
public get valid(): boolean {
|
||||
return !!this.statusChangedEvent;
|
||||
}
|
||||
|
||||
public updateStatus(status: Status): void {
|
||||
this.statusChangedEvent.fire(status);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.statusChangedEvent.dispose();
|
||||
this.statusChangedEvent = null;
|
||||
}
|
||||
}
|
||||
|
||||
let testHook: TestHook;
|
||||
|
||||
export function getTestHook(): TestHook {
|
||||
if (!testHook || !testHook.valid) {
|
||||
testHook = new TestHook();
|
||||
}
|
||||
return testHook;
|
||||
}
|
||||
@@ -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
|
||||
});
|
||||
|
||||
+12
-7
@@ -6,25 +6,30 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as assert from 'assert';
|
||||
|
||||
suite(`Debug Integration Test: `, function() {
|
||||
suiteSetup(async function() {
|
||||
let extension = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
if (!extension.isActive) {
|
||||
suite(`Debug Integration Test: `, function(): 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 = new Promise(resolve => {
|
||||
let debugSessionTerminated: Promise<void> = new Promise(resolve => {
|
||||
vscode.debug.onDidTerminateDebugSession((e) => resolve());
|
||||
});
|
||||
|
||||
try {
|
||||
assert.equal(vscode.debug.activeDebugSession.type, "cppdbg");
|
||||
} catch (e) {
|
||||
assert.fail("Debugger failed to launch. Did the extension activate correctly?")
|
||||
assert.fail("Debugger failed to launch. Did the extension activate correctly?");
|
||||
}
|
||||
|
||||
await debugSessionTerminated;
|
||||
@@ -1,131 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as assert from 'assert';
|
||||
import { getLanguageConfigFromPatterns } from '../../src/LanguageServer/languageConfig';
|
||||
import * as config from '../../src/LanguageServer/configurations';
|
||||
import { CppSettings } from '../../src/LanguageServer/settings';
|
||||
|
||||
suite("multiline comment setting tests", function() {
|
||||
suiteSetup(async function() {
|
||||
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
});
|
||||
|
||||
let defaultRules: vscode.OnEnterRule[] = [
|
||||
{
|
||||
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
afterText: /^\s*\*\/$/,
|
||||
action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
action: { indentAction: vscode.IndentAction.None, appendText: ' * ' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
|
||||
action: { indentAction: vscode.IndentAction.None, appendText: '* ' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\*\/\s*$/,
|
||||
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\*[^/]*\*\/\s*$/,
|
||||
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
|
||||
}
|
||||
];
|
||||
let defaultSLRules: vscode.OnEnterRule[] = [
|
||||
{
|
||||
beforeText: /^\s*\/\/\/.+$/,
|
||||
action: { indentAction: vscode.IndentAction.None, appendText: '///' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\/\/\/$/,
|
||||
action: { indentAction: vscode.IndentAction.None, removeText: 0 }
|
||||
}
|
||||
];
|
||||
|
||||
test("Check the default OnEnterRules for C", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Check for removal of single line comment continuations for C", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**", "///" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Check the default OnEnterRules for C++", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Make sure duplicate rules are removed", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**", { begin: "/**", continue: " * " }, "/**" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Check single line rules for C++", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "///" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultSLRules);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
suite("configuration tests", function() {
|
||||
suiteSetup(async function() {
|
||||
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
// Open a c++ file to start the language server.
|
||||
await vscode.workspace.openTextDocument({ language: "cpp", content: "int main() { return 0; }"});
|
||||
});
|
||||
|
||||
suiteTeardown(async function() {
|
||||
// Delete c_cpp_properties.json
|
||||
});
|
||||
|
||||
|
||||
|
||||
test("Check default configuration", () => {
|
||||
let rootUri: vscode.Uri;
|
||||
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
|
||||
rootUri = vscode.workspace.workspaceFolders[0].uri;
|
||||
}
|
||||
assert.notEqual(rootUri, undefined, "Root Uri is not defined");
|
||||
if (rootUri) {
|
||||
let cppProperties: config.CppProperties = new config.CppProperties(rootUri);
|
||||
let configurations: config.Configuration[] = cppProperties.Configurations;
|
||||
let defaultConfig: config.Configuration = config.getDefaultConfig();
|
||||
assert.deepEqual(configurations[0], defaultConfig);
|
||||
console.log(JSON.stringify(configurations, null, 2));
|
||||
|
||||
// Need to set the CompilerDefaults before the CppProperties can be successfully modified.
|
||||
cppProperties.CompilerDefaults = {
|
||||
compilerPath: "/path/to/compiler",
|
||||
cStandard: "c99",
|
||||
cppStandard: "c++14",
|
||||
frameworks: ["/path/to/framework"],
|
||||
includes: ["/path/to/includes"]
|
||||
};
|
||||
|
||||
configurations[0].cppStandard = "${default}";
|
||||
|
||||
let s: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp.default", rootUri);
|
||||
let d: any = s.inspect("cppStandard");
|
||||
s.update("cppStandard", "c++11", vscode.ConfigurationTarget.WorkspaceFolder);
|
||||
d = s.inspect("cppStandard");
|
||||
|
||||
cppProperties.onDidChangeSettings();
|
||||
}
|
||||
});
|
||||
});
|
||||
*/
|
||||
@@ -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;
|
||||
@@ -0,0 +1,398 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as assert from 'assert';
|
||||
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 { 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");
|
||||
util.setExtensionPath(extension.extensionPath);
|
||||
initializeTemporaryCommandRegistrar();
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
});
|
||||
|
||||
let defaultRules: vscode.OnEnterRule[] = [
|
||||
{
|
||||
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
afterText: /^\s*\*\/$/,
|
||||
action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
action: { indentAction: vscode.IndentAction.None, appendText: ' * ' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
|
||||
action: { indentAction: vscode.IndentAction.None, appendText: '* ' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\*\/\s*$/,
|
||||
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\*[^/]*\*\/\s*$/,
|
||||
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
|
||||
}
|
||||
];
|
||||
let defaultSLRules: vscode.OnEnterRule[] = [
|
||||
{
|
||||
beforeText: /^\s*\/\/\/.+$/,
|
||||
action: { indentAction: vscode.IndentAction.None, appendText: '///' }
|
||||
},
|
||||
{
|
||||
beforeText: /^\s*\/\/\/$/,
|
||||
action: { indentAction: vscode.IndentAction.None, removeText: 0 }
|
||||
}
|
||||
];
|
||||
|
||||
test("Check the default OnEnterRules for C", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Check for removal of single line comment continuations for C", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**", "///" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Check the default OnEnterRules for C++", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Make sure duplicate rules are removed", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**", { begin: "/**", continue: " * " }, "/**" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultRules);
|
||||
});
|
||||
|
||||
test("Check single line rules for C++", () => {
|
||||
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "///" ]).onEnterRules;
|
||||
assert.deepEqual(rules, defaultSLRules);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
function cppPropertiesPath(): string {
|
||||
return vscode.workspace.workspaceFolders[0].uri.fsPath + "/.vscode/c_cpp_properties.json";
|
||||
}
|
||||
|
||||
async function changeCppProperties(cppProperties: config.ConfigurationJson, disposables: vscode.Disposable[]): Promise<void> {
|
||||
let promise: Promise<void> = new Promise<void>((resolve, reject) => {
|
||||
disposables.push(getActiveClient().ActiveConfigChanged(name => {
|
||||
if (name === cppProperties.configurations[0].name) {
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
|
||||
// Can't trust the file watcher, so we need to allocate additional time for the backup watcher to fire.
|
||||
setTimeout(() => { reject(new Error("timeout")); }, 4000);
|
||||
});
|
||||
await util.writeFileText(cppPropertiesPath(), JSON.stringify(cppProperties));
|
||||
let contents: string = await util.readFileText(cppPropertiesPath());
|
||||
console.log(" wrote c_cpp_properties.json: " + contents);
|
||||
return promise;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
suite("extensibility tests v2", function(): void {
|
||||
let cpptools: apit.CppToolsTestApi;
|
||||
let lastResult: api.SourceFileConfigurationItem[];
|
||||
let defaultConfig: api.SourceFileConfiguration = {
|
||||
includePath: [ "${workspaceFolder}", "/v2/folder" ],
|
||||
defines: [ "${workspaceFolder}" ],
|
||||
intelliSenseMode: "msvc-x64",
|
||||
standard: "c++17"
|
||||
};
|
||||
let lastBrowseResult: api.WorkspaceBrowseConfiguration;
|
||||
let defaultBrowseConfig: api.WorkspaceBrowseConfiguration = {
|
||||
browsePath: [ "/v2/folder" ],
|
||||
compilerPath: "",
|
||||
standard: "c++14",
|
||||
windowsSdkVersion: "8.1"
|
||||
};
|
||||
|
||||
// Has to be 'any' instead of api.CustomConfigurationProvider because of missing interface members.
|
||||
let provider: api.CustomConfigurationProvider = {
|
||||
name: "cpptoolsTest-v2",
|
||||
extensionId: "ms-vscode.cpptools-test2",
|
||||
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
|
||||
let result: api.SourceFileConfigurationItem[] = [];
|
||||
uris.forEach(uri => {
|
||||
result.push({
|
||||
uri: uri.toString(),
|
||||
configuration: defaultConfig
|
||||
});
|
||||
});
|
||||
lastResult = result;
|
||||
return Promise.resolve(result);
|
||||
},
|
||||
canProvideBrowseConfiguration(): Thenable<boolean> {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
provideBrowseConfiguration(): Thenable<api.WorkspaceBrowseConfiguration> {
|
||||
lastBrowseResult = defaultBrowseConfig;
|
||||
return Promise.resolve(defaultBrowseConfig);
|
||||
},
|
||||
dispose(): void {
|
||||
console.log(" disposed");
|
||||
}
|
||||
};
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteSetup(async function(): Promise<void> {
|
||||
cpptools = await apit.getCppToolsTestApi(api.Version.v2);
|
||||
cpptools.registerCustomConfigurationProvider(provider);
|
||||
cpptools.notifyReady(provider);
|
||||
disposables.push(cpptools);
|
||||
|
||||
await changeCppProperties({
|
||||
configurations: [ {name: "test2", configurationProvider: provider.extensionId} ],
|
||||
version: 4
|
||||
},
|
||||
disposables);
|
||||
});
|
||||
|
||||
suiteTeardown(function(): void {
|
||||
disposables.forEach(d => d.dispose());
|
||||
});
|
||||
|
||||
test("Check provider", async () => {
|
||||
// Open a c++ file to start the language server.
|
||||
let path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main2.cpp";
|
||||
let uri: vscode.Uri = vscode.Uri.file(path);
|
||||
|
||||
let testHook: apit.CppToolsTestHook = cpptools.getTestHook();
|
||||
let testResult: any = new Promise<void>((resolve, reject) => {
|
||||
disposables.push(testHook.StatusChanged(status => {
|
||||
if (status === apit.Status.IntelliSenseReady) {
|
||||
let expected: api.SourceFileConfigurationItem[] = [ {uri: uri.toString(), configuration: defaultConfig} ];
|
||||
assert.deepEqual(lastResult, expected);
|
||||
assert.deepEqual(lastBrowseResult, defaultBrowseConfig);
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
|
||||
});
|
||||
disposables.push(testHook);
|
||||
|
||||
await vscode.workspace.openTextDocument(path);
|
||||
await testResult;
|
||||
});
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
suite("extensibility tests v1", function(): void {
|
||||
let cpptools: apit.CppToolsTestApi;
|
||||
let lastResult: api.SourceFileConfigurationItem[];
|
||||
let defaultConfig: api.SourceFileConfiguration = {
|
||||
includePath: [ "${workspaceFolder}" ],
|
||||
defines: [ "${workspaceFolder}" ],
|
||||
intelliSenseMode: "msvc-x64",
|
||||
standard: "c++17"
|
||||
};
|
||||
|
||||
// Has to be 'any' instead of api.CustomConfigurationProvider because of missing interface members.
|
||||
let provider: any = {
|
||||
name: "cpptoolsTest-v1",
|
||||
extensionId: "ms-vscode.cpptools-test",
|
||||
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
|
||||
let result: api.SourceFileConfigurationItem[] = [];
|
||||
uris.forEach(uri => {
|
||||
result.push({
|
||||
uri: uri.toString(),
|
||||
configuration: defaultConfig
|
||||
});
|
||||
});
|
||||
lastResult = result;
|
||||
return Promise.resolve(result);
|
||||
},
|
||||
dispose(): void {
|
||||
console.log(" disposed");
|
||||
}
|
||||
};
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteSetup(async function(): Promise<void> {
|
||||
cpptools = await apit.getCppToolsTestApi(api.Version.v1);
|
||||
cpptools.registerCustomConfigurationProvider(provider);
|
||||
disposables.push(cpptools);
|
||||
|
||||
await changeCppProperties({
|
||||
configurations: [ {name: "test1", configurationProvider: provider.extensionId} ],
|
||||
version: 4
|
||||
},
|
||||
disposables);
|
||||
});
|
||||
|
||||
suiteTeardown(function(): void {
|
||||
disposables.forEach(d => d.dispose());
|
||||
});
|
||||
|
||||
test("Check provider", async () => {
|
||||
// Open a c++ file to start the language server.
|
||||
let path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main1.cpp";
|
||||
let uri: vscode.Uri = vscode.Uri.file(path);
|
||||
|
||||
let testHook: apit.CppToolsTestHook = cpptools.getTestHook();
|
||||
let testResult: any = new Promise<void>((resolve, reject) => {
|
||||
disposables.push(testHook.StatusChanged(status => {
|
||||
if (status === apit.Status.IntelliSenseReady) {
|
||||
let expected: api.SourceFileConfigurationItem[] = [ {uri: uri.toString(), configuration: defaultConfig} ];
|
||||
assert.deepEqual(lastResult, expected);
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
|
||||
});
|
||||
disposables.push(testHook);
|
||||
|
||||
await vscode.workspace.openTextDocument(path);
|
||||
await testResult;
|
||||
});
|
||||
});
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
suite("extensibility tests v0", function(): void {
|
||||
let cpptools: apit.CppToolsTestApi;
|
||||
let lastResult: api.SourceFileConfigurationItem[];
|
||||
let defaultConfig: api.SourceFileConfiguration = {
|
||||
includePath: [ "${workspaceFolder}" ],
|
||||
defines: [ "${workspaceFolder}" ],
|
||||
intelliSenseMode: "msvc-x64",
|
||||
standard: "c++17"
|
||||
};
|
||||
|
||||
// Has to be 'any' instead of api.CustomConfigurationProvider because of missing interface members.
|
||||
let provider: any = {
|
||||
name: "cpptoolsTest-v0",
|
||||
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
|
||||
let result: api.SourceFileConfigurationItem[] = [];
|
||||
uris.forEach(uri => {
|
||||
result.push({
|
||||
uri: uri.toString(),
|
||||
configuration: defaultConfig
|
||||
});
|
||||
});
|
||||
lastResult = result;
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
};
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteSetup(async function(): Promise<void> {
|
||||
cpptools = await apit.getCppToolsTestApi(api.Version.v0);
|
||||
cpptools.registerCustomConfigurationProvider(provider);
|
||||
disposables.push(cpptools); // This is a no-op for v0, but do it anyway to make sure nothing breaks.
|
||||
|
||||
await changeCppProperties({
|
||||
configurations: [ { name: "test0", configurationProvider: provider.name } ],
|
||||
version: 4
|
||||
},
|
||||
disposables);
|
||||
});
|
||||
|
||||
suiteTeardown(async function(): Promise<void> {
|
||||
disposables.forEach(d => d.dispose());
|
||||
await util.deleteFile(cppPropertiesPath());
|
||||
});
|
||||
|
||||
test("Check provider", async () => {
|
||||
// Open a C++ file to start the language server.
|
||||
let path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main.cpp";
|
||||
let uri: vscode.Uri = vscode.Uri.file(path);
|
||||
|
||||
let testHook: apit.CppToolsTestHook = cpptools.getTestHook();
|
||||
let testResult: any = new Promise<void>((resolve, reject) => {
|
||||
disposables.push(testHook.StatusChanged(status => {
|
||||
if (status === apit.Status.IntelliSenseReady) {
|
||||
let expected: api.SourceFileConfigurationItem[] = [ {uri: uri.toString(), configuration: defaultConfig} ];
|
||||
assert.deepEqual(lastResult, expected);
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
|
||||
});
|
||||
disposables.push(testHook);
|
||||
|
||||
await vscode.workspace.openTextDocument(path);
|
||||
await testResult;
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
suite("configuration tests", function() {
|
||||
suiteSetup(async function() {
|
||||
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
|
||||
if (!extension.isActive) {
|
||||
await extension.activate();
|
||||
}
|
||||
// Open a c++ file to start the language server.
|
||||
await vscode.workspace.openTextDocument({ language: "cpp", content: "int main() { return 0; }"});
|
||||
});
|
||||
|
||||
suiteTeardown(async function() {
|
||||
// Delete c_cpp_properties.json
|
||||
});
|
||||
|
||||
test("Check default configuration", () => {
|
||||
let rootUri: vscode.Uri;
|
||||
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
|
||||
rootUri = vscode.workspace.workspaceFolders[0].uri;
|
||||
}
|
||||
assert.notEqual(rootUri, undefined, "Root Uri is not defined");
|
||||
if (rootUri) {
|
||||
let cppProperties: config.CppProperties = new config.CppProperties(rootUri);
|
||||
let configurations: config.Configuration[] = cppProperties.Configurations;
|
||||
let defaultConfig: config.Configuration = config.getDefaultConfig();
|
||||
assert.deepEqual(configurations[0], defaultConfig);
|
||||
console.log(JSON.stringify(configurations, null, 2));
|
||||
|
||||
// Need to set the CompilerDefaults before the CppProperties can be successfully modified.
|
||||
cppProperties.CompilerDefaults = {
|
||||
compilerPath: "/path/to/compiler",
|
||||
cStandard: "c99",
|
||||
cppStandard: "c++14",
|
||||
frameworks: ["/path/to/framework"],
|
||||
includes: ["/path/to/includes"]
|
||||
};
|
||||
|
||||
configurations[0].cppStandard = "${default}";
|
||||
|
||||
let s: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp.default", rootUri);
|
||||
let d: any = s.inspect("cppStandard");
|
||||
s.update("cppStandard", "c++11", vscode.ConfigurationTarget.WorkspaceFolder);
|
||||
d = s.inspect("cppStandard");
|
||||
|
||||
cppProperties.onDidChangeSettings();
|
||||
}
|
||||
});
|
||||
});
|
||||
*/
|
||||
+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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
+28
-10
@@ -1,16 +1,34 @@
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "build",
|
||||
"command": "g++",
|
||||
"isShellCommand": true,
|
||||
"args": ["main.cpp", "-g", "-o", "program"],
|
||||
"showOutput": "always",
|
||||
"isBuildCommand": true,
|
||||
"windows": {
|
||||
"command": "C:\\MinGW\\bin\\g++.exe"
|
||||
}
|
||||
"label": "build",
|
||||
"command": "g++",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"main.cpp",
|
||||
"-g",
|
||||
"-o",
|
||||
"program"
|
||||
],
|
||||
"group":{
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": true,
|
||||
"clear": false
|
||||
},
|
||||
"windows": {
|
||||
"command": "C:\\MinGW\\bin\\g++.exe"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
int main(int argc, char* arv[]) {
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
int main(int argc, char* arv[]) {
|
||||
return 0;
|
||||
}
|
||||
@@ -5,11 +5,23 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
child_process = require('child_process');
|
||||
path = require('path');
|
||||
async_child_process = require('async-child-process');
|
||||
|
||||
if (process.env.CODE_TESTS_PATH
|
||||
&& process.env.CODE_TESTS_PATH.startsWith('.')){
|
||||
process.env.CODE_TESTS_PATH = path.join(process.cwd(), process.env.CODE_TESTS_PATH.substr(2));
|
||||
}
|
||||
|
||||
require(path.resolve(__dirname, '../node_modules/vscode/bin/test'));
|
||||
let optionsWithFullEnvironment = {
|
||||
cwd: path.resolve(__dirname, '..'),
|
||||
stdio: 'inherit',
|
||||
env: {
|
||||
...process.env,
|
||||
}
|
||||
};
|
||||
|
||||
spawn = child_process.spawn('node', [path.resolve(__dirname, '../node_modules/vscode/bin/test')], optionsWithFullEnvironment);
|
||||
|
||||
return async_child_process.join(spawn);
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user