Compare commits

...
126 Commits
Author SHA1 Message Date
Sean McManus 16b4710f8c Merge pull request #9561 from microsoft/seanmcm/revert2DeploySteps
Revert deploy steps
2022-07-08 12:54:25 -07:00
Sean McManus 3d58b640f0 Fix changelog version. 2022-07-08 11:45:23 -07:00
Sean McManus a5b573dbcd Update changelog for 1.11.2 2022-07-08 11:43:49 -07:00
Sean McManus 9360987d31 Revert "Revert "Add deploySteps and variables to cppdbg (#9418)""
This reverts commit 8914e28c26.
2022-07-08 11:42:09 -07:00
Sean McManus 08776b77f7 Merge pull request #9557 from microsoft/seanmcm/revertDeplaySteps
revert deploy steps
2022-07-07 18:55:50 -07:00
Sean McManus b34766054b Remove changelog entry. 2022-07-07 18:48:05 -07:00
Sean McManus 8914e28c26 Revert "Add deploySteps and variables to cppdbg (#9418)"
This reverts commit b55a98c697.
2022-07-07 18:46:31 -07:00
Sean McManus 2a39dc402a Merge pull request #9550 from microsoft/main
Merge for 1.11.1
2022-07-07 15:55:09 -07:00
xisui-MSFT b55a98c697 Add deploySteps and variables to cppdbg (#9418)
* Add deploySteps and variables to cppdbg
2022-07-06 19:55:39 -07:00
Sean McManus 08b9c995bd Update changelog for 1.11.1 (#9549) 2022-07-06 17:56:43 -07:00
Colen Garoutte-Carson 6da34e4236 Display a log message when intelliSenseMode is Disabled (#9543) 2022-07-06 17:50:34 -07:00
Sean McManus e172440607 Fix cl.exe being excluded for .c files and c/cpp caching. (#9544)
* Fix cl.exe being excluded for .c files and c/cpp caching.
2022-07-06 15:23:30 -07:00
Colen Garoutte-Carson 996453b3a8 Fix issue in which duplicate compiler args might be used in compiler query (#9532) 2022-07-01 11:44:44 -07:00
Colen Garoutte-Carson 0eb68d22a0 Update changelog to reflect reverted change (#9523) 2022-06-29 12:39:40 -07:00
Colen Garoutte-Carson a2a8d77445 Revert "Reduce default C++ inlay hint font size 12 to match VS and potentially reduce confusion (#9480)" (#9522)
This reverts commit a2683630e0.
2022-06-29 12:35:05 -07:00
Sean McManus 032d9a288e Update changelog for 1.11.1 (#9517) 2022-06-28 21:19:40 -07:00
Sean McManus 59ea146b6e Change C_Cpp.debugShortcut to resource scope (#9514)
Make C_Cpp.debugShortcut resource scope.
2022-06-28 20:57:31 -07:00
Sean McManus 09a1ce1e8a Update ThirdPartyNotices.txt (#9516)
* Update ThirdPartyNotices.txt
2022-06-28 19:18:23 -07:00
Colen Garoutte-Carson 58a9ec846f Fix issue preventing building with the latest nodejs (#9515) 2022-06-28 16:49:19 -07:00
Sean McManus 6f3ae65833 Add setting to hide leading underscores for inlay hints. (#9500)
* Add setting to hide leading underscores for inlay hints.
2022-06-28 16:25:03 -07:00
Sean McManus a8e6695b55 Add setting to show inlay hints on the left. (#9506) 2022-06-28 14:48:06 -07:00
Chuck Ries c7edc9981f Contribute breakpoints for the "rust" language (#9484)
* Contribute breakpoints for the "rust" language

Since rust code can be debugged with this extension, contribute breakpoints for the "rust" language such that the workaround of "allow breakpoints in all files" is no longer required.
2022-06-28 14:12:20 -07:00
Sean McManus 4d0912eb9d Update yarn.lock. (#9513) 2022-06-28 12:15:52 -07:00
Andrew Wang 7747ac6226 Update VSCode Telemetry Package to v0.6.2 (#9512)
* Update VSCode Telemetry Package to v0.6.2
2022-06-28 11:34:09 -07:00
Elaheh Rashedi 13155149ea rename "success" to "succeeded" in telemetry (#9509) 2022-06-28 10:56:55 -07:00
Sean McManus d3fffbad7b Add setting for & space in inlay hints. (#9502)
* Add setting for & space in inlay hints.
2022-06-24 12:06:36 -07:00
Sean McManus 6fe98d2f54 Add left padding to "auto" inlay hints with no spaces on the left (#9499)
* Add left padding to inlay hint.
2022-06-24 11:13:33 -07:00
Sean McManus a2683630e0 Reduce default C++ inlay hint font size 12 to match VS and potentially reduce confusion (#9480)
* Reduce default inlay hint font size to 12 match VS and reduce confusion.
2022-06-23 17:33:37 -07:00
Sean McManus 590923ca99 Fix remove diagnostics for the disable case. (#9495) 2022-06-23 13:42:44 -07:00
Sean McManus 2a5198ed9d Merge pull request #9477 from microsoft/main
Change inlayHint defaults settings. (#9476)
2022-06-20 11:42:18 -07:00
Sean McManus 4a85594360 Change inlayHint defaults settings. (#9476) 2022-06-20 11:18:16 -07:00
Sean McManus 3d7f5ea0ca Merge pull request #9470 from microsoft/main
Show or hide commands based on C_Cpp.intelliSenseEngine value (#9469)
2022-06-17 16:46:44 -07:00
Michelle Matias 982314db80 Show or hide commands based on C_Cpp.intelliSenseEngine value (#9469) 2022-06-17 16:18:57 -07:00
Sean McManus 3abe8a564b Merge pull request #9468 from microsoft/main
Merge for 1.11.0
2022-06-17 14:03:31 -07:00
Sean McManus 2dc0a86605 Update changelog for 1.11.0. (#9462)
* Update changelog for 1.11.0.
2022-06-17 13:26:40 -07:00
Sean McManus 84f5f6505d Update extension pack readme. (#9456) 2022-06-17 13:17:37 -07:00
Sean McManus cc685c8d7f Fix translations (#9467) 2022-06-17 12:41:52 -07:00
Michelle Matias 9b07d494c6 Add settings for inlay hints feature (#9460) 2022-06-17 11:52:04 -07:00
Sean McManus 145a1aa470 Update IntelliSense loc strings. (#9450) 2022-06-15 14:05:41 -07:00
Sean McManus 5d4867e0ab Update version and changelog for 1.10.7. (#9454) 2022-06-15 13:46:29 -07:00
Michelle Matias a665cb1329 Add InlayHintsProvider and Display hints (#9392) 2022-06-14 23:12:29 -07:00
Elaheh Rashedi b29d5e8d33 resolve tasks when IntelliSense is disabled (#9448) 2022-06-14 16:33:48 -07:00
Sean McManus 81827f6536 Update version and changelog. (#9440)
* Update version and changelog.
2022-06-14 14:07:35 -07:00
Sean McManus 8e5f3af858 Remove legacyCompilerArgsBehavior deprecation. (#9439) 2022-06-14 13:49:54 -07:00
Sean McManus 9397ddb725 Code analysis refactor (#9402)
* Refactor code analysis code.
2022-06-08 15:47:39 -07:00
Colen Garoutte-Carson 4fc18a7eb4 Merge pull request #9400 from microsoft/main 2022-06-03 14:48:59 -07:00
Sean McManus c3dd4405a6 Merge pull request #9344 from microsoft/main
Merge for 1.10.3
2022-05-20 17:07:19 -07:00
Sean McManus 32ba555dee Merge pull request #9304 from microsoft/main
Update changelog and version. (#9303)
2022-05-12 17:08:36 -07:00
Michelle Matias f31caa30f4 Merge pull request #9290 from microsoft/main
1.10.1 insiders
2022-05-09 17:52:14 -07:00
Colen Garoutte-Carson fab35332eb Merge pull request #9213 from microsoft/main 2022-04-20 16:52:16 -07:00
Sean McManus 8bea1ecb35 Merge pull request #9061 from microsoft/main
Merge for 1.9.6
2022-03-21 11:48:55 -07:00
Sean McManus caecbf9532 Merge pull request #9045 from microsoft/main
Merge for 1.9.5
2022-03-17 12:42:42 -07:00
Sean McManus c3312d3fba Merge pull request #9030 from microsoft/main
Merge for 1.9.4
2022-03-15 21:46:09 -07:00
Sean McManus 7886ac0e98 Merge pull request #9002 from microsoft/main
Merge for 1.9.3
2022-03-09 13:49:43 -08:00
Sean McManus 8eea7fb23e Merge pull request #8957 from microsoft/main
Merge for 1.9.2
2022-03-01 14:02:57 -08:00
elrashed ec511b941d Merge branch 'main' into insiders 2022-02-24 11:50:54 -08:00
Colen Garoutte-Carson 17140a9fde Merge pull request #8923 from microsoft/main 2022-02-23 19:23:56 -08:00
Michelle Matias b30c098dc1 Merge pull request #8839 from microsoft/main
Insiders 1.9.0 #3
2022-02-10 15:59:16 -08:00
Michelle Matias e135b011bc Merge pull request #8833 from microsoft/mimatias/insiders1-9
Insiders 1.9.0 #2
2022-02-10 13:38:38 -08:00
Michelle Matias 2913721755 Merge branch 'main' into mimatias/insiders1-9 2022-02-10 13:30:18 -08:00
Michelle Matias 7a83d8d76a Merge pull request #8831 from microsoft/mimatias/insiders1_9
Insiders 1.9.0
2022-02-10 13:20:21 -08:00
Michelle Matias db67ca332c remove extra === 2022-02-10 13:17:26 -08:00
Michelle Matias 69cf11512a Merge branch 'main' into mimatias/insiders1_9 2022-02-10 13:11:50 -08:00
Colen Garoutte-Carson 011b5c12a9 Merge pull request #8783 from microsoft/coleng/merge_insiders_1_8_4 2022-02-04 17:14:12 -08:00
Colen Garoutte-Carson b5c13664a6 Update changelog for 1.8.4 (#8778) 2022-02-04 16:37:54 -08:00
Sean McManus f95b1cebf7 Remove offline installation from ReadMes. (#8769) 2022-02-04 16:37:50 -08:00
Colen Garoutte-Carson 4813194480 Suppress incorrect warnings on Mac M1 (#8757) 2022-02-04 16:37:45 -08:00
Sean McManus 97fd5b6bb9 Update changelog. (#8754)
* Update changelog.
2022-02-04 16:37:38 -08:00
Sean McManus 75d131d3ea Merge pull request #8747 from microsoft/main
Merge for 1.8.3 (insiders)
2022-01-31 12:28:29 -08:00
Sean McManus abc3c11cab Merge pull request #8731 from microsoft/main
Merge for 1.8.1
2022-01-27 13:46:46 -08:00
Colen Garoutte-Carson 88f0bbebb9 Merge pull request #8669 from microsoft/main 2022-01-13 13:39:55 -08:00
Colen Garoutte-Carson 7b175d4ab4 Merge pull request #8663 from microsoft/main 2022-01-12 13:48:16 -08:00
Colen Garoutte-Carson 29e8ff6f3b Merge pull request #8658 from microsoft/main 2022-01-11 18:10:18 -08:00
Colen Garoutte-Carson d0985f5c82 Merge main into insiders branch (#8656) 2022-01-11 16:28:17 -08:00
Sean McManus 7f996068d4 Merge pull request #8503 from microsoft/main
Merge for 1.8.0-insiders2
2021-12-07 13:40:33 -08:00
Sean McManus 27d1ac3897 Merge pull request #8463 from microsoft/main
Merge for 1.8.0-insiders
2021-11-29 17:06:40 -08:00
Colen Garoutte-Carson 999f28bf83 Merge pull request #8205 from microsoft/main 2021-09-29 16:28:41 -07:00
Colen Garoutte-Carson f7d0b1bf22 Merge pull request #8187 from microsoft/main 2021-09-24 14:13:41 -07:00
Colen Garoutte-Carson eede66558e Merge pull request #8007 from microsoft/main 2021-08-18 16:00:20 -07:00
Colen Garoutte-Carson a9890f62ae Merge pull request #7988 from microsoft/main 2021-08-16 18:26:31 -07:00
Colen Garoutte-Carson c98303bd2c Merge pull request #7967 from microsoft/main 2021-08-12 13:20:55 -07:00
Colen Garoutte-Carson c658673abb Merge pull request #7963 from microsoft/main
Merge main to insiders branch
2021-08-11 18:52:59 -07:00
Sean McManus 7ad30dae85 Merge pull request #7766 from microsoft/main
Merge for 1.5.0-insiders3 (2nd time)
2021-07-01 14:25:47 -07:00
Sean McManus 2ab63a451a Merge pull request #7758 from microsoft/main
Merge for 1.5.0-insiders3
2021-06-30 17:46:54 -07:00
Sean McManus 857bce91ee Merge pull request #7734 from microsoft/main
Merge for 1.5.0-insiders2
2021-06-21 15:49:31 -07:00
Sean McManus 49b8160a58 Merge pull request #7695 from microsoft/main
Fix settings UI. (#7694)
2021-06-14 15:21:58 -07:00
Sean McManus 4d80ef39cb Merge pull request #7691 from microsoft/main
Minor changes. (#7690)
2021-06-14 11:31:53 -07:00
Sean McManus 8ea76a7d8b Merge pull request #7683 from microsoft/1_5_0_insiders
1 5 0 insiders
2021-06-11 19:36:17 -07:00
Sean McManus 046821112b Merge branch 'main' into 1_5_0_insiders 2021-06-11 17:47:43 -07:00
Sean McManus 18ac98a353 Merge pull request #7591 from microsoft/seanmcm/1_4_0_insiders3_2
1.4.0-insiders3 2nd time
2021-05-25 15:27:47 -07:00
Sean McManus fad828ed78 Merge branch 'main' into seanmcm/1_4_0_insiders3_2 2021-05-25 14:37:44 -07:00
Sean McManus f675d7ece3 Merge pull request #7566 from microsoft/seanmcm/1_4_0_insiders3
1.4.0-insiders3
2021-05-20 18:44:01 -07:00
Sean McManus 213799975c Merge branch 'main' into seanmcm/1_4_0_insiders3 2021-05-20 18:39:44 -07:00
Sean McManus 3512a088d6 Merge pull request #7537 from microsoft/seanmmc/1_4_0_insiders2
1.4.0-insiders2
2021-05-17 14:09:30 -07:00
Sean McManus 8ec3dfa3fd Merge branch 'main' into seanmmc/1_4_0_insiders2 2021-05-17 12:58:47 -07:00
Sean McManus 905f8dc216 Merge pull request #7504 from microsoft/seanmcm/1_4_0_insidersMerge2
1.4.0-insiders merge2
2021-05-10 11:55:49 -07:00
Sean McManus 6464f55fcf Merge branch 'main' into seanmcm/1_4_0_insidersMerge2 2021-05-10 09:54:57 -07:00
Sean McManus dba4a28d88 Merge pull request #7480 from microsoft/seanmcm/1_4_0_insiders
1.4.0-insiders
2021-05-06 19:39:23 -07:00
Sean McManus 53a3864fdc Update version. 2021-05-06 18:46:06 -07:00
Sean McManus 0ea25159d4 Merge branch 'main' into seanmcm/1_4_0_insiders 2021-05-06 18:41:47 -07:00
Colen Garoutte-Carson 143207aadb Merge to insiders (#7320) 2021-04-08 15:22:46 -07:00
Michelle Matias 0edf6c3ea7 Merge pull request #7304 from microsoft/mimatias/insiders4-2
1.3.0-insiders4 (#2)
2021-04-06 16:39:09 -07:00
Michelle Matias 4e22b6577f Merge pull request #7302 from microsoft/mimatias/insiders4
1.3.0-insiders4
2021-04-06 11:48:40 -07:00
Michelle Matias 1ab60bc247 Merge branch 'insiders' into mimatias/insiders4 2021-04-06 11:45:09 -07:00
Colen Garoutte-Carson 33eb2f6abe Add some files missed when merging to Insiders branch (#7271) 2021-04-01 12:15:23 -07:00
Colen Garoutte-Carson 11262438e3 Merge main into insiders (#7266) 2021-03-31 19:16:40 -07:00
Colen Garoutte-Carson 673a68d4cc Merge to insiders (#7236) 2021-03-25 14:05:32 -07:00
Sean McManus 437d9b333a Merge pull request #7223 from microsoft/1_3_0_insiders2
1.3.0-insiders2 merge
2021-03-24 12:10:49 -07:00
Sean McManus 0139274856 Change date. 2021-03-24 12:09:28 -07:00
Sean McManus 87cfa702bc Update changelog. 2021-03-24 06:04:49 -07:00
Sean McManus 013bff267e Merge branch 'insiders' into 1_3_0_insiders2 2021-03-24 05:53:35 -07:00
Colen Garoutte-Carson d942d64b7b Merge main to insiders (#7186) 2021-03-16 20:56:48 -07:00
Colen Garoutte-Carson 1a2bf6fc4c Merge main into insiders (#7180) 2021-03-16 17:44:59 -07:00
Sean McManus 32c1d6bf52 Merge pull request #6997 from microsoft/main
Merge for 1.2.2-insiders2
2021-02-18 18:13:59 -08:00
Sean McManus ebd5314b48 Merge pull request #6986 from microsoft/seanmcm/1_2_2_insiders
1.2.2-insiders
2021-02-17 15:01:04 -08:00
Sean McManus 5c7f551dba Merge. 2021-02-17 14:57:49 -08:00
Sean McManus 6ccea3878b Merge pull request #6853 from microsoft/seanmcm/1_2_0_insiders3
1.2.0-insiders3
2021-01-26 18:22:11 -08:00
Sean McManus e5fd036af9 Update changelog. 2021-01-26 17:40:57 -08:00
Sean McManus 4254419e76 Merge branch 'main' into seanmcm/1_2_0_insiders3 2021-01-26 17:27:51 -08:00
Sean McManus f9ecc9c6f9 Merge pull request #6820 from microsoft/seanmcm/1_2_0_insiders2
1.2.0-insiders2
2021-01-19 20:26:53 -08:00
Sean McManus 9405f41521 Merge branch 'main' into seanmcm/1_2_0_insiders2 2021-01-19 18:22:49 -08:00
Sean McManus 37cca41225 Merge pull request #6785 from microsoft/seanmcm/1_2_0_insiders_updates
1 2 0 insiders updates
2021-01-14 18:22:43 -08:00
Sean McManus ed584b23e2 Merge branch 'main' into seanmcm/1_2_0_insiders_updates 2021-01-14 18:21:56 -08:00
Sean McManus f7cab674a4 Merge branch 'main' into seanmcm/1_2_0_insiders_updates 2021-01-14 17:31:47 -08:00
Sean McManus 42586081fa Merge pull request #6777 from microsoft/seanmcm/1_2_0_insiders
Merge latest changes for 1.2.0-insiders
2021-01-13 18:56:37 -08:00
Sean McManus c49e51d386 Fix extra space. 2021-01-13 18:53:52 -08:00
49 changed files with 7021 additions and 3635 deletions
+1
View File
@@ -33,3 +33,4 @@ localized_string_ids.h
# ignore generate files. It will be generated when building
src/nativeStrings.ts
vscode*.d.ts
+47
View File
@@ -1,5 +1,52 @@
# C/C++ for Visual Studio Code Change Log
## Version 1.11.2 (pre-release): July 8, 2022
### Enhancements
* Add deploySteps and variables to cppdbg. [PR #9418](https://github.com/microsoft/vscode-cpptools/pull/9418)
## Version 1.11.1 (pre-release): July 7, 2022
### Enhancements
* Move "auto" inlay hints to the right by default and add `C_Cpp.inlayHints.autoDeclarationTypes.showOnLeft`. [#9478](https://github.com/microsoft/vscode-cpptools/issues/9478)
* Allow breakpoints for Rust debugging. [PR #9484](https://github.com/microsoft/vscode-cpptools/pull/9484)
* Remove `_` from the start of parameter inlay hints and add `C_Cpp.inlayHints.parameterNames.hideLeadingUnderscores`. [#9485](https://github.com/microsoft/vscode-cpptools/issues/9485)
* Add `C_Cpp.inlayHints.referenceOperator.showSpace` setting. [#9486](https://github.com/microsoft/vscode-cpptools/issues/9486)
* Make `C_Cpp.debugShortcut` settable per-workspace folder. [PR #9514](https://github.com/microsoft/vscode-cpptools/pull/9514)
### Bug Fixes
* Fix "unknown register name" IntelliSense error. [#4382](https://github.com/microsoft/vscode-cpptools/issues/4382)
* Fix performance issue with tag parsing a file with a lot of defines. [#6454](https://github.com/microsoft/vscode-cpptools/issues/6454)
* Fix missing logging when `C_Cpp.intelliSenseEngine` is set to `"Disabled"`. [#9277](https://github.com/microsoft/vscode-cpptools/issues/9277)
* Fix the code analysis "disable" option not automatically clearing the disabled diagnostics. [#9364](https://github.com/microsoft/vscode-cpptools/issues/9364)
* Fix `-isystem` not being used for system headers with code analysis. [#9366](https://github.com/microsoft/vscode-cpptools/issues/9366)
* Fix compiler querying for EDG-based compilers. [#9410](https://github.com/microsoft/vscode-cpptools/issues/9410)
* Fix bug with the environment being incorrect when compiler querying. [#9472](https://github.com/microsoft/vscode-cpptools/issues/9472)
* Fix inlay hints not having padding on the left if there is no existing space. [#9479](https://github.com/microsoft/vscode-cpptools/issues/9479)
* Fix duplicate inlay hints appearing sometimes. [#9487](https://github.com/microsoft/vscode-cpptools/issues/9487)
* Fix duplicate compiler args in compiler query with custom configuration providers using cpptools-api prior to v6. [#9531](https://github.com/microsoft/vscode-cpptools/issues/9531)
* Fix cl.exe build tasks not showing for .c files and .c build tasks being cached for .cpp files (and vice versa). [PR #9544](https://github.com/microsoft/vscode-cpptools/pull/9544)
* Fix process launching concurrency issues on Windows.
## Version 1.11.0 (pre-release): June 20, 2022
### New Features
* Add inlay hints for parameters and auto types. [#5845](https://github.com/microsoft/vscode-cpptools/issues/5845)
### Bug Fixes
* Fix doxygen comments not being displayed for multiple adjacent `@brief` or `@return` tags. [#9316](https://github.com/microsoft/vscode-cpptools/issues/9316)
* Fix crash if clang-tidy returns a replacement with an empty FilePath. [#9437](https://github.com/microsoft/vscode-cpptools/issues/9437)
* Fix hiding IntelliSense dependent commands when `C_Cpp.intelliSenseEngine` is `"Disabled"`. [#9451](https://github.com/microsoft/vscode-cpptools/issues/9451)
* Fix skipping the compiler argument after `-c`. [#9453](https://github.com/microsoft/vscode-cpptools/issues/9453)
* Fix `-std:c++20` not being handled with cl.exe. [#9458](https://github.com/microsoft/vscode-cpptools/issues/9458)
## Version 1.10.7: June 15, 2022
### Bug Fixes
* Fix bugs with process creation on Windows (which caused IntelliSense to fail). [#9431](https://github.com/microsoft/vscode-cpptools/issues/9431)
## Version 1.10.6: June 14, 2022
### Bug Fixes
* Fix `@responseFile` in `compilerArgs` not being handled on Linux/Mac. [#9434](https://github.com/microsoft/vscode-cpptools/issues/9434)
* Fix debug preLaunchTask not working when `C_Cpp.intelliSenseEngine` is `"Disabled"`. [#9446](https://github.com/microsoft/vscode-cpptools/issues/9446)
* Make the `C_Cpp.legacyCompilerArgsBehavior` setting non-deprecated.
## Version 1.10.5: June 8, 2022
### New Features
* Add code actions to apply clang-tidy fixes (and other actions). [#8476](https://github.com/microsoft/vscode-cpptools/issues/8476)
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -3457,5 +3457,9 @@
"znaková konstanta UTF-16 nemůže zabírat více než jednu jednotku kódu; hodnota byla zkrácena",
"oba argumenty musí mít stejný typ",
"typ %t není platný jako argument pro tento předdefinovan.",
"voláno z %nd:"
"voláno z %nd:",
"kvalifikovaný typ je pro anonymní bitová pole nestandardní.",
"typ elementu vektorové podmínky (%t1) musí mít stejnou velikost jako typ elementu výsledku (%t2).",
"typ operandu vektoru s plovoucí desetinnou čárkou (%t) nemá žádný odpovídající celočíselný vektorový typ.",
"mangling pro výrazy requires ještě není implementovaný."
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"Eine UTF-16-Zeichenkonstante darf nicht mehrere Codeeinheiten belegen. Wert abgeschnitten.",
"Beide Argumente müssen denselben Typ aufweisen.",
"Der Typ \"%t\" ist als Argument für dieses integrierte Element ungültig.",
"aufgerufen von %nd:"
"aufgerufen von %nd:",
"ein qualifizierter Typ ist kein Standard für anonyme Bitfelder",
"der Elementtyp der Vektorbedingung (%t1) muss dieselbe Größe haben wie der Elementtyp des Ergebnisses (%t2)",
"der Gleitkomma-Vektoroperandentyp (%t) hat keinen übereinstimmenden ganzzahligen Vektortyp",
"das Mangling für 'requires'-Ausdrücke ist noch nicht implementiert"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"una constante de caracteres UTF-16 no puede ocupar más de una unidad de código; valor truncado",
"ambos argumentos deben tener el mismo tipo",
"el tipo %t no es válido como argumento para este elemento integrado",
"llamado desde %nd:"
"llamado desde %nd:",
"un tipo calificado no es estándar para campos de bits anónimos",
"el tipo de elemento de la condición de vector (%t1) debe tener el mismo tamaño que el tipo de elemento del resultado (%t2)",
"el tipo de operando de vector de punto flotante (%t) no tiene ningún tipo de vector entero coincidente",
"aún no se ha implementado la limpieza de expresiones \"requires\""
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"une constante de caractères UTF-16 ne peut pas occuper plusieurs unités de code ; valeur tronquée",
"les deux arguments doivent avoir le même type",
"le type %t nest pas valide en tant quargument pour ce builtin",
"appelé à partir de %nd :"
"appelé à partir de %nd :",
"un type qualifié nest pas standard pour les champs de bits anonymes.",
"le type d’élément de la condition vectorielle (%t1) doit avoir la même taille que le type d’élément du résultat (%t2).",
"le type dopérande vectoriel à virgule flottante (%t) na pas de type de vecteur entier correspondant.",
"La gestion des expressions \"requires\" n'est pas encore implémentée."
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"una costante di caratteri UTF-16 non può occupare più di un'unità di codice; valore troncato",
"entrambi gli argomenti devono avere lo stesso tipo",
"il tipo %t non è valido come argomento per questa compilazione",
"chiamato da %nd:"
"chiamato da %nd:",
"un tipo qualificato non è conforme allo standard per i campi di bit anonimi",
"il tipo di elemento della condizione vettoriale (%t1) deve avere le stesse dimensioni del tipo di elemento del risultato (%t2)",
"il tipo di operando di vettore a virgola mobile (%t) non ha un tipo di vettore intero corrispondente",
"il mangling per le espressioni 'requires' non è ancora implementato"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"UTF-16 文字定数は複数のコード単位を占有できません。値が切り捨てられました",
"両方の引数は同じ型である必要があります",
"型 %t は、このビルトインの引数として無効です",
"%nd からの呼び出し:"
"%nd からの呼び出し:",
"修飾された型は匿名ビット フィールドでは非標準です",
"ベクトル条件 (%t1) の要素型は、結果の要素型 (%t2) と同じサイズである必要があります",
"浮動小数点ベクトル オペランド型 (%t) に一致する整数ベクトル型がありません",
"'requires' 式のためのマングリングは、まだ実装されていません"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"UTF-16 문자 상수는 코드 단위를 두 개 이상 사용할 수 없음; 값 잘림",
"두 인수의 형식이 같아야 함",
"%t 형식은 이 기본 제공의 인수로 사용할 수 없음",
"%nd에서 호출"
"%nd에서 호출",
"정규화된 형식이 익명 비트 필드에 대해 표준이 아닙니다.",
"벡터 조건의 요소 유형(%t1)은 결과의 요소 유형(%t2)과 크기가 같아야 합니다.",
"부동 소수점 벡터 피연산자 유형(%t)에 일치하는 정수 벡터 유형이 없습니다.",
"'requires' 식에 대한 mangling이 아직 구현되지 않았습니다."
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"stała znaków UTF-16 nie może zajmować więcej niż jednej jednostki kodu; obcięta wartość",
"oba argumenty muszą mieć ten sam typ",
"typ %t jest nieprawidłowy jako argument dla tej wbudowanej",
"wywołano z %nd:"
"wywołano z %nd:",
"kwalifikowany typ jest niestandardowy dla anonimowych pól bitowych",
"typ elementu warunku wektora (%t1) musi mieć taki sam rozmiar jak typ elementu wyniku (%t2)",
"typ operandu wektora zmiennoprzecinkowego (%t) nie ma zgodnego typu wektora liczb całkowitych",
"nie jest jeszcze zaimplementowane dekorowanie wyrażeń typu „requires”."
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"uma constante de caractere UTF-16 não pode ocupar mais de uma unidade de código; valor truncado",
"ambos os argumentos devem ter o mesmo tipo",
"o tipo %téinválido como argumento para este builtin",
"chamado de %nd:"
"chamado de %nd:",
"um tipo qualificado não é padrão para campos de bits anônimos",
"o tipo de elemento da condição de vetor (%t1) deve ter o mesmo tamanho que o tipo de elemento do resultado (%t2)",
"o tipo de operando vetorial de ponto flutuante (%t) não tem nenhum tipo de vetor inteiro correspondente",
"a estruturação para expressões 'requires' ainda não foi implementada"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"символьная константа UTF-16 не может занимать более одной кодовой единицы; значение усечено",
"оба аргумента должны быть одного типа",
"тип %t недопустим в качестве аргумента для этой встроенной функции.",
"вызвано из %nd:"
"вызвано из %nd:",
"нестандартный тип с квалификатором для анонимных битовых полей",
"тип элемента векторного условия (%t1) должен иметь тот же размер, что и тип элемента результата (%t2)",
"тип векторного операнда с плавающей запятой (%t) не имеет соответствующего целочисленного векторного типа",
"искажение для выражений \"requires\" еще не реализовано"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"UTF-16 karakter sabit değeri, bir kod biriminden fazla yer kaplayamaz; kesilmiş değer",
"her iki bağımsız değişken de aynı türe sahip olmalıdır",
"%t türü bu yerleşik için bağımsız değişken olarak geçersiz",
"%nd kaynağından çağrı:"
"%nd kaynağından çağrı:",
"nitelenmiş bir tür adı anonim bit alanları için standart dışı",
"vektör koşulunun öğe türü (%t1), sonucun öğe türü (%t2) ile aynı boyuta sahip olmalıdır",
"kayan nokta vektörü işlenen türü (%t) eşleşen bir tamsayı vektörü türü içermiyor",
"'requires' ifadeleri için değiştirme henüz uygulanmadı"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"UTF-16 字符常量不能占用多个代码单元;值已截断",
"两个参数的类型必须相同",
"类型 %t 无效,不能用作此内置项的参数",
"调用自 %nd:"
"调用自 %nd:",
"限定类型对于匿名位字段是非标准的",
"向量条件的元素类型(%t1)的大小必须与结果的元素类型相同(%t2)",
"浮点向量操作数类型(%t)没有匹配的整数向量类型",
"尚未实现 “requires” 表达式的变量名压缩"
]
+5 -1
View File
@@ -3457,5 +3457,9 @@
"UTF-16 字元常數不可佔用多個程式碼單位; 已截斷值",
"兩個引數的類型必須相同",
"類型 %t 對此內建的引數無效",
"呼叫自 %nd:"
"呼叫自 %nd:",
"限定類型對匿名位欄位而言不是標準類型",
"向量條件 (%t1) 的元素類型大小必須與結果的元素類型相同 (%t2)",
"浮點向量運算元類型 (%t) 沒有相符的整數向量類型",
"尚未實作 'requires' 運算式的重整"
]
@@ -47,7 +47,7 @@
"windows.sdk.version": "Wersja zestawu Windows SDK",
"windows.sdk.version.description": "Wersja ścieżki dyrektywy include zestawu Windows SDK, która ma być używana w systemie Windows, np. {0}.",
"mac.framework.path": "Ścieżka do platformy Mac",
"mac.framework.path.description": "Lista ścieżek do użycia przez aparat IntelliSense podczas wyszukiwania dołączonych nagłówków z platform Mac. Obsługiwane tylko w przypadku konfiguracji dla systemu MacOS.",
"mac.framework.path.description": "Lista ścieżek do użycia przez aparat IntelliSense podczas wyszukiwania dołączonych nagłówków z platform Mac. Obsługiwane tylko w przypadku konfiguracji dla systemu macOS.",
"one.path.per.line": "Jedna ścieżka na wiersz.",
"forced.include": "Wymuszone dołączanie",
"forced.include.description": "Lista plików, które powinny zostać uwzględnione przed przetworzeniem każdego innego znaku w pliku źródłowym. Pliki są uwzględniane w podanej kolejności.",
+938 -43
View File
File diff suppressed because it is too large Load Diff
+36
View File
@@ -166,6 +166,13 @@
"c_cpp.configuration.inactiveRegionOpacity.markdownDescription": { "message": "Controls the opacity of inactive preprocessor blocks. Scales between `0.1` and `1.0`. This setting only applies when inactive region dimming is enabled.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] },
"c_cpp.configuration.inactiveRegionForegroundColor.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.",
"c_cpp.configuration.inactiveRegionBackgroundColor.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.",
"c_cpp.configuration.inlayHints.autoDeclarationTypes.enabled.markdownDescription": { "message": "Display inlay hints for deduced type when `auto` is used in a declaration:\n```cpp \n\n auto index /* : int */ = 0;\n```", "comment": [ "Markdown text between `` and the text inside ``` block is code and should not be localized." ] },
"c_cpp.configuration.inlayHints.autoDeclarationTypes.showOnLeft.markdownDescription": { "message": "Display inlay hints for deduced type when `auto` is used in a declaration on the left of the identifier:\n```cpp \n\n auto /* int */ index = 0;\n```", "comment": [ "Markdown text between `` and the text inside ``` block is code and should not be localized." ] },
"c_cpp.configuration.inlayHints.parameterNames.enabled.markdownDescription": { "message": "Display inlay hints for parameter names:\n```cpp \n\n int a = getArea(/* width: */ x, /* height: */ y);\n```", "comment": [ "Markdown text between `` and the text inside ``` block is code and should not be localized." ] },
"c_cpp.configuration.inlayHints.parameterNames.hideLeadingUnderscores.markdownDescription": { "message": "Hide leading `_` in parameter name hints.", "comment": [ "Markdown text between `` is code and should not be localized." ] },
"c_cpp.configuration.inlayHints.parameterNames.suppressWhenArgumentContainsName.markdownDescription": { "message": "Suppress parameter name hints when the argument text or inline comment contains the parameter name:\n```cpp \n\n int a = getArea(width, /* height: */ y);\n```", "comment": [ "Markdown text between `` and the text inside ``` block is code and should not be localized." ] },
"c_cpp.configuration.inlayHints.referenceOperator.enabled.markdownDescription": { "message": "Display the inlay hint reference operator `&` for parameters passed by non-const reference:\n```cpp \n\n swap(/* &first: */ str1, /* &last: */ str2);\n```", "comment": [ "Markdown text between `` and the text inside ``` block is code and should not be localized." ] },
"c_cpp.configuration.inlayHints.referenceOperator.showSpace.markdownDescription": { "message": "Controls whether a space is shown after `&` for parameters passed by non-const reference:\n```cpp \n\n swap(/* & first: */ str1, /* & last: */ str2);\n```", "comment": [ "Markdown text between `` and the text inside ``` block is code and should not be localized." ] },
"c_cpp.configuration.loggingLevel.markdownDescription": { "message": "The verbosity of logging in the Output Panel. The order of levels from least verbose to most verbose is: `None` < `Error` < `Warning` < `Information` < `Debug`.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] },
"c_cpp.configuration.autoAddFileAssociations.markdownDescription": { "message": "Controls whether files are automatically added to `#files.associations#` when they are the target of a navigation operation from a C/C++ file.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] },
"c_cpp.configuration.workspaceParsingPriority.markdownDescription": { "message": "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.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] },
@@ -294,6 +301,35 @@
"c_cpp.debuggers.hardwareBreakpoints.description": "Explicit control of hardware breakpoint behavior for remote targets.",
"c_cpp.debuggers.hardwareBreakpoints.require.description": "If true, always use hardware breakpoints. Defaults to false.",
"c_cpp.debuggers.hardwareBreakpoints.limit.description": "Optional limit on the number of available hardware breakpoints to use. Only enforced when \"require\" is true and \"limit\" is greater than 0. Defaults to 0.",
"c_cpp.debuggers.variables.description": "Variables for recursive substitution in this launch configuration. Each variable may refer to others.",
"c_cpp.debuggers.variables.properties.description": "Variable for recursive substitution in this launch configuration. The value may refer to other variables.",
"c_cpp.debuggers.host.description": "Host information.",
"c_cpp.debuggers.host.user.description": "User logging into the host.",
"c_cpp.debuggers.host.hostName.description": "Host name.",
"c_cpp.debuggers.host.port.description": "SSH port on the host. Default is 22.",
"c_cpp.debuggers.host.jumpHost.description": "Connect to the target host by first making a connection to the jump hosts.",
"c_cpp.debuggers.host.localForward.description": "Forward connections to the given TCP port or Unix socket on the local (client) host to the given host and port, or Unix socket, on the remote side",
"c_cpp.debuggers.host.localForward.bindAddress.description": "Local address",
"c_cpp.debuggers.host.localForward.port.description": "Local port",
"c_cpp.debuggers.host.localForward.host.description": "Host name",
"c_cpp.debuggers.host.localForward.hostPort.description": "Host port",
"c_cpp.debuggers.host.localForward.localSocket.description": "Local socket",
"c_cpp.debuggers.host.localForward.remoteSocket.description": "Remote socket",
"c_cpp.debuggers.deploySteps.description": "Steps needed to deploy the application. Order matters.",
"c_cpp.debuggers.deploySteps.scp.description": "Copy files using SCP.",
"c_cpp.debuggers.deploySteps.scp.files.description": "Files to be copied via SCP. Supports path pattern.",
"c_cpp.debuggers.deploySteps.scp.targetDir.description": "Target directory.",
"c_cpp.debuggers.deploySteps.scp.scpPath.description": "Optional full path to SCP. Assumes SCP is on PATH if not specified",
"c_cpp.debuggers.deploySteps.debug": "If true, skip when starting without debugging. If false, skip when starting debugging. If undefined, never skip.",
"c_cpp.debuggers.deploySteps.ssh.description": "SSH command step.",
"c_cpp.debuggers.deploySteps.ssh.command.description": "Command to be executed via SSH. The command after '-c' in SSH command.",
"c_cpp.debuggers.deploySteps.ssh.sshPath.description": "Optional full path to SSH. Assumes SSH is on PATH if not specified",
"c_cpp.debuggers.deploySteps.continueOn.description": "An optional finish pattern in output. When this pattern is seen in the output, continue the deploy procedures regardless of whether this step returns.",
"c_cpp.debuggers.deploySteps.shell.description": "Shell command step.",
"c_cpp.debuggers.deploySteps.shell.command.description": "Shell command to be executed.",
"c_cpp.debuggers.vsCodeCommand.description": "VS Code command to be invoked. Can be a command in VS Code or an active extension.",
"c_cpp.debuggers.vsCodeCommand.command.description": "VS Code command to be invoked.",
"c_cpp.debuggers.vsCodeCommand.args.description": "Arguments to the VS Code command.",
"c_cpp.taskDefinitions.name.description": "The name of the task.",
"c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation.",
"c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script.",
+208 -21
View File
@@ -23,10 +23,24 @@ import { PlatformInformation } from '../platform';
import { Environment, ParsedEnvironmentFile } from './ParsedEnvironmentFile';
import { CppSettings, OtherSettings } from '../LanguageServer/settings';
import { configPrefix } from '../LanguageServer/extension';
import { expandAllStrings, ExpansionOptions, ExpansionVars } from '../expand';
import { scp, ssh } from '../SSH/commands';
import * as glob from 'glob';
import { promisify } from 'util';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
enum StepType {
scp = 'scp',
ssh = 'ssh',
shell = 'shell',
remoteShell = 'remoteShell',
command = 'command'
}
const globAsync: (pattern: string, options?: glob.IOptions | undefined) => Promise<string[]> = promisify(glob);
/*
* 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.
@@ -38,6 +52,8 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
private assetProvider: IConfigurationAssetProvider;
// Keep a list of tasks detected by cppBuildTaskProvider.
private static detectedBuildTasks: CppBuildTask[] = [];
private static detectedCppBuildTasks: CppBuildTask[] = [];
private static detectedCBuildTasks: CppBuildTask[] = [];
protected static recentBuildTaskLabel: string;
public constructor(assetProvider: IConfigurationAssetProvider, type: DebuggerType) {
@@ -95,7 +111,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
const selection: ConfigMenu | undefined = await vscode.window.showQuickPick(this.localizeConfigDetail(items), {placeHolder: localize("select.configuration", "Select a configuration")});
if (!selection) {
Telemetry.logDebuggerEvent(DebuggerEvent.debugPanel, { "debugType": "debug", "configSource": ConfigSource.unknown, "configMode": ConfigMode.unknown, "cancelled": "true", "success": "true" });
Telemetry.logDebuggerEvent(DebuggerEvent.debugPanel, { "debugType": "debug", "configSource": ConfigSource.unknown, "configMode": ConfigMode.unknown, "cancelled": "true", "succeeded": "true" });
return []; // User canceled it.
}
@@ -113,14 +129,13 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
* resolveDebugConfigurationWithSubstitutedVariables will be automatically called after this function.
*/
async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: CppDebugConfiguration, token?: vscode.CancellationToken): Promise<CppDebugConfiguration | null | undefined> {
const isIntelliSenseDisabled: boolean = new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined).intelliSenseEngine === "Disabled";
if (!config || !config.type) {
// When DebugConfigurationProviderTriggerKind is Dynamic, this function will be called with an empty config.
// Hence, providing debug configs, and start debugging should be done manually.
// resolveDebugConfiguration will be automatically called after calling provideDebugConfigurations.
const configs: CppDebugConfiguration[]= await this.provideDebugConfigurations(folder);
if (!configs || configs.length === 0) {
Telemetry.logDebuggerEvent(DebuggerEvent.debugPanel, { "debugType": DebugType.debug, "configSource": folder ? ConfigSource.workspaceFolder : ConfigSource.singleFile, "configMode": ConfigMode.noLaunchConfig, "cancelled": "true", "success": "true" });
Telemetry.logDebuggerEvent(DebuggerEvent.debugPanel, { "debugType": DebugType.debug, "configSource": folder ? ConfigSource.workspaceFolder : ConfigSource.singleFile, "configMode": ConfigMode.noLaunchConfig, "cancelled": "true", "succeeded": "true" });
return undefined; // aborts debugging silently
} else {
// Currently, we expect only one debug config to be selected.
@@ -148,6 +163,18 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
if (config.preLaunchTask) {
config.configSource = this.getDebugConfigSource(config, folder);
const isIntelliSenseDisabled: boolean = new CppSettings((vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) ? vscode.workspace.workspaceFolders[0]?.uri : undefined).intelliSenseEngine === "Disabled";
// Run the build task if IntelliSense is disabled.
if (isIntelliSenseDisabled) {
try {
await cppBuildTaskProvider.runBuildTask(config.preLaunchTask);
config.preLaunchTask = undefined;
Telemetry.logDebuggerEvent(DebuggerEvent.debugPanel, { "debugType": DebugType.debug, "configSource": config.configSource || ConfigSource.unknown, "configMode": ConfigMode.launchConfig, "cancelled": "false", "succeeded": "true" });
} catch (err) {
Telemetry.logDebuggerEvent(DebuggerEvent.debugPanel, { "debugType": DebugType.debug, "configSource": config.configSource || ConfigSource.unknown, "configMode": ConfigMode.launchConfig, "cancelled": "false", "succeeded": "false" });
}
return config;
}
let resolveByVsCode: boolean = false;
const isDebugPanel: boolean = !config.debuggerEvent || (config.debuggerEvent && config.debuggerEvent === DebuggerEvent.debugPanel);
const singleFile: boolean = config.configSource === ConfigSource.singleFile;
@@ -169,11 +196,10 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
config.debugType = config.debugType ? config.debugType : DebugType.debug;
const configMode: ConfigMode = isExistingConfig ? ConfigMode.launchConfig : ConfigMode.noLaunchConfig;
// if configuration.debuggerEvent === undefined, it means this configuration is already defined in launch.json and is shown in debugPanel.
Telemetry.logDebuggerEvent(config.debuggerEvent || DebuggerEvent.debugPanel, { "debugType": config.debugType || DebugType.debug, "configSource": config.configSource || ConfigSource.unknown, "configMode": configMode, "cancelled": "false", "success": "true" });
Telemetry.logDebuggerEvent(config.debuggerEvent || DebuggerEvent.debugPanel, { "debugType": config.debugType || DebugType.debug, "configSource": config.configSource || ConfigSource.unknown, "configMode": configMode, "cancelled": "false", "succeeded": "true" });
if (!resolveByVsCode) {
if ((singleFile || isIntelliSenseDisabled ||
(isDebugPanel && !folder && isExistingTask))) {
if ((singleFile || (isDebugPanel && !folder && isExistingTask))) {
await this.resolvePreLaunchTask(config, configMode);
config.preLaunchTask = undefined;
} else {
@@ -193,11 +219,11 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
* This hook is directly called after 'resolveDebugConfiguration' but with all variables substituted.
* This is also ran after the tasks.json has completed.
*
* Try to add all missing attributes to the debug configuration being launched.
* Try to add all missing attributes to the debug configuration being launched.
* If return "undefined", the debugging will be aborted silently.
* If return "null", the debugging will be aborted and launch.json will be opened.
*/
resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, config: CppDebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<CppDebugConfiguration> {
*/
async resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, config: CppDebugConfiguration, token?: vscode.CancellationToken): Promise<CppDebugConfiguration | null | undefined> {
if (!config || !config.type) {
return undefined; // Abort debugging silently.
}
@@ -220,7 +246,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
// Disable debug heap by default, enable if 'enableDebugHeap' is set.
if (!config.enableDebugHeap) {
const disableDebugHeapEnvSetting: Environment = {"name" : "_NO_DEBUG_HEAP", "value" : "1"};
const disableDebugHeapEnvSetting: Environment = { "name": "_NO_DEBUG_HEAP", "value": "1" };
if (config.environment && util.isArray(config.environment)) {
config.environment.push(disableDebugHeapEnvSetting);
@@ -233,6 +259,8 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
// Add environment variables from .env file
this.resolveEnvFile(config, folder);
await this.expand(config, folder);
this.resolveSourceFileMapVariables(config);
// Modify WSL config for OpenDebugAD7
@@ -295,6 +323,19 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
// logger.showOutputChannel();
}
// Run deploy steps
if (config.deploySteps && config.deploySteps.length !== 0) {
const codeVersion: number[] = vscode.version.split('.').map(num => parseInt(num, undefined));
if ((util.isNumber(codeVersion[0]) && codeVersion[0] < 1) || (util.isNumber(codeVersion[0]) && codeVersion[0] === 1 && util.isNumber(codeVersion[1]) && codeVersion[1] < 69)) {
logger.getOutputChannelLogger().showErrorMessage(localize("vs.code.1.69+.required", "'deploySteps' require VS Code 1.69+."));
return undefined;
}
const deploySucceeded: boolean = await this.deploySteps(config, token);
if (!deploySucceeded || token?.isCancellationRequested) {
return undefined;
}
}
return config;
}
@@ -439,8 +480,44 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
}
private async loadDetectedTasks(): Promise<void> {
if (!DebugConfigurationProvider.detectedBuildTasks || DebugConfigurationProvider.detectedBuildTasks.length === 0) {
DebugConfigurationProvider.detectedBuildTasks = await cppBuildTaskProvider.getTasks(true);
const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
const emptyTasks: CppBuildTask[] = [];
if (!editor) {
DebugConfigurationProvider.detectedBuildTasks = emptyTasks;
return;
}
const fileExt: string = path.extname(editor.document.fileName);
if (!fileExt) {
DebugConfigurationProvider.detectedBuildTasks = emptyTasks;
return;
}
// Don't offer tasks for header files.
const isHeader: boolean = util.isHeaderFile (editor.document.uri);
if (isHeader) {
DebugConfigurationProvider.detectedBuildTasks = emptyTasks;
return;
}
// Don't offer tasks if the active file's extension is not a recognized C/C++ extension.
const fileIsCpp: boolean = util.isCppFile(editor.document.uri);
const fileIsC: boolean = util.isCFile(editor.document.uri);
if (!(fileIsCpp || fileIsC)) {
DebugConfigurationProvider.detectedBuildTasks = emptyTasks;
return;
}
if (fileIsCpp) {
if (!DebugConfigurationProvider.detectedCppBuildTasks || DebugConfigurationProvider.detectedCppBuildTasks.length === 0) {
DebugConfigurationProvider.detectedCppBuildTasks = await cppBuildTaskProvider.getTasks(true);
}
DebugConfigurationProvider.detectedBuildTasks = DebugConfigurationProvider.detectedCppBuildTasks;
} else {
if (!DebugConfigurationProvider.detectedCBuildTasks || DebugConfigurationProvider.detectedCBuildTasks.length === 0) {
DebugConfigurationProvider.detectedCBuildTasks = await cppBuildTaskProvider.getTasks(true);
}
DebugConfigurationProvider.detectedBuildTasks = DebugConfigurationProvider.detectedCBuildTasks;
}
}
@@ -547,17 +624,17 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
const newSourceFileMapTarget: string = util.resolveVariables(sourceFileMapTarget, undefined);
if (sourceFileMapTarget !== newSourceFileMapTarget) {
// Add a space if source was changed, else just tab the target message.
message += (message ? ' ' : '\t');
message += (message ? ' ' : '\t');
message += localize("replacing.targetpath", "Replacing {0} '{1}' with '{2}'.", "targetPath", sourceFileMapTarget, newSourceFileMapTarget);
target = newSourceFileMapTarget;
}
} else if (util.isObject(sourceFileMapTarget)) {
const newSourceFileMapTarget: {"editorPath": string; "useForBreakpoints": boolean } = sourceFileMapTarget;
const newSourceFileMapTarget: { "editorPath": string; "useForBreakpoints": boolean } = sourceFileMapTarget;
newSourceFileMapTarget["editorPath"] = util.resolveVariables(sourceFileMapTarget["editorPath"], undefined);
if (sourceFileMapTarget !== newSourceFileMapTarget) {
// Add a space if source was changed, else just tab the target message.
message += (message ? ' ' : '\t');
message += (message ? ' ' : '\t');
message += localize("replacing.editorPath", "Replacing {0} '{1}' with '{2}'.", "editorPath", sourceFileMapTarget, newSourceFileMapTarget["editorPath"]);
target = newSourceFileMapTarget;
}
@@ -753,7 +830,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
}
const selectedConfig: vscode.DebugConfiguration | undefined = await this.selectConfiguration(textEditor, false, true);
if (!selectedConfig) {
Telemetry.logDebuggerEvent(DebuggerEvent.addConfigGear, { "configSource": ConfigSource.workspaceFolder, "configMode": ConfigMode.launchConfig, "cancelled": "true", "success": "true" });
Telemetry.logDebuggerEvent(DebuggerEvent.addConfigGear, { "configSource": ConfigSource.workspaceFolder, "configMode": ConfigMode.launchConfig, "cancelled": "true", "succeeded": "true" });
return; // User canceled it.
}
@@ -770,7 +847,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
selectedConfig.debuggerEvent = undefined;
// Write debug configuration in launch.json file.
await this.writeDebugConfig(selectedConfig, isExistingConfig, folder);
Telemetry.logDebuggerEvent(DebuggerEvent.addConfigGear, { "configSource": ConfigSource.workspaceFolder, "configMode": ConfigMode.launchConfig, "cancelled": "false", "success": "true" });
Telemetry.logDebuggerEvent(DebuggerEvent.addConfigGear, { "configSource": ConfigSource.workspaceFolder, "configMode": ConfigMode.launchConfig, "cancelled": "false", "succeeded": "true" });
}
public async buildAndRun(textEditor: vscode.TextEditor): Promise<void> {
@@ -782,7 +859,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
let folder: vscode.WorkspaceFolder | undefined = vscode.workspace.getWorkspaceFolder(textEditor.document.uri);
const selectedConfig: CppDebugConfiguration | undefined = await this.selectConfiguration(textEditor);
if (!selectedConfig) {
Telemetry.logDebuggerEvent(DebuggerEvent.playButton, { "debugType": debugModeOn ? DebugType.debug : DebugType.run, "configSource": ConfigSource.unknown, "cancelled": "true", "success": "true" });
Telemetry.logDebuggerEvent(DebuggerEvent.playButton, { "debugType": debugModeOn ? DebugType.debug : DebugType.run, "configSource": ConfigSource.unknown, "cancelled": "true", "succeeded": "true" });
return; // User canceled it.
}
@@ -796,7 +873,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
}
selectedConfig.debugType = debugModeOn ? DebugType.debug : DebugType.run;
// startDebugging will trigger a call to resolveDebugConfiguration.
await vscode.debug.startDebugging(folder, selectedConfig, {noDebug: !debugModeOn});
await vscode.debug.startDebugging(folder, selectedConfig, { noDebug: !debugModeOn });
}
private async selectConfiguration(textEditor: vscode.TextEditor, pickDefault: boolean = true, onlyWorkspaceFolder: boolean = false): Promise<CppDebugConfiguration | undefined> {
@@ -860,10 +937,120 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
if (e && e.message === util.failedToParseJson) {
vscode.window.showErrorMessage(util.failedToParseJson);
}
Telemetry.logDebuggerEvent(config.debuggerEvent || DebuggerEvent.debugPanel, { "debugType": config.debugType || DebugType.debug, "configSource": config.configSource || ConfigSource.unknown, "configMode": configMode, "cancelled": "false", "success": "false" });
Telemetry.logDebuggerEvent(config.debuggerEvent || DebuggerEvent.debugPanel, { "debugType": config.debugType || DebugType.debug, "configSource": config.configSource || ConfigSource.unknown, "configMode": configMode, "cancelled": "false", "succeeded": "false" });
}
}
}
private async expand(config: vscode.DebugConfiguration, folder: vscode.WorkspaceFolder | undefined): Promise<void> {
const folderPath: string | undefined = folder?.uri.fsPath || vscode.workspace.workspaceFolders?.[0].uri.fsPath;
const vars: ExpansionVars = config.variables ? config.variables : {};
vars.workspaceFolder = folderPath || '{workspaceFolder}';
vars.workspaceFolderBasename = folderPath ? path.basename(folderPath) : '{workspaceFolderBasename}';
const expansionOptions: ExpansionOptions = { vars, recursive: true };
return expandAllStrings(config, expansionOptions);
}
// Returns true when ALL steps succeed; stop all subsequent steps if one fails
private async deploySteps(config: vscode.DebugConfiguration, cancellationToken?: vscode.CancellationToken): Promise<boolean> {
let succeeded: boolean = true;
const deployStart: number = new Date().getTime();
for (const step of config.deploySteps) {
succeeded = await this.singleDeployStep(config, step, cancellationToken);
if (!succeeded) {
break;
}
}
const deployEnd: number = new Date().getTime();
const telemetryProperties: { [key: string]: string } = {
Succeeded: `${succeeded}`,
IsDebugging: `${!config.noDebug || false}`
};
const telemetryMetrics: { [key: string]: number } = {
NumSteps: config.deploySteps.length,
Duration: deployEnd - deployStart
};
Telemetry.logDebuggerEvent('deploy', telemetryProperties, telemetryMetrics);
return succeeded;
}
private async singleDeployStep(config: vscode.DebugConfiguration, step: any, cancellationToken?: vscode.CancellationToken): Promise<boolean> {
if ((config.noDebug && step.debug === true) || (!config.noDebug && step.debug === false)) {
// Skip steps that doesn't match current launch mode. Explicit true/false check, since a step is always run when debug is undefined.
return true;
}
switch (step.type) {
case StepType.command: {
// VS Code commands are the same regardless of which extension invokes them, so just invoke them here.
if (step.args && !Array.isArray(step.args)) {
logger.getOutputChannelLogger().showErrorMessage(localize('command.args.must.be.array', '"args" in command deploy step must be an array.'));
return false;
}
const returnCode: unknown = await vscode.commands.executeCommand(step.command, ...step.args);
return !returnCode;
}
case StepType.scp: {
if (!step.files || !step.targetDir || !step.host) {
logger.getOutputChannelLogger().showErrorMessage(localize('missing.properties.scp', '"host", "files", and "targetDir" are required in scp steps.'));
return false;
}
const host: util.ISshHostInfo = { hostName: step.host.hostName, user: step.host.user, port: step.host.port };
const jumpHosts: util.ISshHostInfo[] = step.host.jumpHosts;
let files: vscode.Uri[] = [];
if (util.isString(step.files)) {
files = files.concat((await globAsync(step.files)).map(file => vscode.Uri.file(file)));
} else if (util.isArrayOfString(step.files)) {
for (const fileGlob of (step.files as string[])) {
files = files.concat((await globAsync(fileGlob)).map(file => vscode.Uri.file(file)));
}
} else {
logger.getOutputChannelLogger().showErrorMessage(localize('incorrect.files.type.scp', '"files" must be a string or an array of strings in scp steps.'));
return false;
}
const scpResult: util.ProcessReturnType = await scp(files, host, step.targetDir, config.scpPath, jumpHosts, cancellationToken);
if (!scpResult.succeeded || cancellationToken?.isCancellationRequested) {
return false;
}
break;
}
case StepType.ssh: {
if (!step.host || !step.command) {
logger.getOutputChannelLogger().showErrorMessage(localize('missing.properties.ssh', '"host" and "command" are required for ssh steps.'));
return false;
}
const host: util.ISshHostInfo = { hostName: step.host.hostName, user: step.host.user, port: step.host.port };
const jumpHosts: util.ISshHostInfo[] = step.host.jumpHosts;
const localForwards: util.ISshLocalForwardInfo[] = step.host.localForwards;
const continueOn: string = step.continueOn;
const sshResult: util.ProcessReturnType = await ssh(host, step.command, config.sshPath, jumpHosts, localForwards, continueOn, cancellationToken);
if (!sshResult.succeeded || cancellationToken?.isCancellationRequested) {
return false;
}
break;
}
case StepType.shell: {
if (!step.command) {
logger.getOutputChannelLogger().showErrorMessage(localize('missing.properties.shell', '"command" is required for shell steps.'));
return false;
}
const taskResult: util.ProcessReturnType = await util.spawnChildProcess(step.command, undefined, step.continueOn);
if (!taskResult.succeeded || cancellationToken?.isCancellationRequested) {
logger.getOutputChannelLogger().showErrorMessage(taskResult.output);
return false;
}
break;
}
default: {
logger.getOutputChannelLogger().appendLine(localize('deploy.step.type.not.supported', 'Deploy step type {0} is not supported.', step.type));
return false;
}
}
return true;
}
}
export interface IConfigurationAssetProvider {
@@ -1016,7 +1203,7 @@ export class ConfigurationSnippetProvider implements vscode.CompletionItemProvid
items = [];
// Make a copy of each snippet since we are adding a comma to the end of the insertText.
this.snippets.forEach((item) => items.push({...item}));
this.snippets.forEach((item) => items.push({ ...item }));
items.map((item) => {
item.insertText = item.insertText + ','; // Add comma
@@ -4,13 +4,12 @@
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { Position, Range, RequestType, TextEdit } from 'vscode-languageclient';
import * as util from '../../common';
import { DefaultClient } from '../client';
import { CodeActionCodeInfo, CodeActionDiagnosticInfo, codeAnalysisFileToCodeActions, codeAnalysisCodeToFixes,
codeAnalysisAllFixes, DefaultClient } from '../client';
codeAnalysisAllFixes } from '../codeAnalysis';
import { makeVscodeRange } from '../utils';
import { CppSettings } from '../settings';
type LocalizeStringParams = util.LocalizeStringParams;
import { getLocalizedString, LocalizeStringParams } from '../localization';
interface GetCodeActionsRequestParams {
uri: string;
@@ -62,7 +61,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
// Convert to vscode.CodeAction array
commands.forEach((command) => {
const title: string = util.getLocalizedString(command.localizeStringParams);
const title: string = getLocalizedString(command.localizeStringParams);
let wsEdit: vscode.WorkspaceEdit | undefined;
let codeActionKind: vscode.CodeActionKind = vscode.CodeActionKind.QuickFix;
if (command.edit) {
@@ -4,9 +4,9 @@
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { DefaultClient, LocalizeDocumentSymbol, GetDocumentSymbolRequestParams, GetDocumentSymbolRequest, SymbolScope } from '../client';
import * as util from '../../common';
import { processDelayedDidOpen } from '../extension';
import { makeVscodeRange } from '../utils';
import { getLocalizedString, getLocalizedSymbolScope } from '../localization';
export class DocumentSymbolProvider implements vscode.DocumentSymbolProvider {
private client: DefaultClient;
@@ -17,18 +17,18 @@ export class DocumentSymbolProvider implements vscode.DocumentSymbolProvider {
const documentSymbols: vscode.DocumentSymbol[] = [];
if (symbols) {
symbols.forEach((symbol) => {
let detail: string = util.getLocalizedString(symbol.detail);
let detail: string = getLocalizedString(symbol.detail);
if (symbol.scope === SymbolScope.Private) {
if (detail.length === 0) {
detail = "private";
} else {
detail = util.getLocalizedSymbolScope("private", detail);
detail = getLocalizedSymbolScope("private", detail);
}
} else if (symbol.scope === SymbolScope.Protected) {
if (detail.length === 0) {
detail = "protected";
} else {
detail = util.getLocalizedSymbolScope("protected", detail);
detail = getLocalizedSymbolScope("protected", detail);
}
}
@@ -0,0 +1,163 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { DefaultClient, openFileVersions } from '../client';
import { Position, RequestType } from 'vscode-languageclient';
import { CppSettings } from '../settings';
interface GetInlayHintsParams {
uri: string;
}
enum InlayHintKind {
Type = 0,
Parameter = 1,
}
interface CppInlayHint {
position: Position;
label: string;
inlayHintKind: InlayHintKind;
isValueRef: boolean;
hasParamName: boolean;
leftPadding: boolean;
rightPadding: boolean;
identifierLength: number;
}
interface GetInlayHintsResult {
fileVersion: number;
canceled: boolean;
inlayHints: CppInlayHint[];
}
type InlayHintsCacheEntry = {
FileVersion: number;
TypeHints: vscode.InlayHint[];
ParameterHints: CppInlayHint[];
};
const GetInlayHintsRequest: RequestType<GetInlayHintsParams, GetInlayHintsResult, void, void> =
new RequestType<GetInlayHintsParams, GetInlayHintsResult, void, void>('cpptools/getInlayHints');
export class InlayHintsProvider implements vscode.InlayHintsProvider {
private client: DefaultClient;
public onDidChangeInlayHintsEvent = new vscode.EventEmitter<void>();
public onDidChangeInlayHints?: vscode.Event<void>;
private cache: Map<string, InlayHintsCacheEntry> = new Map<string, InlayHintsCacheEntry>();
constructor(client: DefaultClient) {
this.client = client;
this.onDidChangeInlayHints = this.onDidChangeInlayHintsEvent.event;
}
public async provideInlayHints(document: vscode.TextDocument, range: vscode.Range,
token: vscode.CancellationToken): Promise<vscode.InlayHint[] | undefined> {
await this.client.awaitUntilLanguageClientReady();
const uriString: string = document.uri.toString();
// Get results from cache if available.
const cacheEntry: InlayHintsCacheEntry | undefined = this.cache.get(uriString);
if (cacheEntry?.FileVersion === document.version) {
return this.buildVSCodeHints(cacheEntry);
}
// Get new results from the language server
const params: GetInlayHintsParams = { uri: uriString };
const inlayHintsResult: GetInlayHintsResult = await this.client.languageClient.sendRequest(GetInlayHintsRequest, params, token);
if (!inlayHintsResult.canceled) {
if (inlayHintsResult.fileVersion === openFileVersions.get(uriString)) {
const cacheEntry: InlayHintsCacheEntry = this.createCacheEntry(inlayHintsResult);
this.cache.set(uriString, cacheEntry);
return this.buildVSCodeHints(cacheEntry);
} else {
// Force another request because file versions do not match.
this.onDidChangeInlayHintsEvent.fire();
}
}
return undefined;
}
public invalidateFile(uri: string): void {
this.cache.delete(uri);
this.onDidChangeInlayHintsEvent.fire();
}
private buildVSCodeHints(cacheEntry: InlayHintsCacheEntry): vscode.InlayHint[] {
let result: vscode.InlayHint[] = [];
const settings: CppSettings = new CppSettings();
if (settings.inlayHintsAutoDeclarationTypes) {
result = result.concat(cacheEntry?.TypeHints);
}
const resolvedParameterHints: vscode.InlayHint[] = this.resolveParameterHints(cacheEntry.ParameterHints);
result = result.concat(resolvedParameterHints);
return result;
}
private resolveParameterHints(hints: CppInlayHint[]): vscode.InlayHint[] {
const resolvedHints: vscode.InlayHint[] = [];
const settings: CppSettings = new CppSettings();
for (const hint of hints) {
// Build parameter label based on settings.
let paramHintLabel: string = "";
if (settings.inlayHintsParameterNames) {
paramHintLabel = (settings.inlayHintsParameterNamesSuppressName && hint.hasParamName) ? "" : hint.label;
if (paramHintLabel !== "" && settings.inlayHintsParameterNamesHideLeadingUnderscores) {
let nonUnderscoreIndex: number = 0;
for (let i: number = 0; i < paramHintLabel.length; ++i) {
if (paramHintLabel[i] !== '_') {
nonUnderscoreIndex = i;
break;
}
}
if (nonUnderscoreIndex > 0) {
paramHintLabel = paramHintLabel.substring(nonUnderscoreIndex);
}
}
}
let refOperatorString: string = "";
if (settings.inlayHintsReferenceOperator && hint.isValueRef) {
refOperatorString = (paramHintLabel.length > 0 && settings.inlayHintsReferenceOperatorShowSpace) ? "& " : "&";
}
let label: string = "";
if (paramHintLabel.length > 0 || refOperatorString.length > 0) {
label = refOperatorString + paramHintLabel + ":";
}
const inlayHint: vscode.InlayHint = new vscode.InlayHint(
new vscode.Position(hint.position.line, hint.position.character),
label,
vscode.InlayHintKind.Parameter);
inlayHint.paddingRight = true;
resolvedHints.push(inlayHint);
};
return resolvedHints;
}
private createCacheEntry(inlayHintsResults: GetInlayHintsResult): InlayHintsCacheEntry {
const typeHints: vscode.InlayHint[] = [];
const settings: CppSettings = new CppSettings();
for (const h of inlayHintsResults.inlayHints) {
if (h.inlayHintKind === InlayHintKind.Type) {
const showOnLeft: boolean = settings.inlayHintsAutoDeclarationTypesShowOnLeft && h.identifierLength > 0;
const inlayHint: vscode.InlayHint = new vscode.InlayHint(
new vscode.Position(h.position.line, h.position.character +
(showOnLeft ? 0 : h.identifierLength)),
(showOnLeft ? h.label : ": " + h.label),
vscode.InlayHintKind.Type);
inlayHint.paddingRight = showOnLeft || h.rightPadding;
inlayHint.paddingLeft = showOnLeft && h.leftPadding;
typeHints.push(inlayHint);
}
}
const paramHints: CppInlayHint[] = inlayHintsResults.inlayHints.filter(h => h.inlayHintKind === InlayHintKind.Parameter);
const cacheEntry: InlayHintsCacheEntry = {
FileVersion: inlayHintsResults.fileVersion,
TypeHints: typeHints,
ParameterHints: paramHints
};
return cacheEntry;
}
}
@@ -5,7 +5,7 @@
import * as vscode from 'vscode';
import { DefaultClient, GetSymbolInfoRequest, WorkspaceSymbolParams, LocalizeSymbolInformation, SymbolScope } from '../client';
import { makeVscodeLocation } from '../utils';
import * as util from '../../common';
import { getLocalizedString, getLocalizedSymbolScope } from '../localization';
export class WorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
private client: DefaultClient;
@@ -23,13 +23,13 @@ export class WorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
// Convert to vscode.Command array
symbols.forEach((symbol) => {
let suffix: string = util.getLocalizedString(symbol.suffix);
let suffix: string = getLocalizedString(symbol.suffix);
let name: string = symbol.name;
if (suffix.length) {
if (symbol.scope === SymbolScope.Private) {
suffix = util.getLocalizedSymbolScope("private", suffix);
suffix = getLocalizedSymbolScope("private", suffix);
} else if (symbol.scope === SymbolScope.Protected) {
suffix = util.getLocalizedSymbolScope("protected", suffix);
suffix = getLocalizedSymbolScope("protected", suffix);
}
name = name + ' (' + suffix + ')';
} else {
+41 -551
View File
@@ -7,7 +7,7 @@
import * as path from 'path';
import * as vscode from 'vscode';
// Importing providers here
// Start provider imports
import { OnTypeFormattingEditProvider } from './Providers/onTypeFormattingEditProvider';
import { FoldingRangeProvider } from './Providers/foldingRangeProvider';
import { SemanticTokensProvider } from './Providers/semanticTokensProvider';
@@ -18,13 +18,16 @@ import { WorkspaceSymbolProvider } from './Providers/workspaceSymbolProvider';
import { RenameProvider } from './Providers/renameProvider';
import { FindAllReferencesProvider } from './Providers/findAllReferencesProvider';
import { CodeActionProvider } from './Providers/codeActionProvider';
import { InlayHintsProvider } from './Providers/inlayHintProvider';
// End provider imports
import { LanguageClient, LanguageClientOptions, ServerOptions, NotificationType, TextDocumentIdentifier, RequestType, ErrorAction, CloseAction, DidOpenTextDocumentParams, Range, Position, DocumentFilter } from 'vscode-languageclient';
import { SourceFileConfigurationItem, WorkspaceBrowseConfiguration, SourceFileConfiguration, Version } from 'vscode-cpptools';
import { Status, IntelliSenseStatus } from 'vscode-cpptools/out/testApi';
import { getLocaleId, getLocalizedString, LocalizeStringParams } from './localization';
import { Location, TextEdit } from './commonTypes';
import { makeVscodeRange, makeVscodeLocation } from './utils';
import * as util from '../common';
import { Location, makeVscodeRange, makeVscodeLocation, makeVscodeTextEdits, rangeEquals, TextEdit } from './utils';
import * as configs from './configurations';
import { CppSettings, getEditorConfigSettings, OtherSettings } from './settings';
import * as telemetry from '../telemetry';
@@ -34,7 +37,6 @@ import { ClientCollection } from './clientCollection';
import { createProtocolFilter } from './protocolFilter';
import { DataBinding } from './dataBinding';
import minimatch = require("minimatch");
import * as logger from '../logger';
import { updateLanguageConfigurations, CppSourceStr } from './extension';
import { SettingsTracker, getTracker } from './settingsTracker';
import { getTestHook, TestHook } from '../testHook';
@@ -44,10 +46,12 @@ import * as os from 'os';
import * as refs from './references';
import * as nls from 'vscode-nls';
import { lookupString, localizedStringCount } from '../nativeStrings';
import { CodeAnalysisDiagnosticIdentifiersAndUri, RegisterCodeAnalysisNotifications, removeAllCodeAnalysisProblems,
removeCodeAnalysisProblems, RemoveCodeAnalysisProblemsParams } from './codeAnalysis';
import { DebugProtocolParams, getDiagnosticsChannel, getOutputChannelLogger, logDebugProtocol, Logger, logLocalized, showWarning, ShowWarningParams } from '../logger';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
type LocalizeStringParams = util.LocalizeStringParams;
let ui: UI;
let timeStamp: number = 0;
@@ -60,78 +64,7 @@ const languageClientCrashTimes: number[] = [];
let clientCollection: ClientCollection;
let pendingTask: util.BlockingTask<any> | undefined;
let compilerDefaults: configs.CompilerDefaults;
let diagnosticsChannel: vscode.OutputChannel;
let outputChannel: vscode.OutputChannel;
let debugChannel: vscode.OutputChannel;
let warningChannel: vscode.OutputChannel;
let diagnosticsCollectionIntelliSense: vscode.DiagnosticCollection;
let diagnosticsCollectionCodeAnalysis: vscode.DiagnosticCollection;
export interface CodeActionDiagnosticInfo {
version: number; // Needed due to https://github.com/microsoft/vscode/issues/148723 .
// Used to work around https://github.com/microsoft/vscode/issues/126393.
// If that bug were fixed, then we could use the vscode.CodeAction.diagnostic directly.
range: vscode.Range;
code: string;
fixCodeAction?: vscode.CodeAction;
// suppressCodeAction?: vscode.CodeAction; // TODO?
removeCodeAction?: vscode.CodeAction;
}
// Used to handle fix invalidation after an edit,
// i.e. it's set to undefined if it becomes invalid.
interface CodeActionWorkspaceEdit {
workspaceEdit?: vscode.WorkspaceEdit;
}
interface CodeActionPerUriInfo {
// These two arrays have the same length, i.e. index i of identifiers
// is used to index into workspaceEdits to get the corresponding edit.
identifiers: CodeAnalysisDiagnosticIdentifier[];
workspaceEdits?: CodeActionWorkspaceEdit[];
// Used to quickly determine how many non-undefined entries are in "workspaceEdits"
// (so the array doesn't have to be iterated through).
numValidWorkspaceEdits: number;
}
// Tracks the "type" code actions (i.e. "code" is a synonym for "type" in this context).
export interface CodeActionCodeInfo {
version: number; // Needed due to https://github.com/microsoft/vscode/issues/148723 .
// Needed to quickly update the "type" action for a file.
uriToInfo: Map<string, CodeActionPerUriInfo>;
fixAllTypeCodeAction?: vscode.CodeAction;
disableAllTypeCodeAction?: vscode.CodeAction;
removeAllTypeCodeAction?: vscode.CodeAction;
docCodeAction?: vscode.CodeAction;
}
interface CodeActionAllInfo {
version: number; // Needed due to https://github.com/microsoft/vscode/issues/148723 .
fixAllCodeAction: vscode.CodeAction;
removeAllCodeAction: vscode.CodeAction;
}
export const codeAnalysisFileToCodeActions: Map<string, CodeActionDiagnosticInfo[]> = new Map<string, CodeActionDiagnosticInfo[]>();
export const codeAnalysisCodeToFixes: Map<string, CodeActionCodeInfo> = new Map<string, CodeActionCodeInfo>();
export const codeAnalysisAllFixes: CodeActionAllInfo = {
version: 0,
fixAllCodeAction: {
title: localize("fix_all_code_analysis_problems", "Fix all code analysis problems"),
command: { title: 'FixAllCodeAnalysisProblems', command: 'C_Cpp.FixAllCodeAnalysisProblems',
arguments: [ 0, undefined, true, [] ] },
kind: vscode.CodeActionKind.QuickFix
},
removeAllCodeAction: {
title: localize("clear_all_code_analysis_problems", "Clear all code analysis problems"),
command: { title: "RemoveAllCodeAnalysisProblems", command: "C_Cpp.RemoveAllCodeAnalysisProblems" },
kind: vscode.CodeActionKind.QuickFix
}
};
let workspaceDisposables: vscode.Disposable[] = [];
export let workspaceReferences: refs.ReferencesManager;
@@ -154,38 +87,16 @@ function logTelemetry(notificationBody: TelemetryPayload): void {
function setupOutputHandlers(): void {
console.assert(languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
languageClient.onNotification(DebugProtocolNotification, (output) => {
if (!debugChannel) {
debugChannel = vscode.window.createOutputChannel(`${localize("c.cpp.debug.protocol", "C/C++ Debug Protocol")}`);
workspaceDisposables.push(debugChannel);
}
debugChannel.appendLine("");
debugChannel.appendLine("************************************************************************************************************************");
debugChannel.append(`${output}`);
});
languageClient.onNotification(DebugProtocolNotification, logDebugProtocol);
languageClient.onNotification(DebugLogNotification, logLocalized);
}
function log(output: string): void {
if (!outputChannel) {
outputChannel = logger.getOutputChannel();
workspaceDisposables.push(outputChannel);
}
outputChannel.appendLine(`${output}`);
}
function logLocalized(params: LocalizeStringParams): void {
const output: string = util.getLocalizedString(params);
log(output);
}
/** Note: We should not await on the following functions,
* or any funstion that returns a promise acquired from them,
* vscode.window.showInformationMessage, vscode.window.showWarningMessage, vscode.window.showErrorMessage
*/
function showMessageWindow(params: ShowMessageWindowParams): void {
const message: string = util.getLocalizedString(params.localizeStringParams);
const message: string = getLocalizedString(params.localizeStringParams);
switch (params.type) {
case 1: // Error
vscode.window.showErrorMessage(message);
@@ -202,21 +113,6 @@ function showMessageWindow(params: ShowMessageWindowParams): void {
}
}
function showWarning(params: ShowWarningParams): void {
const message: string = util.getLocalizedString(params.localizeStringParams);
let showChannel: boolean = false;
if (!warningChannel) {
warningChannel = vscode.window.createOutputChannel(`${localize("c.cpp.warnings", "C/C++ Configuration Warnings")}`);
workspaceDisposables.push(warningChannel);
showChannel = true;
}
// Append before showing the channel, to avoid a delay.
warningChannel.appendLine(`[${new Date().toLocaleString()}] ${message}`);
if (showChannel) {
warningChannel.show(true);
}
}
function publishIntelliSenseDiagnostics(params: PublishIntelliSenseDiagnosticsParams): void {
if (!diagnosticsCollectionIntelliSense) {
diagnosticsCollectionIntelliSense = vscode.languages.createDiagnosticCollection(CppSourceStr);
@@ -225,7 +121,7 @@ function publishIntelliSenseDiagnostics(params: PublishIntelliSenseDiagnosticsPa
// Convert from our Diagnostic objects to vscode Diagnostic objects
const diagnosticsIntelliSense: vscode.Diagnostic[] = [];
params.diagnostics.forEach((d) => {
const message: string = util.getLocalizedString(d.localizeStringParams);
const message: string = getLocalizedString(d.localizeStringParams);
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(makeVscodeRange(d.range), message, d.severity);
diagnostic.code = d.code;
diagnostic.source = CppSourceStr;
@@ -245,328 +141,6 @@ function publishIntelliSenseDiagnostics(params: PublishIntelliSenseDiagnosticsPa
clientCollection.timeTelemetryCollector.setUpdateRangeTime(realUri);
}
// Rebuild codeAnalysisCodeToFixes and codeAnalysisAllFixes.fixAllCodeActions.
function rebuildCodeAnalysisCodeAndAllFixes(): void {
if (codeAnalysisAllFixes.fixAllCodeAction.command?.arguments !== undefined) {
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[0] = ++codeAnalysisAllFixes.version;
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[1] = undefined;
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[3] = [];
}
const identifiersAndUrisForAllFixes: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
const uriToEditsForAll: Map<vscode.Uri, vscode.TextEdit[]> = new Map<vscode.Uri, vscode.TextEdit[]>();
let numFixTypes: number = 0;
for (const codeToFixes of codeAnalysisCodeToFixes) {
const identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
const uriToEdits: Map<vscode.Uri, vscode.TextEdit[]> = new Map<vscode.Uri, vscode.TextEdit[]>();
codeToFixes[1].uriToInfo.forEach((perUriInfo: CodeActionPerUriInfo, uri: string) => {
const newIdentifiersAndUri: CodeAnalysisDiagnosticIdentifiersAndUri = { uri: uri, identifiers: perUriInfo.identifiers };
identifiersAndUris.push(newIdentifiersAndUri);
if (perUriInfo.workspaceEdits === undefined || perUriInfo.numValidWorkspaceEdits === 0) {
return;
}
identifiersAndUrisForAllFixes.push(newIdentifiersAndUri);
for (const edit of perUriInfo.workspaceEdits) {
if (edit.workspaceEdit === undefined) {
continue;
}
for (const [uri, edits] of edit.workspaceEdit.entries()) {
const textEdits: vscode.TextEdit[] = uriToEdits.get(uri) ?? [];
textEdits.push(...edits);
uriToEdits.set(uri, textEdits);
const textEditsForAll: vscode.TextEdit[] = uriToEditsForAll.get(uri) ?? [];
textEditsForAll.push(...edits);
uriToEditsForAll.set(uri, textEdits);
}
}
});
if (uriToEdits.size > 0) {
const allTypeWorkspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
for (const [uri, edits] of uriToEdits.entries()) {
allTypeWorkspaceEdit.set(uri, edits);
}
++numFixTypes;
codeToFixes[1].fixAllTypeCodeAction = {
title: localize("fix_all_type_problems", "Fix all {0} problems", codeToFixes[0]),
command: { title: 'FixAllTypeCodeAnalysisProblems', command: 'C_Cpp.FixAllTypeCodeAnalysisProblems',
arguments: [ codeToFixes[0], ++codeToFixes[1].version, allTypeWorkspaceEdit, true, identifiersAndUris ] },
kind: vscode.CodeActionKind.QuickFix
};
}
if (new CppSettings().clangTidyCodeActionShowDisable) {
codeToFixes[1].disableAllTypeCodeAction = {
title: localize("disable_all_type_problems", "Disable all {0} problems", codeToFixes[0]),
command: { title: 'DisableAllTypeCodeAnalysisProblems', command: 'C_Cpp.DisableAllTypeCodeAnalysisProblems',
arguments: [ codeToFixes[0], identifiersAndUris ] },
kind: vscode.CodeActionKind.QuickFix
};
} else {
codeToFixes[1].disableAllTypeCodeAction = undefined;
}
if (new CppSettings().clangTidyCodeActionShowClear !== "None") {
codeToFixes[1].removeAllTypeCodeAction = {
title: localize("clear_all_type_problems", "Clear all {0} problems", codeToFixes[0]),
command: { title: 'RemoveAllTypeCodeAnalysisProblems', command: 'C_Cpp.RemoveCodeAnalysisProblems',
arguments: [ false, identifiersAndUris ] },
kind: vscode.CodeActionKind.QuickFix
};
}
}
if (numFixTypes > 1) {
const allWorkspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
for (const [uri, edits] of uriToEditsForAll.entries()) {
allWorkspaceEdit.set(uri, edits);
}
if (codeAnalysisAllFixes.fixAllCodeAction.command?.arguments !== undefined) {
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[1] = allWorkspaceEdit;
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[3] = identifiersAndUrisForAllFixes;
}
} else {
if (codeAnalysisAllFixes.fixAllCodeAction.command?.arguments !== undefined) {
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[1] = undefined;
}
}
}
function publishCodeAnalysisDiagnostics(params: PublishCodeAnalysisDiagnosticsParams): void {
if (!diagnosticsCollectionCodeAnalysis) {
diagnosticsCollectionCodeAnalysis = vscode.languages.createDiagnosticCollection("clang-tidy");
}
// Convert from our Diagnostic objects to vscode Diagnostic objects
const diagnosticsCodeAnalysis: vscode.Diagnostic[] = [];
const realUri: vscode.Uri = vscode.Uri.parse(params.uri);
// Reset codeAnalysisCodeToFixes for the file.
for (const codeToFixes of codeAnalysisCodeToFixes) {
++codeToFixes[1].version;
if (codeToFixes[1].uriToInfo.has(params.uri)) {
codeToFixes[1].uriToInfo.delete(params.uri);
}
}
const previousDiagnostics: CodeActionDiagnosticInfo[] | undefined = codeAnalysisFileToCodeActions.get(params.uri);
let nextVersion: number = 0;
if (previousDiagnostics !== undefined) {
for (const diagnostic of previousDiagnostics) {
if (diagnostic.version > nextVersion) {
nextVersion = diagnostic.version;
}
}
}
++nextVersion;
const codeActionDiagnosticInfo: CodeActionDiagnosticInfo[] = [];
for (const d of params.diagnostics) {
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(makeVscodeRange(d.range),
util.getLocalizedString(d.localizeStringParams), d.severity);
const identifier: CodeAnalysisDiagnosticIdentifier = { range: d.range, code: d.code };
const identifiersAndUri: CodeAnalysisDiagnosticIdentifiersAndUri = { uri: params.uri, identifiers: [ identifier ] };
const codeAction: CodeActionDiagnosticInfo = {
version: nextVersion,
range: makeVscodeRange(identifier.range),
code: identifier.code,
removeCodeAction: {
title: localize("clear_this_problem", "Clear this {0} problem", d.code),
command: { title: 'RemoveCodeAnalysisProblems', command: 'C_Cpp.RemoveCodeAnalysisProblems',
arguments: [ false, [ identifiersAndUri ] ] },
kind: vscode.CodeActionKind.QuickFix
}
};
const workspaceEdit: CodeActionWorkspaceEdit = {};
if (d.workspaceEdit) {
workspaceEdit.workspaceEdit = new vscode.WorkspaceEdit();
for (const [uriStr, edits] of Object.entries(d.workspaceEdit.changes)) {
workspaceEdit.workspaceEdit.set(vscode.Uri.parse(uriStr, true), makeVscodeTextEdits(edits));
}
const fixThisCodeAction: vscode.CodeAction = {
title: localize("fix_this_problem", "Fix this {0} problem", d.code),
command: { title: 'FixThisCodeAnalysisProblem', command: 'C_Cpp.FixThisCodeAnalysisProblem',
arguments: [ nextVersion, workspaceEdit.workspaceEdit, true, [ identifiersAndUri ] ] },
kind: vscode.CodeActionKind.QuickFix
};
codeAction.fixCodeAction = fixThisCodeAction;
}
// Edits from clang-tidy can be associated with the related information instead of the root diagnostic.
const relatedCodeActions: CodeActionDiagnosticInfo[] = [];
const rootAndRelatedWorkspaceEdits: CodeActionWorkspaceEdit[] = [];
const rootAndRelatedIdentifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
if (workspaceEdit.workspaceEdit !== undefined) {
rootAndRelatedWorkspaceEdits.push(workspaceEdit);
rootAndRelatedIdentifiersAndUris.push(identifiersAndUri);
}
if (d.relatedInformation) {
diagnostic.relatedInformation = [];
for (const info of d.relatedInformation) {
diagnostic.relatedInformation.push(new vscode.DiagnosticRelatedInformation(makeVscodeLocation(info.location), info.message));
if (info.workspaceEdit === undefined) {
continue;
}
const relatedWorkspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
for (const [uriStr, edits] of Object.entries(info.workspaceEdit.changes)) {
relatedWorkspaceEdit.set(vscode.Uri.parse(uriStr, true), makeVscodeTextEdits(edits));
}
const relatedIdentifier: CodeAnalysisDiagnosticIdentifier = { range: info.location.range, code: d.code };
const relatedIdentifiersAndUri: CodeAnalysisDiagnosticIdentifiersAndUri = {
uri: info.location.uri, identifiers: [ relatedIdentifier ] };
const relatedCodeAction: vscode.CodeAction = {
title: localize("fix_this_problem", "Fix this {0} problem", d.code),
command: { title: 'FixThisCodeAnalysisProblem', command: 'C_Cpp.FixThisCodeAnalysisProblem',
arguments: [ nextVersion, relatedWorkspaceEdit, true, [ relatedIdentifiersAndUri ] ] },
kind: vscode.CodeActionKind.QuickFix
};
if (codeAction.fixCodeAction === undefined) {
codeAction.fixCodeAction = relatedCodeAction;
} else {
const relatedCodeActionInfo: CodeActionDiagnosticInfo = {
version: nextVersion,
range: makeVscodeRange(relatedIdentifier.range),
code: relatedIdentifier.code,
fixCodeAction: relatedCodeAction
};
relatedCodeActions.push(relatedCodeActionInfo);
}
rootAndRelatedWorkspaceEdits.push({ workspaceEdit: relatedWorkspaceEdit});
rootAndRelatedIdentifiersAndUris.push(relatedIdentifiersAndUri);
}
}
if (identifier.code.length !== 0) {
const codeActionCodeInfo: CodeActionCodeInfo = codeAnalysisCodeToFixes.get(identifier.code) ??
{ version: 0, uriToInfo: new Map<string, CodeActionPerUriInfo>() };
let rootAndRelatedWorkspaceEditsIndex: number = 0;
for (const rootAndRelatedIdentifiersAndUri of rootAndRelatedIdentifiersAndUris) {
const existingInfo: CodeActionPerUriInfo = codeActionCodeInfo.uriToInfo.get(rootAndRelatedIdentifiersAndUri.uri) ??
{ identifiers: [], numValidWorkspaceEdits: 0 };
existingInfo.identifiers.push(...rootAndRelatedIdentifiersAndUri.identifiers);
const rootAndRelatedWorkspaceEdit: CodeActionWorkspaceEdit = rootAndRelatedWorkspaceEdits[rootAndRelatedWorkspaceEditsIndex];
if (rootAndRelatedWorkspaceEdit !== undefined) {
if (existingInfo.workspaceEdits === undefined) {
existingInfo.workspaceEdits = [ rootAndRelatedWorkspaceEdit ];
} else {
existingInfo.workspaceEdits.push(rootAndRelatedWorkspaceEdit);
}
++existingInfo.numValidWorkspaceEdits;
}
codeActionCodeInfo.uriToInfo.set(rootAndRelatedIdentifiersAndUri.uri, existingInfo);
++rootAndRelatedWorkspaceEditsIndex;
}
if (!identifier.code.startsWith("clang-diagnostic-")) {
const codes: string[] = identifier.code.split(',');
let codeIndex: number = codes.length - 1;
if (codes[codeIndex] === "cert-dcl51-cpp") { // Handle aliasing
codeIndex = 0;
}
// TODO: Is the ideal code always selected as the primary one?
const primaryCode: string = codes[codeIndex];
const docPage: string = primaryCode === "clang-tidy-nolint" ? "#suppressing-undesired-diagnostics" :
`checks/${primaryCode}.html`;
const primaryDocUri: vscode.Uri = vscode.Uri.parse(`https://releases.llvm.org/14.0.0/tools/clang/tools/extra/docs/clang-tidy/${docPage}`);
diagnostic.code = { value: identifier.code, target: primaryDocUri };
if (new CppSettings().clangTidyCodeActionShowDocumentation) {
if (codeActionCodeInfo.docCodeAction === undefined) {
codeActionCodeInfo.docCodeAction = {
title: localize("show_documentation_for", "Show documentation for {0}", primaryCode),
command: { title: 'ShowDocumentation', command: 'C_Cpp.ShowCodeAnalysisDocumentation',
arguments: [ primaryDocUri ] },
kind: vscode.CodeActionKind.QuickFix
};
}
} else {
codeActionCodeInfo.docCodeAction = undefined;
}
} else {
diagnostic.code = d.code;
}
codeAnalysisCodeToFixes.set(identifier.code, codeActionCodeInfo);
} else {
diagnostic.code = d.code;
}
diagnostic.source = CppSourceStr;
codeActionDiagnosticInfo.push(codeAction);
if (relatedCodeActions.length > 0) {
codeActionDiagnosticInfo.push(...relatedCodeActions);
}
diagnosticsCodeAnalysis.push(diagnostic);
}
codeAnalysisFileToCodeActions.set(params.uri, codeActionDiagnosticInfo);
rebuildCodeAnalysisCodeAndAllFixes();
diagnosticsCollectionCodeAnalysis.set(realUri, diagnosticsCodeAnalysis);
}
function removeCodeAnalysisCodeActions(identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[],
removeFixesOnly: boolean): void {
for (const identifiersAndUri of identifiersAndUris) {
const codeActionDiagnosticInfo: CodeActionDiagnosticInfo[] | undefined = codeAnalysisFileToCodeActions.get(identifiersAndUri.uri);
if (codeActionDiagnosticInfo === undefined) {
return;
}
for (const identifier of identifiersAndUri.identifiers) {
const updatedCodeActions: CodeActionDiagnosticInfo[] = [];
for (const codeAction of codeActionDiagnosticInfo) {
if (rangeEquals(codeAction.range, identifier.range) && codeAction.code === identifier.code) {
if (removeFixesOnly) {
++codeAction.version;
codeAction.fixCodeAction = undefined;
} else {
continue;
}
}
updatedCodeActions.push(codeAction);
}
codeAnalysisFileToCodeActions.set(identifiersAndUri.uri, updatedCodeActions);
let codeActionInfoChanged: boolean = false;
for (const codeFixes of codeAnalysisCodeToFixes) {
const codeActionInfo: CodeActionPerUriInfo | undefined = codeFixes[1].uriToInfo.get(identifiersAndUri.uri);
if (codeActionInfo === undefined) {
continue;
}
let removedCodeActionInfoIndex: number = -1;
for (let codeActionInfoIndex: number = 0; codeActionInfoIndex < codeActionInfo.identifiers.length; ++codeActionInfoIndex) {
if (identifier.code === codeActionInfo.identifiers[codeActionInfoIndex].code &&
rangeEquals(identifier.range, codeActionInfo.identifiers[codeActionInfoIndex].range)) {
removedCodeActionInfoIndex = codeActionInfoIndex;
codeActionInfoChanged = true;
break;
}
}
if (removedCodeActionInfoIndex !== -1) {
if (removeFixesOnly) {
if (codeActionInfo.workspaceEdits !== undefined) {
codeActionInfo.workspaceEdits[removedCodeActionInfoIndex].workspaceEdit = undefined;
--codeActionInfo.numValidWorkspaceEdits;
}
} else {
codeActionInfo.identifiers.splice(removedCodeActionInfoIndex, 1);
if (codeActionInfo.workspaceEdits !== undefined) {
codeActionInfo.workspaceEdits.splice(removedCodeActionInfoIndex, 1);
--codeActionInfo.numValidWorkspaceEdits;
}
}
if (codeActionInfo.identifiers.length === 0) {
codeFixes[1].uriToInfo.delete(identifiersAndUri.uri);
} else {
codeFixes[1].uriToInfo.set(identifiersAndUri.uri, codeActionInfo);
}
}
}
if (codeActionInfoChanged) {
rebuildCodeAnalysisCodeAndAllFixes();
}
}
}
}
function publishRemoveCodeAnalysisCodeActionFixes(params: RemoveCodeAnalysisCodeActionFixesParams): void {
removeCodeAnalysisCodeActions(params.identifiersAndUris, true);
}
interface WorkspaceFolderParams {
workspaceFolderUri?: string;
}
@@ -577,12 +151,6 @@ interface TelemetryPayload {
metrics?: { [key: string]: number };
}
interface DebugProtocolParams {
jsonrpc: string;
method: string;
params?: any;
}
interface ReportStatusNotificationBody extends WorkspaceFolderParams {
status: string;
}
@@ -668,12 +236,6 @@ interface IntelliSenseDiagnosticRelatedInformation {
message: string;
}
interface CodeAnalysisDiagnosticRelatedInformation {
location: Location;
message: string;
workspaceEdit?: WorkspaceEdit;
}
interface IntelliSenseDiagnostic {
range: Range;
code?: number;
@@ -682,53 +244,16 @@ interface IntelliSenseDiagnostic {
relatedInformation?: IntelliSenseDiagnosticRelatedInformation[];
}
interface CodeAnalysisDiagnostic {
range: Range;
code: string;
severity: vscode.DiagnosticSeverity;
localizeStringParams: LocalizeStringParams;
relatedInformation?: CodeAnalysisDiagnosticRelatedInformation[];
workspaceEdit?: WorkspaceEdit;
}
interface CodeAnalysisDiagnosticIdentifier {
range: Range;
code: string;
}
export interface CodeAnalysisDiagnosticIdentifiersAndUri {
uri: string;
identifiers: CodeAnalysisDiagnosticIdentifier[];
}
interface RemoveCodeAnalysisProblemsParams {
identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[];
refreshSquigglesOnSave: boolean;
};
interface RemoveCodeAnalysisCodeActionFixesParams {
identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[];
};
interface PublishIntelliSenseDiagnosticsParams {
uri: string;
diagnostics: IntelliSenseDiagnostic[];
}
interface PublishCodeAnalysisDiagnosticsParams {
uri: string;
diagnostics: CodeAnalysisDiagnostic[];
}
interface ShowMessageWindowParams {
type: number;
localizeStringParams: LocalizeStringParams;
}
interface ShowWarningParams {
localizeStringParams: LocalizeStringParams;
}
export interface GetDocumentSymbolRequestParams {
uri: string;
}
@@ -787,10 +312,6 @@ export interface FormatParams {
useVcFormat: boolean;
}
interface WorkspaceEdit {
changes: { [uri: string]: TextEdit[] };
}
export interface GetFoldingRangesParams {
uri: string;
}
@@ -959,17 +480,15 @@ const ReferencesNotification: NotificationType<refs.ReferencesResultMessage, voi
const ReportReferencesProgressNotification: NotificationType<refs.ReportReferencesProgressNotification, void> = new NotificationType<refs.ReportReferencesProgressNotification, void>('cpptools/reportReferencesProgress');
const RequestCustomConfig: NotificationType<string, void> = new NotificationType<string, void>('cpptools/requestCustomConfig');
const PublishIntelliSenseDiagnosticsNotification: NotificationType<PublishIntelliSenseDiagnosticsParams, void> = new NotificationType<PublishIntelliSenseDiagnosticsParams, void>('cpptools/publishIntelliSenseDiagnostics');
const PublishCodeAnalysisDiagnosticsNotification: NotificationType<PublishCodeAnalysisDiagnosticsParams, void> = new NotificationType<PublishCodeAnalysisDiagnosticsParams, void>('cpptools/publishCodeAnalysisDiagnostics');
const ShowMessageWindowNotification: NotificationType<ShowMessageWindowParams, void> = new NotificationType<ShowMessageWindowParams, void>('cpptools/showMessageWindow');
const ShowWarningNotification: NotificationType<ShowWarningParams, void> = new NotificationType<ShowWarningParams, void>('cpptools/showWarning');
const ReportTextDocumentLanguage: NotificationType<string, void> = new NotificationType<string, void>('cpptools/reportTextDocumentLanguage');
const SemanticTokensChanged: NotificationType<string, void> = new NotificationType<string, void>('cpptools/semanticTokensChanged');
const InlayHintsChanged: NotificationType<string, void> = new NotificationType<string, void>('cpptools/inlayHintsChanged');
const IntelliSenseSetupNotification: NotificationType<IntelliSenseSetup, void> = new NotificationType<IntelliSenseSetup, void>('cpptools/IntelliSenseSetup');
const SetTemporaryTextDocumentLanguageNotification: NotificationType<SetTemporaryTextDocumentLanguageParams, void> = new NotificationType<SetTemporaryTextDocumentLanguageParams, void>('cpptools/setTemporaryTextDocumentLanguage');
const ReportCodeAnalysisProcessedNotification: NotificationType<number, void> = new NotificationType<number, void>('cpptools/reportCodeAnalysisProcessed');
const ReportCodeAnalysisTotalNotification: NotificationType<number, void> = new NotificationType<number, void>('cpptools/reportCodeAnalysisTotal');
const PublishRemoveCodeAnalysisCodeActionFixesNotification: NotificationType<RemoveCodeAnalysisCodeActionFixesParams, void> = new NotificationType<RemoveCodeAnalysisCodeActionFixesParams, void>('cpptools/publishRemoveCodeAnalysisCodeActionFixes');
let failureMessageShown: boolean = false;
export interface ReferencesCancellationState {
@@ -1148,6 +667,7 @@ export class DefaultClient implements Client {
private onTypeFormattingProviderDisposable: vscode.Disposable | undefined;
private codeFoldingProvider: FoldingRangeProvider | undefined;
private codeFoldingProviderDisposable: vscode.Disposable | undefined;
private inlayHintsProvider: InlayHintsProvider | undefined;
private semanticTokensProvider: SemanticTokensProvider | undefined;
private semanticTokensProviderDisposable: vscode.Disposable | undefined;
private innerConfiguration?: configs.CppProperties;
@@ -1336,6 +856,9 @@ export class DefaultClient implements Client {
// e.g. prevents empty c_cpp_properties.json from generation.
this.registerFileWatcher();
this.inlayHintsProvider = new InlayHintsProvider(this);
this.disposables.push(vscode.languages.registerInlayHintsProvider(this.documentSelector, this.inlayHintsProvider));
this.disposables.push(vscode.languages.registerRenameProvider(this.documentSelector, new RenameProvider(this)));
this.disposables.push(vscode.languages.registerReferenceProvider(this.documentSelector, new FindAllReferencesProvider(this)));
this.disposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(this)));
@@ -1771,7 +1294,8 @@ export class DefaultClient implements Client {
autoSaveAfterDelay: settings_filesAutoSaveAfterDelay
},
editor: {
autoClosingBrackets: settings_editorAutoClosingBrackets
autoClosingBrackets: settings_editorAutoClosingBrackets,
inlayHintsEnabled: workspaceOtherSettings.InlayHintsEnabled
},
workspace_fallback_encoding: workspaceOtherSettings.filesEncoding,
cpp_exclude_files: settings_cppFilesExclude,
@@ -1803,7 +1327,7 @@ export class DefaultClient implements Client {
},
vcpkg_root: util.getVcpkgRoot(),
experimentalFeatures: workspaceSettings.experimentalFeatures,
edgeMessagesDirectory: path.join(util.getExtensionFilePath("bin"), "messages", util.getLocaleId()),
edgeMessagesDirectory: path.join(util.getExtensionFilePath("bin"), "messages", getLocaleId()),
localizedStrings: localizedStrings,
packageVersion: util.packageJson.version,
legacyCompilerArgsBehavior: settings_legacyCompilerArgsBehavior
@@ -1903,7 +1427,8 @@ export class DefaultClient implements Client {
}
},
editor: {
autoClosingBrackets: otherSettingsFolder.editorAutoClosingBrackets
autoClosingBrackets: otherSettingsFolder.editorAutoClosingBrackets,
inlayHintsEnabled: otherSettingsWorkspace.InlayHintsEnabled
},
files: {
encoding: otherSettingsFolder.filesEncoding,
@@ -1942,7 +1467,7 @@ export class DefaultClient implements Client {
this.loggingLevel = newLoggingLevel;
const newLoggingLevelLogged: boolean = !!newLoggingLevel && newLoggingLevel !== "None" && newLoggingLevel !== "Error";
if (oldLoggingLevelLogged || newLoggingLevelLogged) {
const out: logger.Logger = logger.getOutputChannelLogger();
const out: Logger = getOutputChannelLogger();
out.appendLine(localize({ key: "loggingLevel.changed", comment: ["{0} is the setting name 'loggingLevel', {1} is a string value such as 'Debug'"] }, "{0} has changed to: {1}", "loggingLevel", changedSettings["loggingLevel"]));
}
}
@@ -2058,7 +1583,9 @@ export class DefaultClient implements Client {
if (this.semanticTokensProvider) {
this.semanticTokensProvider.invalidateFile(uri);
}
if (this.inlayHintsProvider) {
this.inlayHintsProvider.invalidateFile(uri);
}
openFileVersions.delete(uri);
}
@@ -2232,12 +1759,8 @@ export class DefaultClient implements Client {
public async logDiagnostics(): Promise<void> {
const response: GetDiagnosticsResult = await this.requestWhenReady(() => this.languageClient.sendRequest(GetDiagnosticsRequest, null));
if (!diagnosticsChannel) {
diagnosticsChannel = vscode.window.createOutputChannel(localize("c.cpp.diagnostics", "C/C++ Diagnostics"));
workspaceDisposables.push(diagnosticsChannel);
} else {
diagnosticsChannel.clear();
}
const diagnosticsChannel: vscode.OutputChannel = getDiagnosticsChannel();
diagnosticsChannel.clear();
const header: string = `-------- Diagnostics - ${new Date().toLocaleString()}\n`;
const version: string = `Version: ${util.packageJson.version}\n`;
@@ -2587,12 +2110,12 @@ export class DefaultClient implements Client {
client.handleRequestCustomConfig(requestFile);
});
this.languageClient.onNotification(PublishIntelliSenseDiagnosticsNotification, publishIntelliSenseDiagnostics);
this.languageClient.onNotification(PublishCodeAnalysisDiagnosticsNotification, publishCodeAnalysisDiagnostics);
this.languageClient.onNotification(PublishRemoveCodeAnalysisCodeActionFixesNotification, publishRemoveCodeAnalysisCodeActionFixes);
RegisterCodeAnalysisNotifications(this.languageClient);
this.languageClient.onNotification(ShowMessageWindowNotification, showMessageWindow);
this.languageClient.onNotification(ShowWarningNotification, showWarning);
this.languageClient.onNotification(ReportTextDocumentLanguage, (e) => this.setTextDocumentLanguage(e));
this.languageClient.onNotification(SemanticTokensChanged, (e) => this.semanticTokensProvider?.invalidateFile(e));
this.languageClient.onNotification(InlayHintsChanged, (e) => this.inlayHintsProvider?.invalidateFile(e));
this.languageClient.onNotification(IntelliSenseSetupNotification, (e) => this.logIntellisenseSetupTime(e));
this.languageClient.onNotification(SetTemporaryTextDocumentLanguageNotification, (e) => this.setTemporaryTextDocumentLanguage(e));
this.languageClient.onNotification(ReportCodeAnalysisProcessedNotification, (e) => this.updateCodeAnalysisProcessed(e));
@@ -2774,7 +2297,7 @@ export class DefaultClient implements Client {
} else if (message.endsWith("IntelliSense done")) {
const settings: CppSettings = new CppSettings();
if (settings.loggingLevel === "Debug") {
const out: logger.Logger = logger.getOutputChannelLogger();
const out: Logger = getOutputChannelLogger();
const duration: number = Date.now() - timeStamp;
out.appendLine(localize("update.intellisense.time", "Update IntelliSense time (sec): {0}", duration / 1000));
}
@@ -2847,7 +2370,7 @@ export class DefaultClient implements Client {
}
private updateTagParseStatus(notificationBody: LocalizeStringParams): void {
this.model.parsingWorkspaceStatus.Value = util.getLocalizedString(notificationBody);
this.model.parsingWorkspaceStatus.Value = getLocalizedString(notificationBody);
if (notificationBody.text.startsWith("Workspace parsing paused")) {
this.model.isParsingWorkspacePausable.Value = true;
this.model.isParsingWorkspacePaused.Value = true;
@@ -3190,7 +2713,7 @@ export class DefaultClient implements Client {
}
const settings: CppSettings = new CppSettings();
const out: logger.Logger = logger.getOutputChannelLogger();
const out: Logger = getOutputChannelLogger();
if (settings.loggingLevel === "Debug") {
out.appendLine(localize("configurations.received", "Custom configurations received:"));
}
@@ -3215,6 +2738,7 @@ export class DefaultClient implements Client {
itemConfig.compilerPath = compilerPathAndArgs.compilerPath;
if (providerVersion < Version.v6) {
itemConfig.compilerArgsLegacy = compilerPathAndArgs.allCompilerArgs;
itemConfig.compilerArgs = undefined;
} else {
itemConfig.compilerArgs = compilerPathAndArgs.allCompilerArgs;
}
@@ -3293,7 +2817,7 @@ export class DefaultClient implements Client {
const settings: CppSettings = new CppSettings();
if (settings.loggingLevel === "Debug") {
const out: logger.Logger = logger.getOutputChannelLogger();
const out: Logger = getOutputChannelLogger();
out.appendLine(localize("browse.configuration.received", "Custom browse configuration received: {0}", JSON.stringify(sanitized, null, 2)));
}
@@ -3306,6 +2830,7 @@ export class DefaultClient implements Client {
sanitized.compilerPath = compilerPathAndArgs.compilerPath;
if (providerVersion < Version.v6) {
sanitized.compilerArgsLegacy = compilerPathAndArgs.allCompilerArgs;
sanitized.compilerArgs = undefined;
} else {
sanitized.compilerArgs = compilerPathAndArgs.allCompilerArgs;
}
@@ -3486,14 +3011,9 @@ export class DefaultClient implements Client {
public async handleRemoveAllCodeAnalysisProblems(): Promise<void> {
await this.awaitUntilLanguageClientReady();
if (!diagnosticsCollectionCodeAnalysis) {
return;
if (removeAllCodeAnalysisProblems()) {
this.languageClient.sendNotification(CodeAnalysisNotification, CodeAnalysisScope.ClearSquiggles);
}
diagnosticsCollectionCodeAnalysis.clear();
codeAnalysisFileToCodeActions.clear();
codeAnalysisCodeToFixes.clear();
rebuildCodeAnalysisCodeAndAllFixes();
this.languageClient.sendNotification(CodeAnalysisNotification, CodeAnalysisScope.ClearSquiggles);
}
public async handleFixCodeAnalysisProblems(workspaceEdit: vscode.WorkspaceEdit, refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void> {
@@ -3504,9 +3024,6 @@ export class DefaultClient implements Client {
public async handleRemoveCodeAnalysisProblems(refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void> {
await this.awaitUntilLanguageClientReady();
if (!diagnosticsCollectionCodeAnalysis) {
return;
}
// A deep copy is needed because the call to identifiers.splice below can
// remove elements in identifiersAndUris[...].identifiers.
@@ -3515,38 +3032,11 @@ export class DefaultClient implements Client {
identifiersAndUrisCopy.push({ uri: identifiersAndUri.uri, identifiers: [...identifiersAndUri.identifiers] });
}
// Remove the diagnostics.
for (const identifiersAndUri of identifiersAndUris) {
const uri: vscode.Uri = vscode.Uri.parse(identifiersAndUri.uri);
const diagnostics: readonly vscode.Diagnostic[] | undefined = diagnosticsCollectionCodeAnalysis.get(uri);
if (diagnostics === undefined) {
continue;
}
const newDiagnostics: vscode.Diagnostic[] = [];
for (const diagnostic of diagnostics) {
const code: string = typeof diagnostic.code === "string" ? diagnostic.code :
(typeof diagnostic.code === "object" && typeof diagnostic.code.value === "string" ?
diagnostic.code.value : "");
let removed: boolean = false;
for (const identifier of identifiersAndUri.identifiers) {
if (code !== identifier.code || !rangeEquals(diagnostic.range, identifier.range)) {
continue;
}
removed = true;
break;
}
if (!removed) {
newDiagnostics.push(diagnostic);
}
}
diagnosticsCollectionCodeAnalysis.set(uri, newDiagnostics);
if (removeCodeAnalysisProblems(identifiersAndUris)) {
// Need to notify the language client of the removed diagnostics so it doesn't re-send them.
this.languageClient.sendNotification(RemoveCodeAnalysisProblemsNotification, {
identifiersAndUris: identifiersAndUrisCopy, refreshSquigglesOnSave: refreshSquigglesOnSave });
}
removeCodeAnalysisCodeActions(identifiersAndUris, false);
// Need to notify the language client of the removed diagnostics so it doesn't re-send them.
this.languageClient.sendNotification(RemoveCodeAnalysisProblemsNotification, {
identifiersAndUris: identifiersAndUrisCopy, refreshSquigglesOnSave: refreshSquigglesOnSave });
}
public async handleDisableAllTypeCodeAnalysisProblems(code: string,
@@ -295,7 +295,6 @@ export class ClientCollection {
// this.defaultClient is already in this.languageClients, so do not call dispose() on it.
this.languageClients.forEach(client => client.dispose());
this.languageClients.clear();
cpptools.disposeWorkspaceData();
return cpptools.DefaultClient.stopLanguageClient();
}
}
@@ -0,0 +1,501 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import { LanguageClient, NotificationType, Range } from 'vscode-languageclient';
import { Location, WorkspaceEdit } from './commonTypes';
import { makeVscodeRange, makeVscodeLocation, makeVscodeTextEdits, rangeEquals } from './utils';
import {LocalizeStringParams, getLocalizedString } from './localization';
import { CppSourceStr } from './extension';
import { CppSettings } from './settings';
import * as nls from 'vscode-nls';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
let diagnosticsCollectionCodeAnalysis: vscode.DiagnosticCollection;
export function RegisterCodeAnalysisNotifications(languageClient: LanguageClient): void {
languageClient.onNotification(PublishCodeAnalysisDiagnosticsNotification, publishCodeAnalysisDiagnostics);
languageClient.onNotification(PublishRemoveCodeAnalysisCodeActionFixesNotification, publishRemoveCodeAnalysisCodeActionFixes);
}
export interface CodeActionDiagnosticInfo {
version: number; // Needed due to https://github.com/microsoft/vscode/issues/148723 .
// Used to work around https://github.com/microsoft/vscode/issues/126393.
// If that bug were fixed, then we could use the vscode.CodeAction.diagnostic directly.
range: vscode.Range;
code: string;
fixCodeAction?: vscode.CodeAction;
// suppressCodeAction?: vscode.CodeAction; // TODO?
removeCodeAction?: vscode.CodeAction;
}
// Used to handle fix invalidation after an edit,
// i.e. it's set to undefined if it becomes invalid.
interface CodeActionWorkspaceEdit {
workspaceEdit?: vscode.WorkspaceEdit;
}
interface CodeActionPerUriInfo {
// These two arrays have the same length, i.e. index i of identifiers
// is used to index into workspaceEdits to get the corresponding edit.
identifiers: CodeAnalysisDiagnosticIdentifier[];
workspaceEdits?: CodeActionWorkspaceEdit[];
// Used to quickly determine how many non-undefined entries are in "workspaceEdits"
// (so the array doesn't have to be iterated through).
numValidWorkspaceEdits: number;
}
// Tracks the "type" code actions (i.e. "code" is a synonym for "type" in this context).
export interface CodeActionCodeInfo {
version: number; // Needed due to https://github.com/microsoft/vscode/issues/148723 .
// Needed to quickly update the "type" action for a file.
uriToInfo: Map<string, CodeActionPerUriInfo>;
fixAllTypeCodeAction?: vscode.CodeAction;
disableAllTypeCodeAction?: vscode.CodeAction;
removeAllTypeCodeAction?: vscode.CodeAction;
docCodeAction?: vscode.CodeAction;
}
interface CodeActionAllInfo {
version: number; // Needed due to https://github.com/microsoft/vscode/issues/148723 .
fixAllCodeAction: vscode.CodeAction;
removeAllCodeAction: vscode.CodeAction;
}
interface CodeAnalysisDiagnosticRelatedInformation {
location: Location;
message: string;
workspaceEdit?: WorkspaceEdit;
}
interface CodeAnalysisDiagnostic {
range: Range;
code: string;
severity: vscode.DiagnosticSeverity;
localizeStringParams: LocalizeStringParams;
relatedInformation?: CodeAnalysisDiagnosticRelatedInformation[];
workspaceEdit?: WorkspaceEdit;
}
interface CodeAnalysisDiagnosticIdentifier {
range: Range;
code: string;
}
export interface CodeAnalysisDiagnosticIdentifiersAndUri {
uri: string;
identifiers: CodeAnalysisDiagnosticIdentifier[];
}
export interface RemoveCodeAnalysisProblemsParams {
identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[];
refreshSquigglesOnSave: boolean;
};
interface RemoveCodeAnalysisCodeActionFixesParams {
identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[];
};
interface PublishCodeAnalysisDiagnosticsParams {
uri: string;
diagnostics: CodeAnalysisDiagnostic[];
}
const PublishCodeAnalysisDiagnosticsNotification: NotificationType<PublishCodeAnalysisDiagnosticsParams, void> = new NotificationType<PublishCodeAnalysisDiagnosticsParams, void>('cpptools/publishCodeAnalysisDiagnostics');
const PublishRemoveCodeAnalysisCodeActionFixesNotification: NotificationType<RemoveCodeAnalysisCodeActionFixesParams, void> = new NotificationType<RemoveCodeAnalysisCodeActionFixesParams, void>('cpptools/publishRemoveCodeAnalysisCodeActionFixes');
export const codeAnalysisFileToCodeActions: Map<string, CodeActionDiagnosticInfo[]> = new Map<string, CodeActionDiagnosticInfo[]>();
export const codeAnalysisCodeToFixes: Map<string, CodeActionCodeInfo> = new Map<string, CodeActionCodeInfo>();
export const codeAnalysisAllFixes: CodeActionAllInfo = {
version: 0,
fixAllCodeAction: {
title: localize("fix_all_code_analysis_problems", "Fix all code analysis problems"),
command: { title: 'FixAllCodeAnalysisProblems', command: 'C_Cpp.FixAllCodeAnalysisProblems',
arguments: [ 0, undefined, true, [] ] },
kind: vscode.CodeActionKind.QuickFix
},
removeAllCodeAction: {
title: localize("clear_all_code_analysis_problems", "Clear all code analysis problems"),
command: { title: "RemoveAllCodeAnalysisProblems", command: "C_Cpp.RemoveAllCodeAnalysisProblems" },
kind: vscode.CodeActionKind.QuickFix
}
};
// Rebuild codeAnalysisCodeToFixes and codeAnalysisAllFixes.fixAllCodeActions.
function rebuildCodeAnalysisCodeAndAllFixes(): void {
if (codeAnalysisAllFixes.fixAllCodeAction.command?.arguments !== undefined) {
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[0] = ++codeAnalysisAllFixes.version;
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[1] = undefined;
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[3] = [];
}
const identifiersAndUrisForAllFixes: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
const uriToEditsForAll: Map<vscode.Uri, vscode.TextEdit[]> = new Map<vscode.Uri, vscode.TextEdit[]>();
let numFixTypes: number = 0;
for (const codeToFixes of codeAnalysisCodeToFixes) {
const identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
const uriToEdits: Map<vscode.Uri, vscode.TextEdit[]> = new Map<vscode.Uri, vscode.TextEdit[]>();
codeToFixes[1].uriToInfo.forEach((perUriInfo: CodeActionPerUriInfo, uri: string) => {
const newIdentifiersAndUri: CodeAnalysisDiagnosticIdentifiersAndUri = { uri: uri, identifiers: perUriInfo.identifiers };
identifiersAndUris.push(newIdentifiersAndUri);
if (perUriInfo.workspaceEdits === undefined || perUriInfo.numValidWorkspaceEdits === 0) {
return;
}
identifiersAndUrisForAllFixes.push(newIdentifiersAndUri);
for (const edit of perUriInfo.workspaceEdits) {
if (edit.workspaceEdit === undefined) {
continue;
}
for (const [uri, edits] of edit.workspaceEdit.entries()) {
const textEdits: vscode.TextEdit[] = uriToEdits.get(uri) ?? [];
textEdits.push(...edits);
uriToEdits.set(uri, textEdits);
const textEditsForAll: vscode.TextEdit[] = uriToEditsForAll.get(uri) ?? [];
textEditsForAll.push(...edits);
uriToEditsForAll.set(uri, textEdits);
}
}
});
if (uriToEdits.size > 0) {
const allTypeWorkspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
for (const [uri, edits] of uriToEdits.entries()) {
allTypeWorkspaceEdit.set(uri, edits);
}
++numFixTypes;
codeToFixes[1].fixAllTypeCodeAction = {
title: localize("fix_all_type_problems", "Fix all {0} problems", codeToFixes[0]),
command: { title: 'FixAllTypeCodeAnalysisProblems', command: 'C_Cpp.FixAllTypeCodeAnalysisProblems',
arguments: [ codeToFixes[0], ++codeToFixes[1].version, allTypeWorkspaceEdit, true, identifiersAndUris ] },
kind: vscode.CodeActionKind.QuickFix
};
}
if (new CppSettings().clangTidyCodeActionShowDisable) {
codeToFixes[1].disableAllTypeCodeAction = {
title: localize("disable_all_type_problems", "Disable all {0} problems", codeToFixes[0]),
command: { title: 'DisableAllTypeCodeAnalysisProblems', command: 'C_Cpp.DisableAllTypeCodeAnalysisProblems',
arguments: [ codeToFixes[0], identifiersAndUris ] },
kind: vscode.CodeActionKind.QuickFix
};
} else {
codeToFixes[1].disableAllTypeCodeAction = undefined;
}
if (new CppSettings().clangTidyCodeActionShowClear !== "None") {
codeToFixes[1].removeAllTypeCodeAction = {
title: localize("clear_all_type_problems", "Clear all {0} problems", codeToFixes[0]),
command: { title: 'RemoveAllTypeCodeAnalysisProblems', command: 'C_Cpp.RemoveCodeAnalysisProblems',
arguments: [ false, identifiersAndUris ] },
kind: vscode.CodeActionKind.QuickFix
};
}
}
if (numFixTypes > 1) {
const allWorkspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
for (const [uri, edits] of uriToEditsForAll.entries()) {
allWorkspaceEdit.set(uri, edits);
}
if (codeAnalysisAllFixes.fixAllCodeAction.command?.arguments !== undefined) {
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[1] = allWorkspaceEdit;
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[3] = identifiersAndUrisForAllFixes;
}
} else {
if (codeAnalysisAllFixes.fixAllCodeAction.command?.arguments !== undefined) {
codeAnalysisAllFixes.fixAllCodeAction.command.arguments[1] = undefined;
}
}
}
export function publishCodeAnalysisDiagnostics(params: PublishCodeAnalysisDiagnosticsParams): void {
if (!diagnosticsCollectionCodeAnalysis) {
diagnosticsCollectionCodeAnalysis = vscode.languages.createDiagnosticCollection("clang-tidy");
}
// Convert from our Diagnostic objects to vscode Diagnostic objects
const diagnosticsCodeAnalysis: vscode.Diagnostic[] = [];
const realUri: vscode.Uri = vscode.Uri.parse(params.uri);
// Reset codeAnalysisCodeToFixes for the file.
for (const codeToFixes of codeAnalysisCodeToFixes) {
++codeToFixes[1].version;
if (codeToFixes[1].uriToInfo.has(params.uri)) {
codeToFixes[1].uriToInfo.delete(params.uri);
}
}
const previousDiagnostics: CodeActionDiagnosticInfo[] | undefined = codeAnalysisFileToCodeActions.get(params.uri);
let nextVersion: number = 0;
if (previousDiagnostics !== undefined) {
for (const diagnostic of previousDiagnostics) {
if (diagnostic.version > nextVersion) {
nextVersion = diagnostic.version;
}
}
}
++nextVersion;
const codeActionDiagnosticInfo: CodeActionDiagnosticInfo[] = [];
for (const d of params.diagnostics) {
const diagnostic: vscode.Diagnostic = new vscode.Diagnostic(makeVscodeRange(d.range),
getLocalizedString(d.localizeStringParams), d.severity);
const identifier: CodeAnalysisDiagnosticIdentifier = { range: d.range, code: d.code };
const identifiersAndUri: CodeAnalysisDiagnosticIdentifiersAndUri = { uri: params.uri, identifiers: [ identifier ] };
const codeAction: CodeActionDiagnosticInfo = {
version: nextVersion,
range: makeVscodeRange(identifier.range),
code: identifier.code,
removeCodeAction: {
title: localize("clear_this_problem", "Clear this {0} problem", d.code),
command: { title: 'RemoveCodeAnalysisProblems', command: 'C_Cpp.RemoveCodeAnalysisProblems',
arguments: [ false, [ identifiersAndUri ] ] },
kind: vscode.CodeActionKind.QuickFix
}
};
const workspaceEdit: CodeActionWorkspaceEdit = {};
if (d.workspaceEdit) {
workspaceEdit.workspaceEdit = new vscode.WorkspaceEdit();
for (const [uriStr, edits] of Object.entries(d.workspaceEdit.changes)) {
workspaceEdit.workspaceEdit.set(vscode.Uri.parse(uriStr, true), makeVscodeTextEdits(edits));
}
const fixThisCodeAction: vscode.CodeAction = {
title: localize("fix_this_problem", "Fix this {0} problem", d.code),
command: { title: 'FixThisCodeAnalysisProblem', command: 'C_Cpp.FixThisCodeAnalysisProblem',
arguments: [ nextVersion, workspaceEdit.workspaceEdit, true, [ identifiersAndUri ] ] },
kind: vscode.CodeActionKind.QuickFix
};
codeAction.fixCodeAction = fixThisCodeAction;
}
// Edits from clang-tidy can be associated with the related information instead of the root diagnostic.
const relatedCodeActions: CodeActionDiagnosticInfo[] = [];
const rootAndRelatedWorkspaceEdits: CodeActionWorkspaceEdit[] = [];
const rootAndRelatedIdentifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
rootAndRelatedIdentifiersAndUris.push(identifiersAndUri);
if (workspaceEdit.workspaceEdit !== undefined) {
rootAndRelatedWorkspaceEdits.push(workspaceEdit);
}
if (d.relatedInformation) {
diagnostic.relatedInformation = [];
for (const info of d.relatedInformation) {
diagnostic.relatedInformation.push(new vscode.DiagnosticRelatedInformation(makeVscodeLocation(info.location), info.message));
if (info.workspaceEdit === undefined) {
continue;
}
const relatedWorkspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
for (const [uriStr, edits] of Object.entries(info.workspaceEdit.changes)) {
relatedWorkspaceEdit.set(vscode.Uri.parse(uriStr, true), makeVscodeTextEdits(edits));
}
const relatedIdentifier: CodeAnalysisDiagnosticIdentifier = { range: info.location.range, code: d.code };
const relatedIdentifiersAndUri: CodeAnalysisDiagnosticIdentifiersAndUri = {
uri: info.location.uri, identifiers: [ relatedIdentifier ] };
const relatedCodeAction: vscode.CodeAction = {
title: localize("fix_this_problem", "Fix this {0} problem", d.code),
command: { title: 'FixThisCodeAnalysisProblem', command: 'C_Cpp.FixThisCodeAnalysisProblem',
arguments: [ nextVersion, relatedWorkspaceEdit, true, [ relatedIdentifiersAndUri ] ] },
kind: vscode.CodeActionKind.QuickFix
};
if (codeAction.fixCodeAction === undefined) {
codeAction.fixCodeAction = relatedCodeAction;
} else {
const relatedCodeActionInfo: CodeActionDiagnosticInfo = {
version: nextVersion,
range: makeVscodeRange(relatedIdentifier.range),
code: relatedIdentifier.code,
fixCodeAction: relatedCodeAction
};
relatedCodeActions.push(relatedCodeActionInfo);
}
rootAndRelatedWorkspaceEdits.push({ workspaceEdit: relatedWorkspaceEdit});
rootAndRelatedIdentifiersAndUris.push(relatedIdentifiersAndUri);
}
}
if (identifier.code.length !== 0) {
const codeActionCodeInfo: CodeActionCodeInfo = codeAnalysisCodeToFixes.get(identifier.code) ??
{ version: 0, uriToInfo: new Map<string, CodeActionPerUriInfo>() };
let rootAndRelatedWorkspaceEditsIndex: number = 0;
for (const rootAndRelatedIdentifiersAndUri of rootAndRelatedIdentifiersAndUris) {
const existingInfo: CodeActionPerUriInfo = codeActionCodeInfo.uriToInfo.get(rootAndRelatedIdentifiersAndUri.uri) ??
{ identifiers: [], numValidWorkspaceEdits: 0 };
existingInfo.identifiers.push(...rootAndRelatedIdentifiersAndUri.identifiers);
const rootAndRelatedWorkspaceEdit: CodeActionWorkspaceEdit = rootAndRelatedWorkspaceEdits[rootAndRelatedWorkspaceEditsIndex];
if (rootAndRelatedWorkspaceEdit !== undefined) {
if (existingInfo.workspaceEdits === undefined) {
existingInfo.workspaceEdits = [ rootAndRelatedWorkspaceEdit ];
} else {
existingInfo.workspaceEdits.push(rootAndRelatedWorkspaceEdit);
}
++existingInfo.numValidWorkspaceEdits;
}
codeActionCodeInfo.uriToInfo.set(rootAndRelatedIdentifiersAndUri.uri, existingInfo);
++rootAndRelatedWorkspaceEditsIndex;
}
if (!identifier.code.startsWith("clang-diagnostic-")) {
const codes: string[] = identifier.code.split(',');
let codeIndex: number = codes.length - 1;
if (codes[codeIndex] === "cert-dcl51-cpp") { // Handle aliasing
codeIndex = 0;
}
// TODO: Is the ideal code always selected as the primary one?
const primaryCode: string = codes[codeIndex];
const docPage: string = primaryCode === "clang-tidy-nolint" ? "#suppressing-undesired-diagnostics" :
`checks/${primaryCode}.html`;
const primaryDocUri: vscode.Uri = vscode.Uri.parse(`https://releases.llvm.org/14.0.0/tools/clang/tools/extra/docs/clang-tidy/${docPage}`);
diagnostic.code = { value: identifier.code, target: primaryDocUri };
if (new CppSettings().clangTidyCodeActionShowDocumentation) {
if (codeActionCodeInfo.docCodeAction === undefined) {
codeActionCodeInfo.docCodeAction = {
title: localize("show_documentation_for", "Show documentation for {0}", primaryCode),
command: { title: 'ShowDocumentation', command: 'C_Cpp.ShowCodeAnalysisDocumentation',
arguments: [ primaryDocUri ] },
kind: vscode.CodeActionKind.QuickFix
};
}
} else {
codeActionCodeInfo.docCodeAction = undefined;
}
} else {
diagnostic.code = d.code;
}
codeAnalysisCodeToFixes.set(identifier.code, codeActionCodeInfo);
} else {
diagnostic.code = d.code;
}
diagnostic.source = CppSourceStr;
codeActionDiagnosticInfo.push(codeAction);
if (relatedCodeActions.length > 0) {
codeActionDiagnosticInfo.push(...relatedCodeActions);
}
diagnosticsCodeAnalysis.push(diagnostic);
}
codeAnalysisFileToCodeActions.set(params.uri, codeActionDiagnosticInfo);
rebuildCodeAnalysisCodeAndAllFixes();
diagnosticsCollectionCodeAnalysis.set(realUri, diagnosticsCodeAnalysis);
}
function removeCodeAnalysisCodeActions(identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[],
removeFixesOnly: boolean): void {
for (const identifiersAndUri of identifiersAndUris) {
const codeActionDiagnosticInfo: CodeActionDiagnosticInfo[] | undefined = codeAnalysisFileToCodeActions.get(identifiersAndUri.uri);
if (codeActionDiagnosticInfo === undefined) {
return;
}
for (const identifier of identifiersAndUri.identifiers) {
const updatedCodeActions: CodeActionDiagnosticInfo[] = [];
for (const codeAction of codeActionDiagnosticInfo) {
if (rangeEquals(codeAction.range, identifier.range) && codeAction.code === identifier.code) {
if (removeFixesOnly) {
++codeAction.version;
codeAction.fixCodeAction = undefined;
} else {
continue;
}
}
updatedCodeActions.push(codeAction);
}
codeAnalysisFileToCodeActions.set(identifiersAndUri.uri, updatedCodeActions);
let codeActionInfoChanged: boolean = false;
for (const codeFixes of codeAnalysisCodeToFixes) {
const codeActionInfo: CodeActionPerUriInfo | undefined = codeFixes[1].uriToInfo.get(identifiersAndUri.uri);
if (codeActionInfo === undefined) {
continue;
}
let removedCodeActionInfoIndex: number = -1;
for (let codeActionInfoIndex: number = 0; codeActionInfoIndex < codeActionInfo.identifiers.length; ++codeActionInfoIndex) {
if (identifier.code === codeActionInfo.identifiers[codeActionInfoIndex].code &&
rangeEquals(identifier.range, codeActionInfo.identifiers[codeActionInfoIndex].range)) {
removedCodeActionInfoIndex = codeActionInfoIndex;
codeActionInfoChanged = true;
break;
}
}
if (removedCodeActionInfoIndex !== -1) {
if (removeFixesOnly) {
if (codeActionInfo.workspaceEdits !== undefined) {
codeActionInfo.workspaceEdits[removedCodeActionInfoIndex].workspaceEdit = undefined;
--codeActionInfo.numValidWorkspaceEdits;
}
} else {
codeActionInfo.identifiers.splice(removedCodeActionInfoIndex, 1);
if (codeActionInfo.workspaceEdits !== undefined) {
codeActionInfo.workspaceEdits.splice(removedCodeActionInfoIndex, 1);
--codeActionInfo.numValidWorkspaceEdits;
}
}
if (codeActionInfo.identifiers.length === 0) {
codeFixes[1].uriToInfo.delete(identifiersAndUri.uri);
} else {
codeFixes[1].uriToInfo.set(identifiersAndUri.uri, codeActionInfo);
}
}
}
if (codeActionInfoChanged) {
rebuildCodeAnalysisCodeAndAllFixes();
}
}
}
}
export function publishRemoveCodeAnalysisCodeActionFixes(params: RemoveCodeAnalysisCodeActionFixesParams): void {
removeCodeAnalysisCodeActions(params.identifiersAndUris, true);
}
export function removeAllCodeAnalysisProblems(): boolean {
if (!diagnosticsCollectionCodeAnalysis) {
return false;
}
diagnosticsCollectionCodeAnalysis.clear();
codeAnalysisFileToCodeActions.clear();
codeAnalysisCodeToFixes.clear();
rebuildCodeAnalysisCodeAndAllFixes();
return true;
}
export function removeCodeAnalysisProblems(identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): boolean {
if (!diagnosticsCollectionCodeAnalysis) {
return false;
}
// Remove the diagnostics.
for (const identifiersAndUri of identifiersAndUris) {
const uri: vscode.Uri = vscode.Uri.parse(identifiersAndUri.uri);
const diagnostics: readonly vscode.Diagnostic[] | undefined = diagnosticsCollectionCodeAnalysis.get(uri);
if (diagnostics === undefined) {
continue;
}
const newDiagnostics: vscode.Diagnostic[] = [];
for (const diagnostic of diagnostics) {
const code: string = typeof diagnostic.code === "string" ? diagnostic.code :
(typeof diagnostic.code === "object" && typeof diagnostic.code.value === "string" ?
diagnostic.code.value : "");
let removed: boolean = false;
for (const identifier of identifiersAndUri.identifiers) {
if (code !== identifier.code || !rangeEquals(diagnostic.range, identifier.range)) {
continue;
}
removed = true;
break;
}
if (!removed) {
newDiagnostics.push(diagnostic);
}
}
diagnosticsCollectionCodeAnalysis.set(uri, newDiagnostics);
}
removeCodeAnalysisCodeActions(identifiersAndUris, false);
return true;
}
@@ -0,0 +1,21 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import { Range } from 'vscode-languageclient';
/** Differs from vscode.Location, which has a uri of type vscode.Uri. */
export interface Location {
uri: string;
range: Range;
}
export interface TextEdit {
range: Range;
newText: string;
}
export interface WorkspaceEdit {
changes: { [uri: string]: TextEdit[] };
}
@@ -122,10 +122,19 @@ export class CppBuildTaskProvider implements TaskProvider {
const knownCompilerPathsSet: Set<string> = new Set();
let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers();
if (knownCompilers) {
const compiler_condition: (info: configs.KnownCompiler) => boolean = info => ((fileIsCpp && !info.isC) || (fileIsC && info.isC)) &&
(!isCompilerValid || (!!userCompilerPathAndArgs &&
(path.basename(info.path) !== userCompilerPathAndArgs.compilerName))) &&
(!isWindows || !info.path.startsWith("/")); // TODO: Add WSL compiler support.
const compiler_condition: (info: configs.KnownCompiler) => boolean = info =>
(
// Filter out c compilers for cpp files and vice versa, except for cl.exe, which handles both.
path.basename(info.path) === "cl.exe" ||
(fileIsCpp && !info.isC) || (fileIsC && info.isC)
) &&
(
!isCompilerValid || (!!userCompilerPathAndArgs &&
(path.basename(info.path) !== userCompilerPathAndArgs.compilerName))
) &&
(
!isWindows || !info.path.startsWith("/")
); // TODO: Add WSL compiler support.
const cl_to_add: configs.KnownCompiler | undefined = userCompilerIsCl ? undefined : knownCompilers.find(info =>
((path.basename(info.path) === "cl.exe") && compiler_condition(info)));
knownCompilers = knownCompilers.filter(info =>
+4 -3
View File
@@ -12,8 +12,9 @@ import * as util from '../common';
import * as telemetry from '../telemetry';
import { TreeNode, NodeType } from './referencesModel';
import { UI, getUI } from './ui';
import { Client, openFileVersions, CodeAnalysisDiagnosticIdentifiersAndUri, CodeActionDiagnosticInfo, codeAnalysisCodeToFixes,
codeAnalysisFileToCodeActions, codeAnalysisAllFixes } from './client';
import { Client, openFileVersions } from './client';
import { CodeAnalysisDiagnosticIdentifiersAndUri, CodeActionDiagnosticInfo, codeAnalysisCodeToFixes,
codeAnalysisFileToCodeActions, codeAnalysisAllFixes } from './codeAnalysis';
import { makeCpptoolsRange, rangeEquals } from './utils';
import { ClientCollection } from './clientCollection';
import { CppSettings, OtherSettings } from './settings';
@@ -362,7 +363,7 @@ export function processDelayedDidOpen(document: vscode.TextDocument): boolean {
return false;
}
function onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
function onDidChangeVisibleTextEditors(editors: readonly vscode.TextEditor[]): void {
// Process delayed didOpen for any visible editors we haven't seen before
editors.forEach(editor => {
if ((editor.document.uri.scheme === "file") && (editor.document.languageId === "c" || editor.document.languageId === "cpp" || editor.document.languageId === "cuda-cpp")) {
@@ -0,0 +1,75 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import { getExtensionFilePath } from '../common';
import { lookupString } from '../nativeStrings';
import * as nls from 'vscode-nls';
import path = require('path');
import * as fs from 'fs';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
export interface LocalizeStringParams {
text: string;
stringId: number;
stringArgs: string[];
indentSpaces: number;
}
export function getLocalizedString(params: LocalizeStringParams): string {
let indent: string = "";
if (params.indentSpaces) {
indent = " ".repeat(params.indentSpaces);
}
let text: string = params.text;
if (params.stringId !== 0) {
text = lookupString(params.stringId, params.stringArgs);
}
return indent + text;
}
interface VSCodeNlsConfig {
locale: string;
availableLanguages: {
[pack: string]: string;
};
}
export function getLocaleId(): string {
// This replicates the language detection used by initializeSettings() in vscode-nls
if (typeof process.env.VSCODE_NLS_CONFIG === 'string') {
const vscodeOptions: VSCodeNlsConfig = JSON.parse(process.env.VSCODE_NLS_CONFIG) as VSCodeNlsConfig;
if (vscodeOptions.availableLanguages) {
const value: any = vscodeOptions.availableLanguages['*'];
if (typeof value === 'string') {
return value;
}
}
if (typeof vscodeOptions.locale === 'string') {
return vscodeOptions.locale.toLowerCase();
}
}
return "en";
}
export function getLocalizedHtmlPath(originalPath: string): string {
const locale: string = getLocaleId();
if (!locale.startsWith("en")) {
const localizedFilePath: string = getExtensionFilePath(path.join("dist/html/", locale, originalPath));
if (fs.existsSync(localizedFilePath)) {
return localizedFilePath;
}
}
return getExtensionFilePath(originalPath);
}
export function getLocalizedSymbolScope(scope: string, detail: string): string {
return localize({
key: "c.cpp.symbolscope.separator", comment:
["{0} is an untranslated C++ keyword (e.g. \"private\") and {1} is either another keyword (e.g. \"typedef\") or a localized property (e.g. a localized version of \"declaration\""]
}, "{0}, {1}", scope, detail);
}
+29
View File
@@ -252,6 +252,34 @@ export class CppSettings extends Settings {
public get codeFolding(): boolean { return super.Section.get<string>("codeFolding") === "Enabled"; }
public get legacyCompilerArgsBehavior(): boolean | undefined { return super.Section.get<boolean>("legacyCompilerArgsBehavior"); }
public get inlayHintsAutoDeclarationTypes(): boolean {
return super.Section.get<boolean>("inlayHints.autoDeclarationTypes.enabled") === true;
}
public get inlayHintsAutoDeclarationTypesShowOnLeft(): boolean {
return super.Section.get<boolean>("inlayHints.autoDeclarationTypes.showOnLeft") === true;
}
public get inlayHintsParameterNames(): boolean {
return super.Section.get<boolean>("inlayHints.parameterNames.enabled") === true;
}
public get inlayHintsParameterNamesSuppressName(): boolean {
return super.Section.get<boolean>("inlayHints.parameterNames.suppressWhenArgumentContainsName") === true;
}
public get inlayHintsParameterNamesHideLeadingUnderscores(): boolean {
return super.Section.get<boolean>("inlayHints.parameterNames.hideLeadingUnderscores") === true;
}
public get inlayHintsReferenceOperator(): boolean {
return super.Section.get<boolean>("inlayHints.referenceOperator.enabled") === true;
}
public get inlayHintsReferenceOperatorShowSpace(): boolean {
return super.Section.get<boolean>("inlayHints.referenceOperator.showSpace") === true;
}
public get enhancedColorization(): boolean {
return super.Section.get<string>("enhancedColorization") === "Enabled"
&& super.Section.get<string>("intelliSenseEngine") === "Default"
@@ -788,6 +816,7 @@ export class OtherSettings {
}
public get filesExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); }
public get filesAutoSaveAfterDelay(): boolean { return vscode.workspace.getConfiguration("files").get("autoSave") === "afterDelay"; }
public get InlayHintsEnabled(): boolean { return vscode.workspace.getConfiguration("editor.inlayHints").get<string>("enabled") !== "off"; }
public get searchExclude(): vscode.WorkspaceConfiguration | undefined { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); }
public get settingsEditor(): string | undefined { return vscode.workspace.getConfiguration("workbench.settings").get<string>("editor"); }
@@ -10,6 +10,7 @@ import * as vscode from 'vscode';
import * as util from '../common';
import * as config from './configurations';
import * as telemetry from '../telemetry';
import { getLocalizedHtmlPath } from './localization';
// TODO: share ElementId between SettingsPanel and SettingsApp. Investigate why SettingsApp cannot import/export
const elementId: { [key: string]: string } = {
@@ -373,7 +374,7 @@ export class SettingsPanel {
private getHtml(): string {
let content: string | undefined;
content = fs.readFileSync(util.getLocalizedHtmlPath("ui/settings.html")).toString();
content = fs.readFileSync(getLocalizedHtmlPath("ui/settings.html")).toString();
if (this.panel && this.panel.webview) {
const cppImageUri: vscode.Uri = this.panel.webview.asWebviewUri(vscode.Uri.file(path.join(util.extensionPath, 'LanguageCCPP_color_128x.png')));
+1 -11
View File
@@ -5,17 +5,7 @@
'use strict';
import * as vscode from 'vscode';
import { Range } from 'vscode-languageclient';
/** Differs from vscode.Location, which has a uri of type vscode.Uri. */
export interface Location {
uri: string;
range: Range;
}
export interface TextEdit {
range: Range;
newText: string;
}
import { Location, TextEdit } from './commonTypes';
export function makeCpptoolsRange(vscRange: vscode.Range): Range {
return { start: { line: vscRange.start.line, character: vscRange.start.character },
+340
View File
@@ -0,0 +1,340 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { stripEscapeSequences, isWindows, escapeStringForRegex } from '../common';
export type IDifferingHostConfirmationProvider =
(message: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
export type IFingerprintConfirmationProvider =
(host: string, fingerprint: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
export interface IInteraction {
canceled?: boolean;
postAction?: 'consume' | 'keep';
response?: string;
isPassword?: boolean;
continue?: boolean; // Continue without waiting for the program to finish or pause
}
export interface IInteractorDataDetails {
detectedServerKey?: string;
detail?: string;
}
export interface IInteractor {
id: string;
onData(data: string, cancelToken?: vscode.CancellationToken, extraDetails?: IInteractorDataDetails): Promise<IInteraction>;
}
export class MitmInteractor implements IInteractor {
static ID = 'mitm';
constructor() { }
get id(): string {
return MitmInteractor.ID;
}
async onData(data: string): Promise<IInteraction> {
if (!!data.match('Port forwarding is disabled to avoid man-in-the-middle attacks.')) {
throw Error('Port forwarding is disabled to avoid man-in-the-middle attacks.');
}
return {};
}
}
export class FingerprintInteractor implements IInteractor {
static ID = 'fingerprint';
constructor(private readonly hostName: string, private readonly confirmationProvider: IFingerprintConfirmationProvider) { }
get id(): string {
return FingerprintInteractor.ID;
}
async onData(data: string, cancelToken?: vscode.CancellationToken, extraDetails?: IInteractorDataDetails): Promise<IInteraction> {
const fingerprintMatcher: RegExp = /fingerprint\sis\s(.+)\./;
const result: IInteraction = { postAction: 'keep' };
data = data.trim();
let fingerprintMatch: RegExpMatchArray | null;
if (
data.includes('Are you sure you want to continue connecting') &&
(fingerprintMatch = data.match(fingerprintMatcher))
) {
result.postAction = 'consume';
const confirmation: string | undefined = await this.confirmationProvider(
this.hostName,
fingerprintMatch[1],
cancelToken
);
if (confirmation) {
result.response = confirmation;
} else {
result.canceled = true;
}
} else if (
isWindows() &&
(data.includes('The authenticity of host ') || (data === '' && extraDetails?.detectedServerKey))
) {
// hack for #1195
// First line local server case (git ssh only gives the first line over ssh_askpass)
const key: string = extraDetails?.detectedServerKey || '(unknown)';
result.postAction = 'consume';
const confirmation: string | undefined = await this.confirmationProvider(this.hostName, key, cancelToken);
if (confirmation) {
result.response = confirmation;
} else {
result.canceled = true;
}
}
return result;
}
}
export class DifferingHostKeyInteractor implements IInteractor {
static ID = 'differing host key';
constructor(private readonly confirmationProvider: IDifferingHostConfirmationProvider) { }
get id(): string {
return DifferingHostKeyInteractor.ID;
}
async onData(data: string, cancelToken?: vscode.CancellationToken, _extraDetails?: IInteractorDataDetails): Promise<IInteraction> {
const result: IInteraction = { postAction: 'keep' };
data = data.trim();
if (
data.includes('Are you sure you want to continue connecting') &&
data.includes('Offending key for IP in') &&
data.includes('Matching host key in')
) {
result.postAction = 'consume';
const message: string = data.substring(data.indexOf('Warning'), data.indexOf('Are')).trim();
const confirmation: string | undefined = await this.confirmationProvider(message, cancelToken);
if (confirmation) {
result.response = confirmation;
} else {
result.canceled = true;
}
}
return result;
}
}
export type IStringProvider =
(key?: string, detail?: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
export class PassphraseInteractor implements IInteractor {
static ID = 'passphrase';
constructor(private readonly passphraseProvider: IStringProvider) { }
get id(): string {
return PassphraseInteractor.ID;
}
async onData(data: string, cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
const result: IInteraction = { postAction: 'keep' };
const lines: string[] = data.trim().split('\n');
if (lines.some(l => l.indexOf('Enter passphrase for') >= 0)) {
result.postAction = 'consume';
const passphrase: string | undefined = await this.passphraseProvider(undefined, undefined, cancelToken); // TODO keep track of the key name
if (typeof passphrase === 'string') {
result.response = passphrase;
result.isPassword = true;
} else {
result.canceled = true;
}
} else if (lines.some(l => l.indexOf('Identity added:') >= 0)) {
result.postAction = 'consume';
}
return result;
}
}
export function getExitCode(output: string, marker: string): number | undefined {
const regex: RegExp = new RegExp(`${marker}##([0-9]*)##`);
const match: RegExpExecArray | null = regex.exec(output);
if (match) {
try {
const num: number = parseInt(match[1]);
return Number.isNaN(num) ? undefined : num;
} catch (err) {
return undefined;
}
}
return 0;
}
/**
* Matches SSH password prompt of format:
* 's password:
* or
* Password:
* not
* 's old password:
* 's new password:
*/
function getPasswordPrompt(data: string, details?: IInteractorDataDetails): { user?: string; message?: string } | undefined {
if (data.includes('Password:')) {
// Password prompt for unspecified user
return { user: '' };
}
// Got \r\r\n as a line ending here
const match: RegExpMatchArray | null = stripEscapeSequences(data).match(/([a-zA-Z0-9\-_@\.]*)'s password:/);
if (match) {
return {
user: match[1],
message: details ? details.detail : undefined
};
}
return undefined;
}
export class PasswordInteractor implements IInteractor {
static ID = 'password';
constructor(private readonly passwordProvider: IStringProvider) { }
get id(): string {
return PasswordInteractor.ID;
}
async onData(data: string, cancelToken?: vscode.CancellationToken, extraDetails?: IInteractorDataDetails): Promise<IInteraction> {
const result: IInteraction = { postAction: 'keep' };
const pwPrompt: { user?: string; message?: string } | undefined = getPasswordPrompt(data, extraDetails);
if (pwPrompt && typeof pwPrompt.user === 'string') {
result.postAction = 'consume';
const password: string | undefined = await this.passwordProvider(pwPrompt.user, pwPrompt.message, cancelToken);
if (typeof password === 'string') {
result.response = password;
result.isPassword = true;
} else {
result.canceled = true;
}
}
return result;
}
}
export type IVerificationCodeProvider =
(msg: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
export class TwoFacInteractor implements IInteractor {
static ID = '2fa';
constructor(private readonly verificationCodeProvider: IVerificationCodeProvider) { }
get id(): string {
return TwoFacInteractor.ID;
}
async onData(data: string, cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
const result: IInteraction = { postAction: 'keep' };
if (data.includes('Verification code:')) {
result.postAction = 'consume';
const verificationCode: string | undefined = await this.verificationCodeProvider('Enter verification code', cancelToken);
if (typeof verificationCode === 'string') {
result.response = verificationCode;
result.isPassword = true;
} else {
result.canceled = true;
}
}
return result;
}
}
// https://github.com/microsoft/vscode-remote-release/issues/2170
export class DuoTwoFacInteractor implements IInteractor {
static ID = 'duo-2fa';
constructor(private readonly verificationCodeProvider: IVerificationCodeProvider) { }
get id(): string {
return DuoTwoFacInteractor.ID;
}
async onData(data: string, cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
const result: IInteraction = { postAction: 'keep' };
if (data.includes('Passcode:')) {
result.postAction = 'consume';
const verificationCode: string | undefined = await this.verificationCodeProvider('Enter passcode', cancelToken);
if (typeof verificationCode === 'string') {
result.response = verificationCode;
result.isPassword = true;
} else {
result.canceled = true;
}
}
return result;
}
}
export class ContinueOnInteractor implements IInteractor {
static ID = 'continueOn';
constructor(private readonly continueOn: string) { }
get id(): string {
return ContinueOnInteractor.ID;
}
async onData(data: string, _cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
const result: IInteraction = { postAction: 'keep' };
const pattern: string = escapeStringForRegex(this.continueOn);
const re: RegExp = new RegExp(pattern, 'g');
if (data.match(re)) {
result.continue = true;
}
return result;
}
}
export class ComposedInteractor implements IInteractor {
constructor(private readonly interactors: IInteractor[]) { }
get id(): string {
return 'composed';
}
async onData(data: string): Promise<IInteraction> {
for (const interactor of this.interactors) {
const result: IInteraction = await interactor.onData(data);
if (result.postAction === 'consume') {
return result;
}
}
return { postAction: 'keep' };
}
}
export interface ISystemInteractor {
createTerminal(options: vscode.TerminalOptions): vscode.Terminal;
onDidCloseTerminal: typeof vscode.window.onDidCloseTerminal;
onDidWriteTerminalData: typeof vscode.window.onDidWriteTerminalData;
}
export const defaultSystemInteractor: ISystemInteractor = {
createTerminal: vscode.window.createTerminal,
onDidCloseTerminal: vscode.window.onDidCloseTerminal,
onDidWriteTerminalData: vscode.window.onDidWriteTerminalData
};
+98
View File
@@ -0,0 +1,98 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { ISshHostInfo, ISshLocalForwardInfo, ProcessReturnType } from '../common';
import { defaultSystemInteractor } from './commandInteractors';
import { runSshTerminalCommandWithLogin } from './sshCommandRunner';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
export async function scp(files: vscode.Uri[], host: ISshHostInfo, targetDir: string, scpPath?: string, jumpHosts?: ISshHostInfo[], cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
const args: string[] = [];
if (jumpHosts && jumpHosts.length > 0) {
args.push('-J', jumpHosts.map(getFullHostAddress).join(','));
}
if (host.port) {
// upper case P
args.push('-P', `${host.port}`);
}
args.push(files.map(uri => `"${uri.fsPath}"`).join(' '), `${getFullHostAddressNoPort(host)}:${targetDir}`);
return runSshTerminalCommandWithLogin(host, { systemInteractor: defaultSystemInteractor, nickname: 'scp', command: `"${scpPath || 'scp'}" ${args.join(' ')}`, token: cancellationToken });
}
export function ssh(host: ISshHostInfo, command: string, sshPath?: string, jumpHosts?: ISshHostInfo[], localForwards?: ISshLocalForwardInfo[], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
const args: string[] = [];
if (jumpHosts && jumpHosts.length > 0) {
args.push('-J', jumpHosts.map(getFullHostAddress).join(','));
}
if (host.port) {
// lower case p
args.push('-p', `${host.port}`);
}
if (localForwards) {
localForwards.forEach(info => args.push(...localForwardToArgs(info)));
}
args.push(getFullHostAddressNoPort(host), `"${command}"`);
return runSshTerminalCommandWithLogin(host, {
systemInteractor: defaultSystemInteractor,
command: `"${sshPath || 'ssh'}" ${args.join(' ')}`,
nickname: 'ssh',
continueOn,
token: cancellationToken
});
}
/**
* Takes one local forward info and convert it to '-L' args in ssh.
*/
function localForwardToArgs(localForward: ISshLocalForwardInfo): string[] {
// Do not combine error checking and arg conversion for clarity.
if (localForward.localSocket && (localForward.bindAddress || localForward.port)) {
throw Error(localize('local.forward.local.conflict', '"localSocket" cannot be specifed at the same time with "bindAddress" or "port" in localForwards'));
}
if (!localForward.localSocket && !localForward.port) {
throw Error(localize('local.forward.local.missing', '"port" or "localSocket" required in localForwards'));
}
if (localForward.remoteSocket && (localForward.host || localForward.hostPort)) {
throw Error(localize('local.forward.remote.conflict', '"remoteSocket" cannot be specifed at the same time with "host" or "hostPort" in localForwards'));
}
if (!localForward.remoteSocket && (!localForward.host || !localForward.hostPort)) {
throw Error(localize('local.forward.remote.missing', '"host" and "hostPort", or "remoteSocket" required in localForwards'));
}
let arg: string = '';
if (localForward.localSocket) {
arg += `${localForward.localSocket}:`;
}
if (localForward.bindAddress) {
arg += `${localForward.bindAddress}:`;
}
if (localForward.port) {
arg += `${localForward.port}:`;
}
if (localForward.remoteSocket) {
arg += `${localForward.remoteSocket}`;
}
if (localForward.host && localForward.hostPort) {
arg += `${localForward.host}:${localForward.hostPort}`;
}
return ['-L', arg];
}
/** user@host */
function getFullHostAddressNoPort(host: ISshHostInfo): string {
return host.user ? `${host.user}@${host.hostName}` : `${host.hostName}`;
}
function getFullHostAddress(host: ISshHostInfo): string {
const fullHostName: string = getFullHostAddressNoPort(host);
return host.port ? `${fullHostName}:${host.port}` : fullHostName;
}
+518
View File
@@ -0,0 +1,518 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as os from 'os';
import * as path from 'path';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import {
DifferingHostKeyInteractor,
DuoTwoFacInteractor,
FingerprintInteractor,
IInteractor,
MitmInteractor,
PassphraseInteractor,
PasswordInteractor,
TwoFacInteractor,
ContinueOnInteractor,
ISystemInteractor,
IInteraction
} from './commandInteractors';
import { isWindows, ISshHostInfo, splitLines, stripEscapeSequences, ProcessReturnType } from '../common';
import { getOutputChannelLogger } from '../logger';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
export class CanceledError extends Error {
constructor() {
super(localize('ssh.canceled', 'SSH command canceled'));
}
}
export interface ICommandResult {
stdout: string;
stderr: string;
}
export function showPassphraseInputBox(
keyName?: string,
prompt?: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
const keyStr: string = keyName ? `"${keyName}"` : '';
const msg: string = localize('ssh.passphrase.input.box', 'Enter passphrase for ssh key {0}', keyStr);
return showInputBox(msg, prompt, cancelToken);
}
export function showPasswordInputBox(
user: string | undefined,
prompt?: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
const msg: string = user ? localize('ssh.enter.password.for.user', 'Enter password for user "{0}"', user) : localize('ssh_message_enterPassword', 'Enter password');
return showInputBox(msg, prompt, cancelToken);
}
export function showVerificationCodeInputBox(
msg: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
return showInputBox(msg, undefined, cancelToken);
}
export async function showInputBox(
msg: string,
prompt?: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
return new Promise((resolve, reject) => {
const quickPick: vscode.InputBox = vscode.window.createInputBox();
quickPick.title = msg;
quickPick.prompt = prompt;
quickPick.password = true;
quickPick.ignoreFocusOut = true;
let isAccepted: boolean = false;
quickPick.onDidAccept(() => {
isAccepted = true;
const passphrase: string = quickPick.value;
quickPick.dispose();
resolve(passphrase);
});
quickPick.onDidHide(() => {
if (!isAccepted) {
resolve(undefined);
}
});
quickPick.show();
if (cancelToken) {
cancelToken.onCancellationRequested(() => {
reject(new CanceledError());
quickPick.dispose();
});
}
});
}
class ConfirmationItem implements vscode.QuickPickItem, vscode.MessageItem {
title: string;
isCloseAffordance: boolean = true;
constructor(public label: string, public value: string) {
this.title = label;
}
}
const continueConfirmationPlaceholder: string = localize('ssh.continue.confirmation.placeholder', 'Are you sure you want to continue?');
export async function showHostKeyConfirmation(
host: string,
fingerprint: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
return showConfirmationPicker(
localize('ssh.host.key.confirmation.title', '"{0}" has fingerprint "{1}".', host, fingerprint),
continueConfirmationPlaceholder,
cancelToken
);
}
export async function showDifferingHostConfirmation(
message: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
return showConfirmationPicker(message, continueConfirmationPlaceholder, cancelToken);
}
async function showConfirmationPicker(
title: string,
placeholder: string,
cancelToken?: vscode.CancellationToken
): Promise<string | undefined> {
return new Promise((resolve, reject) => {
const quickPick: vscode.QuickPick<ConfirmationItem> = vscode.window.createQuickPick<ConfirmationItem>();
quickPick.canSelectMany = false;
quickPick.items = [new ConfirmationItem(localize('continue', 'Continue'), 'yes'), new ConfirmationItem(localize('cancel', 'Cancel'), 'no')];
quickPick.title = title;
quickPick.placeholder = placeholder;
let isAccepted: boolean = false;
quickPick.onDidAccept(async () => {
isAccepted = true;
const value: string = quickPick.selectedItems[0].value;
quickPick.dispose();
resolve(value);
});
quickPick.onDidHide(() => {
if (!isAccepted) {
resolve(undefined);
}
});
quickPick.show();
if (cancelToken) {
cancelToken.onCancellationRequested(() => {
quickPick.hide();
reject(new CanceledError());
});
}
});
}
export interface ITerminalCommandWithLoginArgs {
systemInteractor: ISystemInteractor;
command: string;
nickname: string;
marker?: string;
usedInteractors?: Set<string>;
interactor?: IInteractor;
cwd?: string;
token?: vscode.CancellationToken;
continueOn?: string;
revealTerminal?: vscode.Event<void>;
}
export async function runSshTerminalCommandWithLogin(
host: ISshHostInfo,
terminalArgs: ITerminalCommandWithLoginArgs,
showLoginTerminal = false
): Promise<ProcessReturnType> {
const interactors: IInteractor[] = [];
if (terminalArgs.interactor) {
interactors.push(terminalArgs.interactor);
}
if (!showLoginTerminal) {
interactors.push(
new MitmInteractor(),
new FingerprintInteractor(host.hostName, showHostKeyConfirmation),
new PassphraseInteractor(showPassphraseInputBox),
new DifferingHostKeyInteractor(showDifferingHostConfirmation),
new PasswordInteractor(showPasswordInputBox),
new TwoFacInteractor(showVerificationCodeInputBox),
new DuoTwoFacInteractor(showVerificationCodeInputBox)
);
}
if (terminalArgs.continueOn) {
interactors.push(new ContinueOnInteractor(terminalArgs.continueOn));
}
// This terminal is always local
const result: ProcessReturnType = await runInteractiveSshTerminalCommand({
systemInteractor: terminalArgs.systemInteractor,
command: terminalArgs.command,
interactors,
usedInteractors: terminalArgs.usedInteractors,
nickname: terminalArgs.nickname,
token: terminalArgs.token,
marker: terminalArgs.marker,
revealTerminal: terminalArgs.revealTerminal,
showLoginTerminal,
cwd: terminalArgs.cwd ? vscode.Uri.file(terminalArgs.cwd) : undefined
});
return result;
}
export interface ITerminalCommandArgs {
systemInteractor: ISystemInteractor;
command: string;
interactors?: IInteractor[];
nickname: string;
usedInteractors?: Set<string>;
sendText?: string;
cwd?: vscode.Uri;
terminalIsWindows?: boolean;
token?: vscode.CancellationToken;
marker?: string;
revealTerminal?: vscode.Event<void>;
showLoginTerminal?: boolean; // If true, respect the showLoginTerminal setting
}
export function getPauseLogMarker(uuid: string): string {
return `${uuid}: pauseLog`;
}
export function getResumeLogMarker(uuid: string): string {
return `${uuid}: resumeLog`;
}
export function runInteractiveSshTerminalCommand(args: ITerminalCommandArgs): Promise<ProcessReturnType> {
const disposables: vscode.Disposable[] = [];
const { systemInteractor, command, interactors, nickname, token } = args;
let logIsPaused: boolean = false;
return new Promise(async (resolve, reject) => {
let stdout: string = '';
let windowListener: vscode.Disposable | undefined;
let terminalListener: vscode.Disposable | undefined;
let terminal: vscode.Terminal | undefined;
let tokenListener: vscode.Disposable;
let continueWithoutExiting: boolean = false;
const clean = () => {
if (terminalListener) {
terminalListener.dispose();
terminalListener = undefined;
}
if (terminal) {
terminal.dispose();
terminal = undefined;
}
if (windowListener) {
windowListener.dispose();
windowListener = undefined;
}
if (tokenListener) {
tokenListener.dispose();
}
disposables.forEach(disposable => disposable.dispose());
};
const done = (cancel: boolean = false, noClean: boolean = false, exitCode?: number) => {
if (!noClean) {
clean();
}
getOutputChannelLogger().appendLine(cancel ? localize('ssh.terminal.command.canceled', '"{0}" terminal command canceled.', nickname) : localize('ssh.terminal.command.done', '"{0}" terminal command done.', nickname));
if (cancel) {
if (continueWithoutExiting) {
getOutputChannelLogger().showWarningMessage(localize('ssh.continuing.command.canceled', 'Task \'{0}\' is canceled, but the underlying command may not be terminated. Please check manually.', command));
}
return reject(new CanceledError());
}
// When using showLoginTerminal, stdout include the passphrase prompt, etc. Try to get just the command output on the last line.
const actualOutput: string | undefined = cancel ? '' : lastNonemptyLine(stdout);
resolve({ succeeded: !exitCode, exitCode, output: actualOutput || '' });
};
const failed = (error?: any) => {
clean();
getOutputChannelLogger().showErrorMessage(localize('ssh.process.failed', '"{0}" process failed: {1}', nickname, error));
reject(error);
};
const handleOutputLogging = (data: string): void => {
let nextPauseState: boolean | undefined;
if (args.marker) {
const pauseMarker: string = getPauseLogMarker(args.marker);
const pauseIdx: number = data.lastIndexOf(pauseMarker);
if (pauseIdx >= 0) {
data = data.substring(0, pauseIdx + pauseMarker.length);
nextPauseState = true;
}
const resumeIdx: number = data.lastIndexOf(getResumeLogMarker(args.marker));
if (resumeIdx >= 0) {
data = data.substring(resumeIdx);
nextPauseState = false;
}
}
// Log the chunk of data that includes the pause/resume markers,
// so unpause first and pause after logging
if (!logIsPaused) {
logReceivedData(data, nickname);
}
if (typeof nextPauseState === 'boolean') {
logIsPaused = nextPauseState;
}
};
const handleTerminalOutput = async (dataWrite: vscode.TerminalDataWriteEvent): Promise<void> => {
handleOutputLogging(dataWrite.data);
stdout += dataWrite.data;
if (interactors) {
for (const interactor of interactors) {
try {
const interaction: IInteraction = await interactor.onData(stdout);
if (interaction.postAction === 'consume') {
if (args.usedInteractors) {
args.usedInteractors.add(interactor.id);
}
stdout = '';
}
if (interaction.canceled) {
if (args.usedInteractors) {
args.usedInteractors.add(interactor.id);
}
done(true);
return;
}
if (interaction.continue) {
if (args.usedInteractors) {
args.usedInteractors.add(interactor.id);
}
continueWithoutExiting = true;
done(false, true);
return;
}
if (typeof interaction.response === 'string') {
if (args.usedInteractors) {
args.usedInteractors.add(interactor.id);
}
if (terminal) {
terminal.sendText(`${interaction.response}\n`);
const logOutput: string = interaction.isPassword
? interaction.response.replace(/./g, '*')
: interaction.response;
getOutputChannelLogger().appendLine(localize('ssh.wrote.data.to.terminal', '"{0}" wrote data to terminal: "{1}".', nickname, logOutput));
}
}
} catch (e) {
failed(e);
}
}
}
};
if (token) {
tokenListener = token.onCancellationRequested(() => {
done(true);
});
}
const terminalIsWindows: boolean = typeof args.terminalIsWindows === 'boolean' ? args.terminalIsWindows : isWindows();
try {
// the terminal process should not fail, but exit cleanly
let shellArgs: string | string[];
if (args.sendText) {
shellArgs = '';
} else {
shellArgs = terminalIsWindows ? `/c (${command})\nexit /b %ErrorLevel%` : ['-c', `${command}\nexit $?`];
}
const options: vscode.TerminalOptions = {
cwd:
args.cwd ||
(terminalIsWindows
? vscode.Uri.file(os.homedir() || 'c:\\')
: vscode.Uri.file(os.homedir() || '/')),
name: nickname,
shellPath: getShellPath(terminalIsWindows),
shellArgs,
hideFromUser: true
};
let terminalDataHandlingQueue: Promise<void> = Promise.resolve();
terminalListener = systemInteractor.onDidWriteTerminalData(async e => {
if (e.terminal !== terminal) {
return;
}
terminalDataHandlingQueue = terminalDataHandlingQueue.finally(() => handleTerminalOutput(e));
});
terminal = systemInteractor.createTerminal(options);
if (args.revealTerminal) {
disposables.push(
args.revealTerminal(() => {
if (terminal) {
terminal.show();
}
})
);
}
if (args.sendText) {
const sendText: string = terminalIsWindows ? `(${args.sendText})\nexit /b %ErrorLevel%` : `${args.sendText}\nexit $?`;
terminal.sendText(sendText);
getOutputChannelLogger().appendLine(localize('ssh.wrote.data.to.terminal', '"{0}" wrote data to terminal: "{1}".', nickname, args.sendText));
}
if (args.showLoginTerminal) {
terminal.show();
}
windowListener = systemInteractor.onDidCloseTerminal(t => {
if (t === terminal) {
terminal = undefined; // Is already disposed
done(false, false, t.exitStatus?.code);
}
});
} catch (error) {
failed(error);
}
});
}
function getShellPath(_isWindows: boolean): string {
if (_isWindows) {
// Some users don't have cmd.exe on the path...
if (process.env.SystemRoot) {
// This var should always exist but be paranoid
const cmdPath: string = path.join(process.env.SystemRoot, 'System32', 'cmd.exe');
return cmdPath;
} else {
return 'cmd.exe';
}
} else {
// Note - can't rely on having sh in path (#590), and can't check the disk (bc remote terminals)
return '/bin/sh';
}
}
function logReceivedData(data: string, nickname: string): void {
const logData: string = data.replace(/\r?\n$/, ''); // Trim single trailing newline for nicer log
if (logData === ' ') {
// From the sleep command that must periodically echo ' '
return;
}
const markedLines: string = logData
.split(/\n/)
.map(line => `${nickname}> ${line}`)
.join('\n');
getOutputChannelLogger().appendLine(markedLines);
}
function lastNonemptyLine(str: string): string | undefined {
const lines: string[] = splitLines(str);
if (isWindows()) {
let outputContainingPipeError: string = '';
for (let i: number = lines.length - 1; i >= 0; i--) {
const strippedLine: string = stripEscapeSequences(lines[i]);
if (strippedLine.match(/The process tried to write to a nonexistent pipe/)) {
outputContainingPipeError = strippedLine;
continue;
}
if (!!strippedLine) {
return strippedLine;
}
}
if (outputContainingPipeError) {
return outputContainingPipeError;
}
}
const nonEmptyLines: string[] = lines.filter(l => !!l);
return nonEmptyLines[nonEmptyLines.length - 1];
}
+115 -89
View File
@@ -17,11 +17,10 @@ import * as assert from 'assert';
import * as https from 'https';
import * as tmp from 'tmp';
import { ClientRequest, OutgoingHttpHeaders } from 'http';
import { lookupString } from './nativeStrings';
import * as nls from 'vscode-nls';
import { Readable } from 'stream';
import * as jsonc from 'comment-json';
import { TargetPopulation } from 'vscode-tas-client';
import { CppSettings } from './LanguageServer/settings';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
@@ -321,10 +320,13 @@ export function resolveCachePath(input: string | undefined, additionalEnvironmen
return resolvedPath;
}
export function isWindows(): boolean {
return os.platform() === 'win32';
}
export function defaultExePath(): string {
const isWindows: boolean = os.platform() === 'win32';
const exePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}');
return isWindows ? exePath + '.exe' : exePath;
return isWindows() ? exePath + '.exe' : exePath;
}
export function findExePathInArgs(args: string[]): string | undefined {
@@ -570,9 +572,9 @@ export function checkDirectoryExistsSync(dirPath: string): boolean {
}
/** Test whether a relative path exists */
export function checkPathExistsSync(path: string, relativePath: string, isWindows: boolean, isWSL: boolean, isCompilerPath: boolean): { pathExists: boolean; path: string } {
export function checkPathExistsSync(path: string, relativePath: string, _isWindows: boolean, isWSL: boolean, isCompilerPath: boolean): { pathExists: boolean; path: string } {
let pathExists: boolean = true;
const existsWithExeAdded: (path: string) => boolean = (path: string) => isCompilerPath && isWindows && !isWSL && fs.existsSync(path + ".exe");
const existsWithExeAdded: (path: string) => boolean = (path: string) => isCompilerPath && _isWindows && !isWSL && fs.existsSync(path + ".exe");
if (!fs.existsSync(path)) {
if (existsWithExeAdded(path)) {
path += ".exe";
@@ -711,32 +713,83 @@ export function execChildProcess(process: string, workingDirectory?: string, cha
});
}
export function spawnChildProcess(process: string, args: string[], workingDirectory: string,
dataCallback: (stdout: string) => void, errorCallback: (stderr: string) => void): Promise<void> {
export interface ProcessReturnType {
succeeded: boolean;
exitCode?: number | NodeJS.Signals;
output: string;
}
return new Promise<void>(function (resolve, reject): void {
const child: child_process.ChildProcess = child_process.spawn(process, args, { cwd: workingDirectory });
export async function spawnChildProcess(program: string, args: string[] = [], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
const programOutput: ProcessOutput = await spawnChildProcessImpl(program, args, continueOn, cancellationToken);
const exitCode: number | NodeJS.Signals | undefined = programOutput.exitCode;
const settings: CppSettings = new CppSettings();
if (settings.loggingLevel === "Information" || settings.loggingLevel === "Debug") {
getOutputChannelLogger().appendLine(`$ ${program} ${args.join(' ')}\n${programOutput.stderr || programOutput.stdout}\n`);
}
if (programOutput.exitCode) {
return { succeeded: false, exitCode, output: programOutput.stderr || programOutput.stdout || localize('process.exited', 'Process exited with code {0}', exitCode) };
} else {
let stdout: string;
if (programOutput.stdout.length) {
// Type system doesn't work very well here, so we need call toString
stdout = programOutput.stdout;
} else {
stdout = localize('process.succeeded', 'Process executed successfully.');
}
return { succeeded: true, exitCode, output: stdout };
}
}
const stdout: Readable | null = child.stdout;
if (stdout) {
stdout.on('data', (data) => {
dataCallback(`${data}`);
});
interface ProcessOutput {
exitCode?: number | NodeJS.Signals;
stdout: string;
stderr: string;
}
async function spawnChildProcessImpl(program: string, args: string[], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessOutput> {
return new Promise(async (resolve, reject) => {
let proc: child_process.ChildProcess;
if (await isExecutable(program)) {
proc = child_process.spawn(`.${isWindows() ? '\\' : '/'}${path.basename(program)}`, args, { shell: true, cwd: path.dirname(program) });
} else {
proc = child_process.spawn(program, args, { shell: true });
}
const stderr: Readable | null = child.stderr;
if (stderr) {
stderr.on('data', (data) => {
errorCallback(`${data}`);
});
}
const cancellationTokenListener: vscode.Disposable | undefined = cancellationToken?.onCancellationRequested(() => {
getOutputChannelLogger().appendLine(localize('killing.process', 'Killing process {0}', program));
proc.kill();
});
child.on('exit', (code: number) => {
if (code !== 0) {
reject(new Error(localize("process.exited.with.code", "{0} exited with error code {1}", process, code)));
} else {
resolve();
const clean = () => {
proc.removeAllListeners();
if (cancellationTokenListener) {
cancellationTokenListener.dispose();
}
};
let stdout: string = '';
let stderr: string = '';
if (proc.stdout) {
proc.stdout.on('data', data => {
stdout += data.toString();
if (continueOn) {
const continueOnReg: string = escapeStringForRegex(continueOn);
if (stdout.search(continueOnReg)) {
resolve({ stdout: stdout.trim(), stderr: stderr.trim() });
}
}
});
}
if (proc.stderr) {
proc.stderr.on('data', data => stderr += data.toString());
}
proc.on('close', (code, signal) => {
clean();
resolve({ exitCode: code || signal, stdout: stdout.trim(), stderr: stderr.trim() });
});
proc.on('error', error => {
clean();
reject(error);
});
});
}
@@ -927,7 +980,6 @@ function resolveWindowsEnvironmentVariables(str: string): string {
}
function legacyExtractArgs(argsString: string): string[] {
const isWindows: boolean = os.platform() === 'win32';
const result: string[] = [];
let currentArg: string = "";
let isWithinDoubleQuote: boolean = false;
@@ -951,7 +1003,7 @@ function legacyExtractArgs(argsString: string): string[] {
}
} else if (c === '\'') {
// On Windows, a single quote string is not allowed to join multiple args into a single arg
if (!isWindows) {
if (!isWindows()) {
if (!isWithinDoubleQuote) {
isWithinSingleQuote = !isWithinSingleQuote;
}
@@ -1197,67 +1249,6 @@ export class BlockingTask<T> {
}
}
interface VSCodeNlsConfig {
locale: string;
availableLanguages: {
[pack: string]: string;
};
}
export function getLocaleId(): string {
// This replicates the language detection used by initializeSettings() in vscode-nls
if (isString(process.env.VSCODE_NLS_CONFIG)) {
const vscodeOptions: VSCodeNlsConfig = JSON.parse(process.env.VSCODE_NLS_CONFIG) as VSCodeNlsConfig;
if (vscodeOptions.availableLanguages) {
const value: any = vscodeOptions.availableLanguages['*'];
if (isString(value)) {
return value;
}
}
if (isString(vscodeOptions.locale)) {
return vscodeOptions.locale.toLowerCase();
}
}
return "en";
}
export function getLocalizedHtmlPath(originalPath: string): string {
const locale: string = getLocaleId();
if (!locale.startsWith("en")) {
const localizedFilePath: string = getExtensionFilePath(path.join("dist/html/", locale, originalPath));
if (fs.existsSync(localizedFilePath)) {
return localizedFilePath;
}
}
return getExtensionFilePath(originalPath);
}
export interface LocalizeStringParams {
text: string;
stringId: number;
stringArgs: string[];
indentSpaces: number;
}
export function getLocalizedString(params: LocalizeStringParams): string {
let indent: string = "";
if (params.indentSpaces) {
indent = " ".repeat(params.indentSpaces);
}
let text: string = params.text;
if (params.stringId !== 0) {
text = lookupString(params.stringId, params.stringArgs);
}
return indent + text;
}
export function getLocalizedSymbolScope(scope: string, detail: string): string {
return localize({
key: "c.cpp.symbolscope.separator", comment:
["{0} is an untranslated C++ keyword (e.g. \"private\") and {1} is either another keyword (e.g. \"typedef\") or a localized property (e.g. a localized version of \"declaration\""]
}, "{0}, {1}", scope, detail);
}
function decodeUCS16(input: string): number[] {
const output: number[] = [];
let counter: number = 0;
@@ -1471,3 +1462,38 @@ export function isVsCodeInsiders(): boolean {
extensionPath.includes(".vscode-server-exploration");
}
export function stripEscapeSequences(str: string): string {
return str
.replace(/\x1b\[\??[0-9]{0,3}(;[0-9]{1,3})?[a-zA-Z]/g, '')
.replace(/\u0008/g, '')
.replace(/\r/g, '');
}
export function splitLines(data: string): string[] {
return data.split(/\r?\n/g);
}
export function escapeStringForRegex(str: string): string {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
}
export function replaceAll(str: string, searchValue: string, replaceValue: string): string {
const pattern: string = escapeStringForRegex(searchValue);
const re: RegExp = new RegExp(pattern, 'g');
return str.replace(re, replaceValue);
}
export interface ISshHostInfo {
hostName: string;
user?: string;
port?: number | string;
}
export interface ISshLocalForwardInfo {
bindAddress?: string;
port?: number | string;
host?: string;
hostPort?: number | string;
localSocket?: string;
remoteSocket?: string;
}
+133
View File
@@ -0,0 +1,133 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { isString, replaceAll } from './common';
import { getOutputChannelLogger } from './logger';
/**
* Support ExpansionVars (${var}), env (${env:var}), and optionally VS CODE commands (${command:commandID}).
* Supported format follows https://code.visualstudio.com/docs/editor/variables-reference
* Expand options and functions are mofidifed from https://github.com/microsoft/vscode-cmake-tools/blob/main/src/expand.ts
*/
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
export interface ExpansionVars {
[key: string]: string;
workspaceFolder: string;
workspaceFolderBasename: string;
}
export interface ExpansionOptions {
vars: ExpansionVars;
doNotSupportCommands?: boolean;
recursive?: boolean;
}
export async function expandAllStrings(obj: any, options: ExpansionOptions): Promise<void> {
if (Array.isArray(obj) || (obj !== null && typeof obj === 'object')) {
for (const key of Object.keys(obj)) {
if (isString(obj[key])) {
obj[key] = await expandString(obj[key], options);
} else {
await expandAllStrings(obj[key], options);
}
}
}
}
export async function expandString(input: string, options: ExpansionOptions): Promise<string> {
const MAX_RECURSION: number = 10;
let result: string = input;
let didReplacement: boolean = false;
let i: number = 0;
do {
// TODO: consider a full circular reference check?
[result, didReplacement] = await expandStringImpl(result, options);
i++;
} while (i < MAX_RECURSION && options.recursive && didReplacement);
if (i === MAX_RECURSION && didReplacement) {
getOutputChannelLogger().showErrorMessage(localize('max.recursion.reached', 'Reached max string expansion recursion. Possible circular reference.'));
}
return replaceAll(result, '${dollar}', '$');
}
/** Returns [expandedString, didReplacement] */
async function expandStringImpl(input: string, options: ExpansionOptions): Promise<[string, boolean]> {
if (!input) {
return [input, false];
}
// We accumulate a list of substitutions that we need to make, preventing
// recursively expanding or looping forever on bad replacements
const subs: Map<string, string> = new Map<string, string>();
const var_re: RegExp = /\$\{(\w+)\}/g;
let match: RegExpMatchArray | null = null;
while ((match = var_re.exec(input))) {
const full: string = match[0];
const key: string = match[1];
if (key !== 'dollar') {
// Replace dollar sign at the very end of the expanding process
const repl: string = options.vars[key];
if (!repl) {
getOutputChannelLogger().showWarningMessage(localize('invalid.var.reference', 'Invalid variable reference {0} in string: {1}.', full, input));
} else {
subs.set(full, repl);
}
}
}
// Regular expression for variable value (between the variable suffix and the next ending curly bracket):
// .+? matches any character (except line terminators) between one and unlimited times,
// as few times as possible, expanding as needed (lazy)
const varValueRegexp: string = ".+?";
const env_re: RegExp = RegExp(`\\$\\{env:(${varValueRegexp})\\}`, "g");
while ((match = env_re.exec(input))) {
const full: string = match[0];
const varname: string = match[1];
if (process.env[varname] === undefined) {
getOutputChannelLogger().showWarningMessage(localize('env.var.not.found', 'Environment variable {0} not found', varname));
}
const repl: string = process.env[varname] || '';
subs.set(full, repl);
}
const command_re: RegExp = RegExp(`\\$\\{command:(${varValueRegexp})\\}`, "g");
while ((match = command_re.exec(input))) {
if (options.doNotSupportCommands) {
getOutputChannelLogger().showWarningMessage(localize('commands.not.supported', 'Commands are not supported for string: {0}.', input));
break;
}
const full: string = match[0];
const command: string = match[1];
if (subs.has(full)) {
continue; // Don't execute commands more than once per string
}
try {
const command_ret: unknown = await vscode.commands.executeCommand(command, options.vars.workspaceFolder);
subs.set(full, `${command_ret}`);
} catch (e: any) {
getOutputChannelLogger().showWarningMessage(localize('exception.executing.command', 'Exception while executing command {0} for string: {1} {2}.', command, input, e));
}
}
let result: string = input;
let didReplacement: boolean = false;
subs.forEach((value, key) => {
if (value !== key) {
result = replaceAll(result, key, value);
didReplacement = true;
}
});
return [result, didReplacement];
}
+76 -1
View File
@@ -8,6 +8,11 @@ import * as vscode from 'vscode';
import * as os from 'os';
import { CppSettings } from './LanguageServer/settings';
import { CppSourceStr } from './LanguageServer/extension';
import * as nls from 'vscode-nls';
import { getLocalizedString, LocalizeStringParams } from './LanguageServer/localization';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
// This is used for testing purposes
let Subscriber: (message: string) => void;
@@ -67,7 +72,10 @@ export class Logger {
}
}
let outputChannel: vscode.OutputChannel | undefined;
export let outputChannel: vscode.OutputChannel | undefined;
export let diagnosticsChannel: vscode.OutputChannel | undefined;
export let debugChannel: vscode.OutputChannel | undefined;
export let warningChannel: vscode.OutputChannel | undefined;
export function getOutputChannel(): vscode.OutputChannel {
if (!outputChannel) {
@@ -81,6 +89,13 @@ export function getOutputChannel(): vscode.OutputChannel {
return outputChannel;
}
export function getDiagnosticsChannel(): vscode.OutputChannel {
if (!diagnosticsChannel) {
diagnosticsChannel = vscode.window.createOutputChannel(localize("c.cpp.diagnostics", "C/C++ Diagnostics"));
}
return diagnosticsChannel;
}
export function showOutputChannel(): void {
getOutputChannel().show();
}
@@ -93,3 +108,63 @@ export function getOutputChannelLogger(): Logger {
}
return outputChannelLogger;
}
export function log(output: string): void {
if (!outputChannel) {
outputChannel = getOutputChannel();
}
outputChannel.appendLine(`${output}`);
}
export interface DebugProtocolParams {
jsonrpc: string;
method: string;
params?: any;
}
export function logDebugProtocol(output: DebugProtocolParams): void {
if (!debugChannel) {
debugChannel = vscode.window.createOutputChannel(`${localize("c.cpp.debug.protocol", "C/C++ Debug Protocol")}`);
}
debugChannel.appendLine("");
debugChannel.appendLine("************************************************************************************************************************");
debugChannel.append(`${output}`);
}
export interface ShowWarningParams {
localizeStringParams: LocalizeStringParams;
}
export function showWarning(params: ShowWarningParams): void {
const message: string = getLocalizedString(params.localizeStringParams);
let showChannel: boolean = false;
if (!warningChannel) {
warningChannel = vscode.window.createOutputChannel(`${localize("c.cpp.warnings", "C/C++ Configuration Warnings")}`);
showChannel = true;
}
// Append before showing the channel, to avoid a delay.
warningChannel.appendLine(`[${new Date().toLocaleString()}] ${message}`);
if (showChannel) {
warningChannel.show(true);
}
}
export function logLocalized(params: LocalizeStringParams): void {
const output: string = getLocalizedString(params);
log(output);
}
export function disposeOutputChannels(): void {
if (outputChannel) {
outputChannel.dispose();
}
if (diagnosticsChannel) {
diagnosticsChannel.dispose();
}
if (debugChannel) {
debugChannel.dispose();
}
if (warningChannel) {
warningChannel.dispose();
}
}
+13 -5
View File
@@ -21,6 +21,8 @@ import { TargetPopulation } from 'vscode-tas-client';
import * as semver from 'semver';
import * as nls from 'vscode-nls';
import { cppBuildTaskProvider, CppBuildTaskProvider } from './LanguageServer/cppBuildTaskProvider';
import { getLocaleId, getLocalizedHtmlPath } from './LanguageServer/localization';
import { disposeOutputChannels, log } from './logger';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
@@ -40,7 +42,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo
public async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
console.assert(uri.path[0] === '/', "A preceeding slash is expected on schema uri path");
const fileName: string = uri.path.substring(1);
const locale: string = util.getLocaleId();
const locale: string = getLocaleId();
let localizedFilePath: string = util.getExtensionFilePath(path.join("dist/schema/", locale, fileName));
const fileExists: boolean = await util.checkFileExists(localizedFilePath);
if (!fileExists) {
@@ -79,7 +81,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo
// Read the setting and determine whether we should activate the language server prior to installing callbacks,
// to ensure there is no potential race condition. LanguageServer.activate() is called near the end of this
// function, to allow any further setup to occur here, prior to activation.
const shouldActivateLanguageServer: boolean = (settings.intelliSenseEngine !== "Disabled" && !isOldMacOs);
const isIntelliSenseEngineDisabled: boolean = settings.intelliSenseEngine === "Disabled";
const shouldActivateLanguageServer: boolean = (!isIntelliSenseEngineDisabled && !isOldMacOs);
if (isOldMacOs) {
languageServiceDisabled = true;
@@ -134,19 +137,24 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo
if (shouldActivateLanguageServer) {
await LanguageServer.activate();
} else if (isIntelliSenseEngineDisabled) {
// The check here for isIntelliSenseEngineDisabled avoids logging
// the message on old Macs that we've already displayed a warning for.
log(localize("intellisense.disabled", "intelliSenseEngine is Disabled"));
}
return cppTools;
}
export function deactivate(): Thenable<void> {
export async function deactivate(): Promise<void> {
DebuggerExtension.dispose();
Telemetry.deactivate();
disposables.forEach(d => d.dispose());
if (languageServiceDisabled) {
return Promise.resolve();
}
return LanguageServer.deactivate();
await LanguageServer.deactivate();
disposeOutputChannels();
}
async function makeBinariesExecutable(): Promise<void> {
@@ -322,7 +330,7 @@ async function checkVsixCompatibility(): Promise<void> {
if (promise) {
promise.then(async (value) => {
if (value === moreInfoButton) {
await vscode.commands.executeCommand("markdown.showPreview", vscode.Uri.file(util.getLocalizedHtmlPath("Reinstalling the Extension.md")));
await vscode.commands.executeCommand("markdown.showPreview", vscode.Uri.file(getLocalizedHtmlPath("Reinstalling the Extension.md")));
} else if (value === ignoreButton) {
ignoreMismatchedCompatibleVsix.Value = true;
}
+3 -3
View File
@@ -4,7 +4,7 @@
* ------------------------------------------------------------------------------------------ */
'use strict';
import TelemetryReporter from 'vscode-extension-telemetry';
import TelemetryReporter from '@vscode/extension-telemetry';
import { getExperimentationServiceAsync, IExperimentationService, IExperimentationTelemetry, TargetPopulation } from 'vscode-tas-client';
import * as util from './common';
@@ -89,11 +89,11 @@ export async function deactivate(): Promise<void> {
}
}
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }): void {
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }, metrics?: { [key: string]: number }): void {
const sendTelemetry = () => {
if (experimentationTelemetry) {
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
experimentationTelemetry.sendTelemetryEvent(eventNamePrefix + eventName, properties);
experimentationTelemetry.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics);
}
};
+2 -1
View File
@@ -14,6 +14,7 @@
"include": [
"test/**/*.ts",
"tools/**/*.ts",
"ui/**/*.ts"
"ui/**/*.ts",
"./vscode*.d.ts"
]
}
+46
View File
@@ -0,0 +1,46 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as assert from "assert";
import { ExpansionOptions, expandAllStrings, expandString } from "../../src/expand";
suite('Var expansion validation', () => {
test('Expand all strings', async () => {
const input: object = {
in1: "${test2}",
in2: "${test4}",
in3: [
"${test3}",
{
in4: "${test3}"
}
]
};
const variables: object = {
test1: "t1",
test2: "${dollar}{${test1}}",
test3: "test${test2}test:${env:envtest}:${dollar}test",
test4: "${test4}"
};
const expansionOptions: ExpansionOptions = {
vars: {
workspaceFolder: '{workspaceFolder}',
workspaceFolderBasename: '{workspaceFolderBasename}',
...variables
},
recursive: true
};
await expandAllStrings(input, expansionOptions);
assert.deepStrictEqual(input, {
in1: "${t1}",
in2: "${test4}",
in3: [
"test${t1}test::$test",
{
in4: "test${t1}test::$test"
}
]
});
});
});
+8 -7
View File
@@ -53,7 +53,7 @@ function updateDefaults(object: any, defaults: any): any {
}
function refReplace(definitions: any, ref: any): any {
// $ref is formatted as "#/definitions/ObjectName"
// $ref is formatted as "#/definitions/ObjectName"
const referenceStringArray: string[] = ref['$ref'].split('/');
// Getting "ObjectName"
@@ -82,11 +82,7 @@ function replaceReferences(definitions: any, objects: any): any {
// Handle 'anyOf' with references
if (objects[key].hasOwnProperty('anyOf')) {
for (const index in objects[key].anyOf) {
if (objects[key].anyOf[index].hasOwnProperty('$ref')) {
objects[key].anyOf[index] = refReplace(definitions, objects[key].anyOf[index]);
}
}
objects[key].anyOf = replaceReferences(definitions, objects[key].anyOf);
}
// Recursively replace references if this object has properties.
@@ -95,10 +91,15 @@ function replaceReferences(definitions: any, objects: any): any {
objects[key].properties = updateDefaults(objects[key].properties, objects[key].default);
}
// Recursively replace references if the array has objects in items.
// Items in array contains ref
if (objects[key].hasOwnProperty('type') && objects[key].type === "array" && objects[key].items !== null && objects[key].items.hasOwnProperty('$ref')) {
objects[key].items = refReplace(definitions, objects[key].items);
}
// Recursively replace references if the array has objects that contains ref in items.
if (objects[key].hasOwnProperty('type') && objects[key].type === "array" && objects[key].items !== null) {
objects[key].items = replaceReferences(definitions, objects[key].items);
}
}
return objects;
+321 -2
View File
@@ -193,6 +193,313 @@
}
}
},
"Variables": {
"type": "object",
"description": "%c_cpp.debuggers.variables.description%",
"default": {
"<variable-name>": "<variable-value>"
},
"properties": {},
"additionalProperties": {
"type": "string",
"description": "%c_cpp.debuggers.variables.properties.description%",
"default": ""
}
},
"VsCodeCommand": {
"type": "object",
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
"default": {},
"required": [
"type",
"command"
],
"properties": {
"type": {
"type": "string",
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
"default": "",
"enum": [
"command"
]
},
"command": {
"type": "string",
"description": "%c_cpp.debuggers.vsCodeCommand.command.description%",
"default": ""
},
"args": {
"type": "array",
"description": "%c_cpp.debuggers.vsCodeCommand.args.description%",
"items": {
"type": "string"
}
}
}
},
"Host": {
"type": "object",
"description": "%c_cpp.debuggers.host.description%",
"default": {},
"required": [
"hostName"
],
"properties": {
"user": {
"type": "string",
"description": "%c_cpp.debuggers.host.user.description%",
"default": ""
},
"hostName": {
"type": "string",
"description": "%c_cpp.debuggers.host.hostName.description%",
"default": ""
},
"port": {
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"pattern": "^\\d+$|^\\${.+}$"
}
],
"description": "%c_cpp.debuggers.host.port.description%",
"default": 22
},
"jumpHosts": {
"type": "array",
"description": "%c_cpp.debuggers.host.jumpHost.description%",
"items": {
"type": "object",
"default": {},
"required": [
"hostName"
],
"properties": {
"user": {
"type": "string",
"description": "%c_cpp.debuggers.host.user.description%",
"default": ""
},
"hostName": {
"type": "string",
"description": "%c_cpp.debuggers.host.hostName.description%",
"default": ""
},
"port": {
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"pattern": "^\\d+$|^\\${.+}$"
}
],
"description": "%c_cpp.debuggers.host.port.description%",
"default": 22
}
}
}
},
"localForwards": {
"type": "array",
"description": "%c_cpp.debuggers.host.localForward.description%",
"items": {
"type": "object",
"default": {},
"properties": {
"bindAddress": {
"type": "string",
"description": "%c_cpp.debuggers.host.localForward.bindAddress.description%",
"default": ""
},
"port": {
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"pattern": "^\\d+$|^\\${.+}$"
}
],
"description": "%c_cpp.debuggers.host.localForward.port.description%"
},
"host": {
"type": "string",
"description": "%c_cpp.debuggers.host.localForward.host.description%",
"default": ""
},
"hostPort": {
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"pattern": "^\\d+$|^\\${.+}$"
}
],
"description": "%c_cpp.debuggers.host.localForward.hostPort.description%"
},
"localSocket": {
"type": "string",
"description": "%c_cpp.debuggers.host.localForward.localSocket.description%",
"default": ""
},
"remoteSocket": {
"type": "string",
"description": "%c_cpp.debuggers.host.localForward.remoteSocket.description%",
"default": ""
}
}
}
}
}
},
"DeploySteps": {
"type": "array",
"description": "%c_cpp.debuggers.deploySteps.description%",
"items": {
"anyOf": [
{
"type": "object",
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
"default": {},
"required": [
"type",
"files",
"host",
"targetDir"
],
"properties": {
"type": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
"default": "",
"enum": [
"scp"
]
},
"files": {
"anyOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"description": "%c_cpp.debuggers.deploySteps.scp.files.description%",
"default": ""
},
"host": {
"$ref": "#/definitions/Host"
},
"targetDir": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.scp.targetDir.description%",
"default": ""
},
"scpPath": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.scp.scpPath.description%",
"default": ""
},
"debug": {
"type": "boolean",
"description": "%c_cpp.debuggers.deploySteps.debug%"
}
}
},
{
"type": "object",
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
"default": {},
"required": [
"type",
"host",
"command"
],
"properties": {
"type": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
"default": "",
"enum": [
"ssh"
]
},
"host": {
"$ref": "#/definitions/Host"
},
"command": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.ssh.command.description%",
"default": ""
},
"sshPath": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.ssh.sshPath.description%",
"default": ""
},
"continueOn": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
"default": ""
},
"debug": {
"type": "boolean",
"description": "%c_cpp.debuggers.deploySteps.debug%"
}
}
},
{
"type": "object",
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
"default": {},
"required": [
"type",
"command"
],
"properties": {
"type": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
"default": "",
"enum": [
"shell"
]
},
"command": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.shell.command.description%",
"default": ""
},
"continueOn": {
"type": "string",
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
"default": ""
},
"debug": {
"type": "boolean",
"description": "%c_cpp.debuggers.deploySteps.debug%"
}
}
},
{
"$ref": "#/definitions/VsCodeCommand"
}
]
},
"default": []
},
"CppdbgLaunchOptions": {
"type": "object",
"required": [
@@ -253,8 +560,8 @@
},
"launchCompleteCommand": {
"enum": [
"exec-run",
"exec-continue",
"exec-run",
"exec-continue",
"None"
],
"description": "%c_cpp.debuggers.launchCompleteCommand.description%",
@@ -399,6 +706,12 @@
"$ref": "#/definitions/HardwareBreakpoints",
"description": "%c_cpp.debuggers.hardwareBreakpoints.description%",
"default": {}
},
"variables": {
"$ref": "#/definitions/Variables"
},
"deploySteps": {
"$ref": "#/definitions/DeploySteps"
}
}
},
@@ -513,6 +826,12 @@
"symbolLoadInfo": {
"$ref": "#/definitions/SymbolLoadInfo",
"description": "%c_cpp.debuggers.symbolLoadInfo.description%"
},
"variables": {
"$ref": "#/definitions/Variables"
},
"deploySteps": {
"$ref": "#/definitions/DeploySteps"
}
}
},
+1 -1
View File
@@ -15,7 +15,7 @@
},
"include": [
"src/**/*.ts",
"./node_modules/vscode/vscode.d.ts",
"./vscode*.d.ts",
"./node_modules/vscode/lib/*"
]
}
+122 -41
View File
@@ -44,14 +44,14 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz#8f03a22a04de437254e8ce8cc84ba39689288752"
integrity sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==
"@es-joy/jsdoccomment@0.10.8":
version "0.10.8"
resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.10.8.tgz#b3152887e25246410ed4ea569a55926ec13b2b05"
integrity sha512-3P1JiGL4xaR9PoTKUHa2N/LKwa2/eUdRqGwijMWWgBqbFEqJUVpmaOi2TcjcemrsRMgFLBzQCK4ToPhrSVDiFQ==
"@es-joy/jsdoccomment@~0.31.0":
version "0.31.0"
resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.31.0.tgz#dbc342cc38eb6878c12727985e693eaef34302bc"
integrity sha512-tc1/iuQcnaiSIUVad72PBierDFpsxdUHtEF/OrfqvM1CBAsIoMP51j52jTMb3dXriwhieTo289InzZj72jL3EQ==
dependencies:
comment-parser "1.2.4"
comment-parser "1.3.1"
esquery "^1.4.0"
jsdoc-type-pratt-parser "1.1.1"
jsdoc-type-pratt-parser "~3.1.0"
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
@@ -101,6 +101,42 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@microsoft/[email protected]", "@microsoft/1ds-core-js@^3.2.3":
version "3.2.3"
resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.3.tgz#2217d92ec8b073caa4577a13f40ea3a5c4c4d4e7"
integrity sha512-796A8fd90oUKDRO7UXUT9BwZ3G+a9XzJj5v012FcCN/2qRhEsIV3x/0wkx2S08T4FiQEUPkB2uoYHpEjEneM7g==
dependencies:
"@microsoft/applicationinsights-core-js" "2.8.4"
"@microsoft/applicationinsights-shims" "^2.0.1"
"@microsoft/dynamicproto-js" "^1.1.6"
"@microsoft/1ds-post-js@^3.2.3":
version "3.2.3"
resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.3.tgz#1fa7d51615a44f289632ae8c588007ba943db216"
integrity sha512-tcGJQXXr2LYoBbIXPoUVe1KCF3OtBsuKDFL7BXfmNtuSGtWF0yejm6H83DrR8/cUIGMRMUP9lqNlqFGwDYiwAQ==
dependencies:
"@microsoft/1ds-core-js" "3.2.3"
"@microsoft/applicationinsights-shims" "^2.0.1"
"@microsoft/dynamicproto-js" "^1.1.6"
"@microsoft/[email protected]":
version "2.8.4"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.4.tgz#607e531bb241a8920d43960f68a7c76a6f9af596"
integrity sha512-FoA0FNOsFbJnLyTyQlYs6+HR7HMEa6nAOE6WOm9WVejBHMHQ/Bdb+hfVFi6slxwCimr/ner90jchi4/sIYdnyQ==
dependencies:
"@microsoft/applicationinsights-shims" "2.0.1"
"@microsoft/dynamicproto-js" "^1.1.6"
"@microsoft/[email protected]", "@microsoft/applicationinsights-shims@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.1.tgz#5d72fb7aaf4056c4fda54f9d7c93ccf8ca9bcbfd"
integrity sha512-G0MXf6R6HndRbDy9BbEj0zrLeuhwt2nsXk2zKtF0TnYo39KgYqhYC2ayIzKPTm2KAE+xzD7rgyLdZnrcRvt9WQ==
"@microsoft/dynamicproto-js@^1.1.6":
version "1.1.6"
resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.6.tgz#6fe03468862861f5f88ac4c3959a652b3797f1bc"
integrity sha512-D1Oivw1A4bIXhzBIy3/BBPn3p2On+kpO2NiYt9shICDK7L/w+cR6FFBUsBZ05l6iqzTeL+Jm8lAYn0g6G7DmDg==
"@nodelib/[email protected]":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
@@ -254,6 +290,14 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
"@types/glob@^7.1.3":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==
dependencies:
"@types/minimatch" "*"
"@types/node" "*"
"@types/json-schema@*", "@types/json-schema@^7.0.6":
version "7.0.7"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
@@ -269,6 +313,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/minimatch@*":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
"@types/minimatch@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -316,11 +365,6 @@
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd"
integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA==
"@types/[email protected]":
version "1.60.0"
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.60.0.tgz#9330c317691b4f53441a18b598768faeeb71618a"
integrity sha512-wZt3VTmzYrgZ0l/3QmEbCq4KAJ71K3/hmMQ/nfpv84oH8e81KKwPEoQ5v8dNCxfHFVJ1JabHKmCvqdYOoVm1Ow==
"@types/which@^1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf"
@@ -415,6 +459,14 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@vscode/extension-telemetry@^0.6.2":
version "0.6.2"
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.2.tgz#b86814ee680615730da94220c2b03ea9c3c14a8e"
integrity sha512-yb/wxLuaaCRcBAZtDCjNYSisAXz3FWsSqAha5nhHcYxx2ZPdQdWuZqVXGKq0ZpHVndBWWtK6XqtpCN2/HB4S1w==
dependencies:
"@microsoft/1ds-core-js" "^3.2.3"
"@microsoft/1ds-post-js" "^3.2.3"
"@vscode/test-electron@^1.6.1":
version "1.6.1"
resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-1.6.1.tgz#2b282154097e250ee9b94b6a284eb5804e53a3d7"
@@ -1332,10 +1384,10 @@ comment-json@^4.1.1:
has-own-prop "^2.0.0"
repeat-string "^1.6.1"
comment-parser@1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.2.4.tgz#489f3ee55dfd184a6e4bffb31baba284453cb760"
integrity sha512-pm0b+qv+CkWNriSTMsfnjChF9kH0kxz55y44Wo5le9qLxMj5xDQAaEd9ZN1ovSuk9CsrncWaFwgpOMg7ClJwkw==
comment-parser@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.3.1.tgz#3d7ea3adaf9345594aedee6563f422348f165c1b"
integrity sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==
component-emitter@^1.2.1:
version "1.3.0"
@@ -1453,7 +1505,7 @@ [email protected]:
dependencies:
ms "^2.1.1"
debug@4, debug@^4.3.2:
debug@4:
version "4.3.2"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
@@ -1488,6 +1540,13 @@ debug@^4.0.1, debug@^4.1.1:
dependencies:
ms "^2.1.1"
debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
decamelize@^1.1.1, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
@@ -1870,19 +1929,17 @@ eslint-plugin-import@^2.24.2:
resolve "^1.20.0"
tsconfig-paths "^3.11.0"
eslint-plugin-jsdoc@^36.1.0:
version "36.1.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.1.0.tgz#8dfe5f27edfb6aa3812e6d86ccaea849ddc86b03"
integrity sha512-Qpied2AJCQcScxfzTObLKRiP5QgLXjMU/ITjBagEV5p2Q/HpumD1EQtazdRYdjDSwPmXhwOl2yquwOGQ4HOJNw==
eslint-plugin-jsdoc@^39.3.3:
version "39.3.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.3.3.tgz#75dd67ce581e7527a69f27800138cc0f9c388236"
integrity sha512-K/DAjKRUNaUTf0KQhI9PvsF+Y3mGDx/j0pofXsJCQe/tmRsRweBIXR353c8nAro0lytZYEf7l0PluBpzKDiHxw==
dependencies:
"@es-joy/jsdoccomment" "0.10.8"
comment-parser "1.2.4"
debug "^4.3.2"
"@es-joy/jsdoccomment" "~0.31.0"
comment-parser "1.3.1"
debug "^4.3.4"
escape-string-regexp "^4.0.0"
esquery "^1.4.0"
jsdoc-type-pratt-parser "^1.1.1"
lodash "^4.17.21"
regextras "^0.8.0"
semver "^7.3.5"
semver "^7.3.7"
spdx-expression-parse "^3.0.1"
eslint-scope@^5.0.0:
@@ -3407,10 +3464,10 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
jsdoc-type-pratt-parser@1.1.1, jsdoc-type-pratt-parser@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.1.1.tgz#10fe5e409ba38de22a48b555598955a26ff0160f"
integrity sha512-uelRmpghNwPBuZScwgBG/OzodaFk5RbO5xaivBdsAY70icWfShwZ7PCMO0x1zSkOa8T1FzHThmrdoyg/0AwV5g==
jsdoc-type-pratt-parser@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz#a4a56bdc6e82e5865ffd9febc5b1a227ff28e67e"
integrity sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw==
json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
version "1.0.2"
@@ -3477,6 +3534,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
kleur@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
last-run@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b"
@@ -4432,6 +4494,14 @@ progress@^2.0.0:
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
prompts@^2.1.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
dependencies:
kleur "^3.0.3"
sisteransi "^1.0.5"
prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
@@ -4585,11 +4655,6 @@ regexpp@^3.1.0:
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
regextras@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.8.0.tgz#ec0f99853d4912839321172f608b544814b02217"
integrity sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ==
remove-bom-buffer@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53"
@@ -4818,6 +4883,13 @@ semver@^7.2.1, semver@^7.3.4, semver@^7.3.5:
dependencies:
lru-cache "^6.0.0"
semver@^7.3.7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
dependencies:
lru-cache "^6.0.0"
[email protected], serialize-javascript@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
@@ -4898,6 +4970,11 @@ signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@@ -5790,10 +5867,14 @@ [email protected], vscode-debugprotocol@^1.35.0:
resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.38.0.tgz#7a9bcd457e6642f48fabef114c0fa1c25a2fb1e7"
integrity sha512-oam9iSjNfXSn71a8bmNsXv8k/rIKSOcllIPrFnNgxd1EMBpfnum+gb7lmRpcH0zSjGb+OH8Ncn8B5tv8srWbNQ==
vscode-extension-telemetry@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.4.4.tgz#e5d5ac90ea7d07ec054f5310893d95d43d5984b0"
integrity sha512-LzirNf2GnykXCAqqWrvj+snYqgkPVyjwM72tYOHgcZiG/ZRuNjmqlgvs+SomEJdmD8cutduitPmhoyIuzOrVfA==
vscode-dts@^0.3.2:
version "0.3.3"
resolved "https://registry.yarnpkg.com/vscode-dts/-/vscode-dts-0.3.3.tgz#e5ef3afe76182875b252cca7f449938e4a0bf28a"
integrity sha512-JfOsWL0NvfVw0UF9bcTjlv1Onz3Ted7cgpPWKWMnHGB+72t/tn8WFDeKLZO42l2k9KJq/NGS9rFC5gZbyI4FTg==
dependencies:
minimist "^1.2.0"
prompts "^2.1.0"
rimraf "^3.0.0"
vscode-jsonrpc@^4.0.0:
version "4.0.0"
@@ -6135,4 +6216,4 @@ yauzl@^2.10.0:
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-1
View File
@@ -7,4 +7,3 @@ This extension pack includes a set of popular extensions for C++ development in
* [CMake Tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools)
* [Doxygen Documentation Generator](https://marketplace.visualstudio.com/items?itemName=cschlosser.doxdocgen)
* [Better C++ Syntax](https://marketplace.visualstudio.com/items?itemName=jeff-hykin.better-cpp-syntax)
* [Remote Development Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)