Compare commits

..
Author SHA1 Message Date
2189c2346c Merge for 1.32.0 (pre-release) (#14375)
* Update changelog and TPN. (#14298)

* Update flatted and fast-xml-parser. (#14303)

* Bump flatted from 3.4.1 to 3.4.2 in /Extension (#14304)

Bumps [flatted](https://github.com/WebReflection/flatted) from 3.4.1 to 3.4.2.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.4.1...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update changelog with recent fixes. (#14313)

* Bump picomatch from 2.3.1 to 2.3.2 in /ExtensionPack (#14318)

Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump picomatch from 2.3.1 to 2.3.2 in /.github/actions (#14319)

Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sean McManus <[email protected]>

* Bump picomatch from 2.3.1 to 2.3.2 in /Themes (#14323)

Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update picomatch. (#14324)

* Update brace-expansion v5. (#14325)

* Bump serialize-javascript from 7.0.4 to 7.0.5 in /.github/actions (#14332)

Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) from 7.0.4 to 7.0.5.
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](https://github.com/yahoo/serialize-javascript/compare/v7.0.4...v7.0.5)

---
updated-dependencies:
- dependency-name: serialize-javascript
  dependency-version: 7.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update brace-expansion and serialize-javascript. (#14328)

* minimize the calls to lm.selectChatModels (#14327)

* Update brace-expansion for other folders (#14333)

* Update brace-expansion for other folders.

* Update changelog for 1.31.4. (#14338)

* Bump @xmldom/xmldom from 0.8.11 to 0.8.12 in /Extension (#14340)

Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.11 to 0.8.12.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.11...0.8.12)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-version: 0.8.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update TPN. (#14343)

* Update npmrc. (#14346)

* Prefer GPT-5-mini for Copilot Hover (#14349)

* Update lodash. (#14350)

* Fix npx @vscode/vsce. (#14354)

* Fix npx @vscode/vsce.

* Fix cg.yml. (#14355)

* UCRTVersion is not required for a developer environment (#14358)

* Update instructions for installing MSVC (#14361)

* Bump axios from 1.13.6 to 1.15.0 in /.github/actions (#14365)

Bumps [axios](https://github.com/axios/axios) from 1.13.6 to 1.15.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.13.6...v1.15.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.15.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add setting doxygen.generateOnCodeAction. (#14342)

* Run without debugging (#14351)

* Switch to GPT-4o. (#14364)

* Fallback to GPT-5.4-mini and cache the model used. (#14369)

* Fallback to GPT-5.4-mini and cache the model used.

* Add a script to copy language server and debugger binaries to the Extension folder (#14370)

* Add internal silent find-all-references command (#14281)

* Add internal silent find-all-references command

Introduce an internal C_Cpp.FindAllReferences command that issues the existing cpptools/findAllReferences request without joining the workspaceReferences single-flight cancellation path.

Extract the shared request and confirmed-location mapping logic from FindAllReferencesProvider so the existing vscode.executeReferenceProvider flow and the new silent command use the same request translation and cancellation handling for server-side cancel responses.

Keep the interactive provider behavior unchanged: user-invoked references still cancel prior work, reset reference progress state, and update the ReferencesManager UI. The new command resolves the owning client from the target URI and returns locations without progress UI, preview notifications, or references panel updates, enabling concurrent silent callers such as Copilot.

* Add internal quiet definition and call hierarchy commands

Align cpptools with the companion changes that now prefer internal
C_Cpp.* navigation commands over the generic vscode.* provider commands
when running extension-driven symbol queries.

Add C_Cpp.GoToDefinition, C_Cpp.PrepareCallHierarchy,
C_Cpp.CallHierarchyCallsTo, and C_Cpp.CallHierarchyCallsFrom as
internal commands that resolve the owning DefaultClient from the target
URI and send requests directly to cpptools without joining the
workspaceReferences UI and single-flight cancellation path.

Extract shared call hierarchy request and conversion logic from
CallHierarchyProvider so the existing interactive provider flow and the
new silent commands share the same request translation and
server-cancellation handling.

Add a dedicated go-to-definition helper that sends the standard
definition request through the language client and normalizes both
Location and DefinitionLink responses to Location[] so companion callers
can consume a stable result shape.

Keep interactive behavior unchanged: user-invoked providers continue to
use the existing VS Code registrations, progress handling, and
workspaceReferences-driven cancellation semantics, while extension
callers such as the devtools companion can use the new internal command
surface without canceling overlapping work.

* Update changelog for 1.32.0. (#14373)

* Update changelog for 1.32.0.

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Luca <[email protected]>
Co-authored-by: Ben McMorran <[email protected]>
Co-authored-by: Bob Brown <[email protected]>
Co-authored-by: Carson Radtke <[email protected]>
2026-04-14 11:29:39 -07:00
Sean McManus 37e3936cc7 Merge branch 'main' into seanmcm/1_32_0_changelog 2026-04-14 10:57:48 -07:00
Sean McManus a6b12a8c10 Update changelog for 1.32.0. (#14373)
* Update changelog for 1.32.0.
2026-04-14 10:54:17 -07:00
Carson Radtke 775fd692ea Add internal silent find-all-references command (#14281)
* Add internal silent find-all-references command

Introduce an internal C_Cpp.FindAllReferences command that issues the existing cpptools/findAllReferences request without joining the workspaceReferences single-flight cancellation path.

Extract the shared request and confirmed-location mapping logic from FindAllReferencesProvider so the existing vscode.executeReferenceProvider flow and the new silent command use the same request translation and cancellation handling for server-side cancel responses.

Keep the interactive provider behavior unchanged: user-invoked references still cancel prior work, reset reference progress state, and update the ReferencesManager UI. The new command resolves the owning client from the target URI and returns locations without progress UI, preview notifications, or references panel updates, enabling concurrent silent callers such as Copilot.

* Add internal quiet definition and call hierarchy commands

Align cpptools with the companion changes that now prefer internal
C_Cpp.* navigation commands over the generic vscode.* provider commands
when running extension-driven symbol queries.

Add C_Cpp.GoToDefinition, C_Cpp.PrepareCallHierarchy,
C_Cpp.CallHierarchyCallsTo, and C_Cpp.CallHierarchyCallsFrom as
internal commands that resolve the owning DefaultClient from the target
URI and send requests directly to cpptools without joining the
workspaceReferences UI and single-flight cancellation path.

Extract shared call hierarchy request and conversion logic from
CallHierarchyProvider so the existing interactive provider flow and the
new silent commands share the same request translation and
server-cancellation handling.

Add a dedicated go-to-definition helper that sends the standard
definition request through the language client and normalizes both
Location and DefinitionLink responses to Location[] so companion callers
can consume a stable result shape.

Keep interactive behavior unchanged: user-invoked providers continue to
use the existing VS Code registrations, progress handling, and
workspaceReferences-driven cancellation semantics, while extension
callers such as the devtools companion can use the new internal command
surface without canceling overlapping work.
2026-04-14 04:00:46 +00:00
Bob Brown ddb54454e3 Add a script to copy language server and debugger binaries to the Extension folder (#14370) 2026-04-13 15:48:40 -07:00
Sean McManus 2db5c05c37 Fallback to GPT-5.4-mini and cache the model used. (#14369)
* Fallback to GPT-5.4-mini and cache the model used.
2026-04-13 14:50:38 -07:00
Sean McManus bc9a72cf2f Switch to GPT-4o. (#14364) 2026-04-13 13:07:02 -07:00
Bob Brown 291e5a3228 Run without debugging (#14351) 2026-04-13 19:38:30 +00:00
Sean McManus 7774dafb1f Add setting doxygen.generateOnCodeAction. (#14342) 2026-04-13 12:19:54 -07:00
dependabot[bot] 55ef430b96 Bump axios from 1.13.6 to 1.15.0 in /.github/actions (#14365)
Bumps [axios](https://github.com/axios/axios) from 1.13.6 to 1.15.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.13.6...v1.15.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.15.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 08:49:49 -07:00
Bob Brown bb5943c755 Update instructions for installing MSVC (#14361) 2026-04-09 13:37:29 -07:00
Bob Brown 69d4585eb2 UCRTVersion is not required for a developer environment (#14358) 2026-04-08 16:13:33 -07:00
Sean McManus 8e82004017 Fix cg.yml. (#14355) 2026-04-08 08:49:30 -07:00
Sean McManus 900aa75527 Fix npx @vscode/vsce. (#14354)
* Fix npx @vscode/vsce.
2026-04-07 13:03:03 -07:00
Sean McManus 61b53bcda8 Update lodash. (#14350) 2026-04-03 16:02:22 -07:00
Ben McMorran 34d375a616 Prefer GPT-5-mini for Copilot Hover (#14349) 2026-04-03 10:42:25 -07:00
Sean McManus 61815d8869 Update npmrc. (#14346) 2026-04-02 18:23:56 +00:00
Sean McManus f309f90a4f Update TPN. (#14343) 2026-04-02 11:10:56 -07:00
dependabot[bot] fa097e4966 Bump @xmldom/xmldom from 0.8.11 to 0.8.12 in /Extension (#14340)
Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.11 to 0.8.12.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.11...0.8.12)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-version: 0.8.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-01 11:09:05 -07:00
Sean McManus 6770b0a25a Update changelog for 1.31.4. (#14338) 2026-03-31 15:16:52 -07:00
Sean McManus 5f56194feb Update brace-expansion for other folders (#14333)
* Update brace-expansion for other folders.
2026-03-30 11:08:36 -07:00
Luca 21a8e34c91 minimize the calls to lm.selectChatModels (#14327) 2026-03-30 09:41:03 -08:00
Sean McManus 5451e32bd8 Update brace-expansion and serialize-javascript. (#14328) 2026-03-30 10:14:13 -07:00
dependabot[bot] 97943a9d67 Bump serialize-javascript from 7.0.4 to 7.0.5 in /.github/actions (#14332)
Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) from 7.0.4 to 7.0.5.
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](https://github.com/yahoo/serialize-javascript/compare/v7.0.4...v7.0.5)

---
updated-dependencies:
- dependency-name: serialize-javascript
  dependency-version: 7.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 10:09:26 -07:00
Sean McManus 4884af8c94 Update brace-expansion v5. (#14325) 2026-03-27 17:20:36 +00:00
Sean McManus 65beaebaf9 Update picomatch. (#14324) 2026-03-26 18:50:45 -07:00
dependabot[bot] 6e3a7b2b7e Bump picomatch from 2.3.1 to 2.3.2 in /Themes (#14323)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 17:01:33 -07:00
dependabot[bot]andSean McManus 5c16227c40 Bump picomatch from 2.3.1 to 2.3.2 in /.github/actions (#14319)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sean McManus <[email protected]>
2026-03-26 15:44:08 -07:00
dependabot[bot] 37a558260d Bump picomatch from 2.3.1 to 2.3.2 in /ExtensionPack (#14318)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 13:27:38 -07:00
Sean McManus f0d05b9cdf Merge pull request #14297 from microsoft/seanmcm/1_31_2_update_skip_duplicates
Update insiders for CFSClean3 fixes (and set the version to 1.31.2 for skip-duplicates)
2026-03-18 13:37:27 -07:00
Sean McManus 401393418f Change version to 1.31.2 to enable skip-duplicates for build verifications. 2026-03-18 13:14:03 -07:00
Sean McManus 1d239e0b31 Merge branch 'main' into seanmcm/1_31_2_update_skip_duplicates 2026-03-18 13:13:17 -07:00
Sean McManus 69485c736d Merge pull request #14283 from microsoft/main
Fix a yarn.lock mismatch. (#14282)
2026-03-16 16:17:32 -07:00
Sean McManus 5e8ca66b5f Merge pull request #14280 from microsoft/main
Merge for 1.31.2
2026-03-16 12:32:54 -07:00
Sean McManus 77effb9b85 Merge pull request #14260 from microsoft/main
Merge for 1.31.1 (3rd time)
2026-03-10 10:55:26 -07:00
Sean McManus 770ef315d5 Merge pull request #14255 from microsoft/main
Update TPN for 1.31.1. (#14254)
2026-03-09 16:50:27 -07:00
Sean McManus 4bc7ad3f6e Merge pull request #14240 from microsoft/main
Merge for 1.31.1 (pre-release)
2026-03-05 18:12:41 -08:00
Sean McManus 4a1150ebaa Merge pull request #14210 from microsoft/main
Merge to insiders -- this is to build a test vsix to confirm pipeline issues are resolved, not an actual release
2026-02-23 13:39:05 -08:00
Sean McManus 9b3b23fafa Merge pull request #14199 from microsoft/main
Merge for 1.31.0 (pre-release)
2026-02-18 18:19:31 -08:00
Sean McManus e9bf244599 Merge pull request #14147 from microsoft/main
Merge for 1.30.2 (pre-release)
2026-01-23 18:46:16 -08:00
Sean McManusandBen McMorran 3e3c93b814 Merge for 1.30.1 (pre-release) (#14134)
* Fix Copilot hover model selection (#14113)

* Update IntelliSense loc strings. (#14131)

* Update changelog for 1.30.1 (#14133)

* Update changelog for 1.30.1

---------

Co-authored-by: Ben McMorran <[email protected]>
2026-01-12 11:49:03 -08:00
Sean McManus fcaadd8ef5 Merge pull request #14107 from microsoft/main
Merge for 1.30.0 (pre-release)
2025-12-12 16:50:30 -08:00
Sean McManus 2b24151d93 Merge pull request #14059 from microsoft/main
Merge for 1.29.1 (pre-release)
2025-11-20 15:09:26 -08:00
Sean McManus e75c76070e Merge pull request #14034 from microsoft/main
Merge for 1.29.0
2025-11-03 11:30:16 -08:00
Sean McManusandBob Brown 97d3735bb2 Merge for 1.28.2 (2nd time) (#13997)
* Fix some invalid assumptions for tasks (#13989)

* Update changeling and version for 1.28.2 (#13990)

* Update changelog and version for 1.28.2.

* Remove llvm from cgmanifest. (#13994)

* Update changelog. (#13996)

---------

Co-authored-by: Bob Brown <[email protected]>
2025-10-13 14:29:28 -07:00
Sean McManus f33c3b6205 Merge pull request #13983 from microsoft/main
Update changleog (2nd time). (#13981)
2025-10-06 14:39:07 -07:00
Sean McManus 55e2ee962e Merge pull request #13978 from microsoft/main
Merge for 1.25.1 (pre-release)
2025-10-03 15:46:00 -07:00
Sean McManus 52620d638c Merge pull request #13964 from microsoft/main
Merge for 1.28.0
2025-09-24 17:13:46 -07:00
Sean McManus 31f8ee8814 Merge pull request #13935 from microsoft/main
Merge for 1.27.6
2025-09-15 16:42:11 -07:00
Sean McManus 1e19dd9f8d Merge pull request #13921 from microsoft/main
Merge for 1.27.5
2025-09-10 12:30:04 -07:00
Sean McManus 9f4077452f Merge pull request #13913 from microsoft/main
Merge for 1.27.4 (2nd time)
2025-09-09 10:23:41 -07:00
Sean McManus 17a1b3199a Merge pull request #13903 from microsoft/main
Merge for 1.27.4
2025-09-05 16:43:18 -07:00
Sean McManus 1ed7c869aa Merge pull request #13895 from microsoft/main
Merge for 1.27.3
2025-09-02 17:11:52 -07:00
Sean McManus b1ed550820 Merge pull request #13871 from microsoft/main
Fix changelog version. (#13870)
2025-08-21 16:15:22 -07:00
Sean McManus 0d6853ce6c Merge pull request #13869 from microsoft/main
Update changelog and version. (#13868)
2025-08-21 14:57:08 -07:00
Sean McManus 49aa6d7543 Merge pull request #13856 from microsoft/main
Merge for 1.27.1
2025-08-18 14:49:10 -07:00
Sean McManus 51615a38c6 Merge pull request #13833 from microsoft/main
Merge for 1.27.0 (4th time)
2025-08-06 18:51:41 -07:00
Bob Brown bcb0bc476b Merge for 1.27.0 (3rd time)
Merge for 1.27.0 (3rd time)
2025-08-04 16:43:29 -07:00
Bob Brown 59c08fba3e Merge branch 'main' into bobbrow/insiders-1.27.0.3 2025-08-04 16:37:10 -07:00
Bob Brown 7ccb51eead Merge pull request #13812 from microsoft/bobbrow/revertSquash
Revert accidental squash commit
2025-08-04 16:35:47 -07:00
Bob Brown 1f3963e9ef Revert "Merge for 1.27.0 (2nd time) (#13803)"
This reverts commit e340d858e7.
2025-08-04 16:25:04 -07:00
Colen Garoutte-Carson e340d858e7 Merge for 1.27.0 (2nd time) (#13803) 2025-08-01 16:47:49 -07:00
Sean McManus d8636d9057 Merge pull request #13759 from microsoft/main
Merge for 1.27.0 (pre-release)
2025-07-14 15:31:34 -07:00
Sean McManus f9199c761a Merge pull request #13714 from microsoft/main
Merge for 1.26.2 pre-release
2025-06-18 14:14:05 -07:00
Sean McManus eedc0a26cc Merge pull request #13631 from microsoft/main
fix typo (#13630)
2025-05-22 18:55:33 -07:00
Sean McManus ae056fd205 Merge pull request #13629 from microsoft/main
Update changelog for 1.26.1 (#13627)
2025-05-22 16:30:41 -07:00
Sean McManusandLuca 598411c6b8 add note about C++ Copilot suggestions improvement (#13624) (#13625)
Co-authored-by: Luca <[email protected]>
2025-05-21 14:01:11 -07:00
Sean McManus d14eb4ec1d Merge pull request #13623 from microsoft/main
Merge for 1.26.0
2025-05-21 12:29:13 -07:00
Sean McManus 68f7e902a5 Merge pull request #13555 from microsoft/main
Merge for 1.25.2 (2nd time)
2025-04-25 15:22:31 -07:00
Sean McManus 9cf7cda837 Merge pull request #13551 from microsoft/main
Merge for 1.25.2
2025-04-25 11:52:07 -07:00
Sean McManus 248788d4f6 Merge pull request #13542 from microsoft/main
Merge for 1.25.1
2025-04-22 09:41:05 -07:00
Sean McManus 4355f92dd8 Merge pull request #13488 from microsoft/main
Merge for 1.25.0 (2nd time)
2025-04-10 16:09:14 -07:00
Sean McManus 86332db0ed Merge pull request #13482 from microsoft/main
Merger for 1.25.0 (pre-release)
2025-04-10 08:37:52 -07:00
Sean McManus ee2fb39cb8 Merge pull request #13429 from microsoft/main
Merge for 1.24.4 (2nd time)
2025-03-26 14:20:09 -07:00
Sean McManus 7d58a314d9 Merge pull request #13419 from microsoft/main
Merge for 1.24.4
2025-03-26 11:10:08 -07:00
Colen Garoutte-Carson 2acdea1cc9 Merge pull request #13387 from microsoft/main 2025-03-18 15:14:59 -07:00
Sean McManus d24f781721 Merge pull request #13384 from microsoft/main
Merge for 1.24.3 (pre-release)
2025-03-18 13:23:26 -07:00
Colen Garoutte-Carson 399d558522 Merge pull request #13346 from microsoft/main 2025-03-06 15:21:29 -08:00
Sean McManus 0fd436f3ef Merge pull request #13280 from microsoft/main
Merge for 1.24.1
2025-02-13 15:03:59 -08:00
Sean McManus b6e18b00a9 Merge pull request #13271 from microsoft/main
Merge for 1.24.0 (2nd time)
2025-02-11 06:55:18 -08:00
Sean McManus cb3964f78e Merge pull request #13267 from microsoft/main
Fix Copilot hover reprompting. (#13266)
2025-02-10 11:51:03 -08:00
Sean McManus 50b4cd3bd5 Merge pull request #13257 from microsoft/main
Merge for 1.24.0 (2nd time)
2025-02-07 16:22:41 -08:00
Sean McManus 161f02dc49 Merge pull request #13250 from microsoft/seanmcm/1_24_0_insiders
Merge for 1.24.0
2025-02-07 13:42:21 -08:00
Sean McManus c48729b0e4 Merge branch 'main' into seanmcm/1_24_0_insiders 2025-02-06 21:18:02 -08:00
35 changed files with 1570 additions and 264 deletions
+3 -1
View File
@@ -1,2 +1,4 @@
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
always-auth=true
always-auth=true
# Disable postinstall scripts for supply chain security. Allowlist exceptions with npm trust: https://docs.npmjs.com/cli/v11/commands/npm-trust
ignore-scripts=true
+3 -3
View File
@@ -4125,9 +4125,9 @@
"license": "ISC"
},
"node_modules/follow-redirects": {
"version": "1.16.0",
"resolved": "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/follow-redirects/-/follow-redirects-1.16.0.tgz",
"integrity": "sha1-KEdKFZ07nRHvYgUKFO1g5N9tYbw=",
"version": "1.15.11",
"resolved": "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha1-d31z1yqS+OxNLkEOtHNSpWuOg0A=",
"funding": [
{
"type": "individual",
@@ -66,6 +66,11 @@ jobs:
# run: yarn test --scenario=MultirootDeadlockTest
# working-directory: Extension
# - name: Run E2E IntelliSense features tests
# if: ${{ inputs.platform == 'windows' }}
# run: yarn test --scenario=RunWithoutDebugging
# working-directory: Extension
# NOTE: For mac/linux run the tests with xvfb-action for UI support.
# Another way to start xvfb https://github.com/microsoft/vscode-test/blob/master/sample/azure-pipelines.yml
@@ -83,3 +88,10 @@ jobs:
# run: yarn test --scenario=MultirootDeadlockTest
# working-directory: Extension
# - name: Run E2E IntelliSense features tests (xvfb)
# if: ${{ inputs.platform == 'mac' || inputs.platform == 'linux' }}
# uses: coactions/setup-xvfb@v1
# with:
# run: yarn test --scenario=RunWithoutDebugging
# working-directory: Extension
+10 -4
View File
@@ -107,8 +107,14 @@ extends:
fi
retryCountOnTaskFailure: 3
- script: |
cd $(Build.SourcesDirectory)\Extension
npx @vscode/[email protected] package --yarn -o $(Build.ArtifactStagingDirectory)\Extension\cpptools.vsix
name: ProcessRunner_12
- script: yarn install --frozen-lockfile
displayName: Install dependencies with yarn
workingDirectory: $(Build.SourcesDirectory)\Extension
- script: if not exist node_modules\@vscode\vsce-sign\bin\vsce-sign.exe (echo Missing vsce-sign.exe && exit 1)
displayName: Verify vsce-sign binary exists
workingDirectory: $(Build.SourcesDirectory)\Extension
- script: npx vsce package --yarn -o $(Build.ArtifactStagingDirectory)\Extension\cpptools.vsix
displayName: Run VSCE to package vsix
workingDirectory: $(Build.SourcesDirectory)\Extension
+15 -4
View File
@@ -59,13 +59,24 @@ jobs:
- script: mkdir $(Build.ArtifactStagingDirectory)\vsix
displayName: Create Staging Directory
- script: |
cd $(Build.SourcesDirectory)\${{ parameters.srcDir }}
npx @vscode/[email protected] package -o $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.vsix
- script: npm install --no-save --ignore-scripts=false --include=optional --force @vscode/[email protected]
displayName: Install vsce
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
- script: npm rebuild @vscode/vsce-sign --ignore-scripts=false
displayName: Rebuild vsce-sign binary
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
- script: if not exist node_modules\@vscode\vsce-sign\bin\vsce-sign.exe (echo Missing vsce-sign.exe && exit 1)
displayName: Verify vsce-sign binary exists
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
- script: npx vsce package -o $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.vsix
displayName: Run VSCE to package vsix
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
# sign the vsix
- script: npx @vscode/[email protected] generate-manifest -i $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.vsix -o $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.manifest
- script: npx vsce generate-manifest -i $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.vsix -o $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.manifest
displayName: generate manifest
workingDirectory: $(Build.SourcesDirectory)\${{ parameters.srcDir }}
- script: copy $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.manifest $(Build.ArtifactStagingDirectory)\vsix\${{ parameters.vsixName }}.signature.p7s
+10 -2
View File
@@ -31,8 +31,16 @@ jobs:
$aadToken = az account get-access-token --query accessToken --resource $(AzureGuid) -o tsv
Write-Host "##vso[task.setvariable variable=AAD_TOKEN;issecret=true]$aadToken"
- script: |
npx @vscode/[email protected] publish --skip-duplicate -i $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.vsix --manifestPath $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.manifest --signaturePath $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.signature.p7s
- script: npm install --no-save --ignore-scripts=false --include=optional --force @vscode/[email protected]
displayName: Install vsce
- script: npm rebuild @vscode/vsce-sign --ignore-scripts=false
displayName: Rebuild vsce-sign binary
- script: if not exist node_modules\@vscode\vsce-sign\bin\vsce-sign.exe (echo Missing vsce-sign.exe && exit 1)
displayName: Verify vsce-sign binary exists
- script: npx vsce publish --skip-duplicate -i $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.vsix --manifestPath $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.manifest --signaturePath $(Build.StagingDirectory)\vsix\${{ parameters.vsixName }}.signature.p7s
displayName: Publish to Marketplace
env:
VSCE_PAT: $(AAD_TOKEN)
+3 -1
View File
@@ -1,2 +1,4 @@
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
always-auth=true
always-auth=true
# Disable postinstall scripts for supply chain security. Allowlist exceptions with npm trust: https://docs.npmjs.com/cli/v11/commands/npm-trust
ignore-scripts=true
+113
View File
@@ -0,0 +1,113 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { cp, readdir, rm, stat } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { $args, $root, green, heading, note } from './common';
const extensionPrefix = 'ms-vscode.cpptools-';
const foldersToCopy = ['bin', 'debugAdapters', 'LLVM'] as const;
type InstalledExtension = {
path: string;
version: number[];
modified: number;
};
function compareVersions(left: number[], right: number[]): number {
const maxLength: number = Math.max(left.length, right.length);
for (let i = 0; i < maxLength; i++) {
const diff: number = (left[i] ?? 0) - (right[i] ?? 0);
if (diff !== 0) {
return diff;
}
}
return 0;
}
function tryParseVersion(folderName: string): number[] | undefined {
if (!folderName.startsWith(extensionPrefix)) {
return undefined;
}
const versionText: string | undefined = folderName.substring(extensionPrefix.length).match(/^\d+\.\d+\.\d+/)?.[0];
return versionText?.split('.').map(each => Number(each));
}
async function getInstalledExtensions(root: string): Promise<InstalledExtension[]> {
try {
const entries = await readdir(root, { withFileTypes: true });
const candidates: Promise<InstalledExtension | undefined>[] = entries.map(async (entry) => {
if (!entry.isDirectory()) {
return undefined;
}
const version: number[] | undefined = tryParseVersion(entry.name);
if (!version) {
return undefined;
}
const extensionPath: string = join(root, entry.name);
for (const folder of foldersToCopy) {
const info = await stat(join(extensionPath, folder)).catch(() => undefined);
if (!info?.isDirectory()) {
return undefined;
}
}
const info = await stat(extensionPath);
return {
path: extensionPath,
version,
modified: info.mtimeMs
};
});
const found = await Promise.all(candidates);
return found.filter((entry): entry is InstalledExtension => entry !== undefined);
} catch {
return [];
}
}
async function findLatestInstalledExtension(providedPath?: string): Promise<string> {
if (providedPath) {
return providedPath;
}
const searchRoots: string[] = [
join(homedir(), '.vscode', 'extensions'),
join(homedir(), '.vscode-insiders', 'extensions'),
join(homedir(), '.vscode-server', 'extensions'),
join(homedir(), '.vscode-server-insiders', 'extensions')
];
const installed: InstalledExtension[] = (await Promise.all(searchRoots.map(each => getInstalledExtensions(each)))).flat();
if (!installed.length) {
throw new Error(`Unable to find an installed C/C++ extension under ${searchRoots.join(' or ')}.`);
}
installed.sort((left, right) => compareVersions(right.version, left.version) || right.modified - left.modified);
return installed[0].path;
}
export async function main(sourcePath = $args[0]) {
console.log(heading('Copy installed extension binaries'));
const installedExtensionPath: string = await findLatestInstalledExtension(sourcePath);
note(`Using installed extension at ${installedExtensionPath}`);
for (const folder of foldersToCopy) {
const source: string = join(installedExtensionPath, folder);
const destination: string = join($root, folder);
console.log(`Copying ${green(folder)} from ${source}`);
await rm(destination, { recursive: true, force: true });
await cp(source, destination, { recursive: true, force: true });
}
note(`Copied installed binaries into ${$root}`);
}
+4
View File
@@ -97,6 +97,10 @@
"label": "MultirootDeadlockTest ",
"value": "${workspaceFolder}/test/scenarios/MultirootDeadlockTest/assets/test.code-workspace"
},
{
"label": "RunWithoutDebugging ",
"value": "${workspaceFolder}/test/scenarios/RunWithoutDebugging/assets/"
},
{
"label": "SimpleCppProject ",
"value": "${workspaceFolder}/test/scenarios/SimpleCppProject/assets/simpleCppProject.code-workspace"
+1
View File
@@ -35,6 +35,7 @@ eslint.config.js
gulpfile.js
localized_string_ids.h
readme.developer.md
Reinstalling the Extension.md
test.tsconfig.json
translations_auto_pr.js
tsconfig.json
+16 -3
View File
@@ -1,9 +1,22 @@
# C/C++ for Visual Studio Code Changelog
## Version 1.31.5: April 20, 2026
## Version 1.32.0: April 14, 2026
### New Feature
* Add support for run without debugging. [#1201](https://github.com/microsoft/vscode-cpptools/issues/1201)
### Enhancements
* Add a `C_Cpp.doxygen.generateOnCodeAction` setting to allow disabling of Doxygen generation code actions. [#14341](https://github.com/microsoft/vscode-cpptools/issues/14341)
* Improve wildcard matching with the debugger natvis. [MIEngine#1162](https://github.com/microsoft/MIEngine/issues/1162)
* Add support for `HideRawView` with the debugger natvis. [MIEngine#1458](https://github.com/microsoft/MIEngine/issues/1458)
### Bug Fixes
* Fix `Reinstalling the Extension.md` not being found. [#14389](https://github.com/microsoft/vscode-cpptools/issues/14389)
* Fix the `C/C++ DevTools` extension language service tools not working after the `C/C++` extension updates via `Restart Extensions`. [#14392](https://github.com/microsoft/vscode-cpptools/issues/14392)
* Fix high CPU usage caused by repeated calls to `selectChatModels`. [#14168](https://github.com/microsoft/vscode-cpptools/issues/14168), [#14211](https://github.com/microsoft/vscode-cpptools/issues/14211), [#14241](https://github.com/microsoft/vscode-cpptools/issues/14241)
* Fix the MSVC developer environment not working if `UCRTVersion` isn't found, and update the walkthrough instructions for installing MSVC. [#14352](https://github.com/microsoft/vscode-cpptools/issues/14352)
* Fix Copilot hover taking too many premium requests. [#14372](https://github.com/microsoft/vscode-cpptools/issues/14372)
* Fix null pointers being expandable for variables in the debugger. [MIEngine#698](https://github.com/microsoft/MIEngine/issues/698)
* Fix recursive `{this}` evaluation with the debugger natvis. [MIEngine#1391](https://github.com/microsoft/MIEngine/issues/1391)
* Update clang-tidy and clang-format from 22.1.1 to 22.1.3 (bug fixes).
* Fix a bug with semantic colorization of operators.
## Version 1.31.4: March 31, 2026
### Bug Fix
+6 -6
View File
@@ -1250,7 +1250,7 @@ SOFTWARE.
---------------------------------------------------------
@xmldom/xmldom 0.8.11 - MIT
@xmldom/xmldom 0.8.12 - MIT
https://github.com/xmldom/xmldom
Copyright 2019 - present Christopher J. Brody and other contributors
@@ -1510,7 +1510,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---------------------------------------------------------
brace-expansion 1.1.12 - MIT
brace-expansion 1.1.13 - MIT
https://github.com/juliangruber/brace-expansion
Copyright (c) 2013 Julian Gruber <[email protected]>
@@ -1542,7 +1542,7 @@ SOFTWARE.
---------------------------------------------------------
brace-expansion 2.0.2 - MIT
brace-expansion 2.0.3 - MIT
https://github.com/juliangruber/brace-expansion
Copyright (c) 2013 Julian Gruber <[email protected]>
@@ -1642,7 +1642,7 @@ SOFTWARE.
chokidar 3.6.0 - MIT
https://github.com/paulmillr/chokidar
(c) Paul Miller <https://paulmillr.com>
(c) Paul Miller
Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker
The MIT License (MIT)
@@ -3018,7 +3018,7 @@ THE SOFTWARE.
---------------------------------------------------------
picomatch 2.3.1 - MIT
picomatch 2.3.2 - MIT
https://github.com/micromatch/picomatch
Copyright (c) 2017-present, Jon Schlinkert
@@ -3183,7 +3183,7 @@ readdirp 3.6.0 - MIT
https://github.com/paulmillr/readdirp
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com)
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller <https://paulmillr.com>
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller ( https://paulmillr.com )
MIT License
+8 -1
View File
@@ -2,7 +2,7 @@
"name": "cpptools",
"displayName": "C/C++",
"description": "C/C++ IntelliSense, debugging, and code browsing.",
"version": "1.31.5-main",
"version": "1.32.0-main",
"publisher": "ms-vscode",
"icon": "LanguageCCPP_color_128x.png",
"readme": "README.md",
@@ -1703,6 +1703,12 @@
"description": "%c_cpp.configuration.doxygen.generateOnType.description%",
"scope": "resource"
},
"C_Cpp.doxygen.generateOnCodeAction": {
"type": "boolean",
"default": true,
"description": "%c_cpp.configuration.doxygen.generateOnCodeAction.description%",
"scope": "resource"
},
"C_Cpp.doxygen.generatedStyle": {
"type": "string",
"enum": [
@@ -6799,6 +6805,7 @@
"generate-native-strings": "ts-node -T ./.scripts/generateNativeStrings.ts",
"generate-options-schema": "ts-node -T ./.scripts/generateOptionsSchema.ts",
"copy-walkthrough-media": "ts-node -T ./.scripts/copyWalkthruMedia.ts",
"copy-extension-binaries": "ts-node -T ./.scripts/copyExtensionBinaries.ts",
"translations-export": "yarn install && yarn prep && yarn generate-native-strings && gulp translations-export",
"translations-generate": "gulp translations-generate",
"translations-import": "gulp translations-import",
+1
View File
@@ -580,6 +580,7 @@
]
},
"c_cpp.configuration.doxygen.generateOnType.description": "Controls whether to automatically insert the Doxygen comment after typing the chosen comment style.",
"c_cpp.configuration.doxygen.generateOnCodeAction.description": "Controls whether the code action to generate a Doxygen comment is enabled.",
"c_cpp.configuration.doxygen.generatedStyle.description": "The string of characters used as the starting line of the Doxygen comment.",
"c_cpp.configuration.doxygen.sectionTags.description": "Select the Doxygen section tags that you would like to appear on hover in the tooltip area when the 'Simplify Structured Comments' setting is enabled. ",
"c_cpp.configuration.commentContinuationPatterns.items.anyof.string.markdownDescription": {
@@ -147,12 +147,14 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
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 {
const noDebug = config.noDebug ?? false; // Preserve the noDebug value from the config if it exists.
// Currently, we expect only one debug config to be selected.
console.assert(configs.length === 1, "More than one debug config is selected.");
config = configs[0];
// Keep track of the entry point where the debug config has been selected, for telemetry purposes.
config.debuggerEvent = DebuggerEvent.debugPanel;
config.configSource = folder ? ConfigSource.workspaceFolder : ConfigSource.singleFile;
config.noDebug = noDebug;
}
}
+3 -3
View File
@@ -97,7 +97,7 @@ function createLaunchString(name: string, type: string, executable: string): str
"stopAtEntry": false,
"cwd": "$\{fileDirname\}",
"environment": [],
${ type === "cppdbg" ? `"externalConsole": false` : `"console": "externalTerminal"` }
${type === "cppdbg" ? `"externalConsole": false` : `"console": "internalConsole"`}
`;
}
@@ -164,7 +164,7 @@ export class MIConfigurations extends Configuration {
\t${indentJsonString(createLaunchString(name, this.miDebugger, this.executable))},
\t"MIMode": "${this.MIMode}"{0}{1}
}`, [this.miDebugger === "cppdbg" && os.platform() === "win32" ? `,${os.EOL}\t"miDebuggerPath": "/path/to/gdb"` : "",
this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
return {
"label": configPrefix + name,
@@ -182,7 +182,7 @@ export class MIConfigurations extends Configuration {
\t${indentJsonString(createAttachString(name, this.miDebugger, this.executable))}
\t"MIMode": "${this.MIMode}"{0}{1}
}`, [this.miDebugger === "cppdbg" && os.platform() === "win32" ? `,${os.EOL}\t"miDebuggerPath": "/path/to/gdb"` : "",
this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
return {
"label": configPrefix + name,
@@ -7,11 +7,13 @@ import * as os from 'os';
import * as path from 'path';
import * as vscode from "vscode";
import * as nls from 'vscode-nls';
import { getOutputChannel } from '../logger';
import { RunWithoutDebuggingAdapter } from './runWithoutDebuggingAdapter';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
// Registers DebugAdapterDescriptorFactory for `cppdbg` and `cppvsdbg`. If it is not ready, it will prompt a wait for the download dialog.
// Registers DebugAdapterDescriptorFactory for `cppdbg` and `cppvsdbg`.
// NOTE: This file is not automatically tested.
abstract class AbstractDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
@@ -26,8 +28,15 @@ abstract class AbstractDebugAdapterDescriptorFactory implements vscode.DebugAdap
}
export class CppdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDescriptorFactory {
async createDebugAdapterDescriptor(session: vscode.DebugSession, _executable?: vscode.DebugAdapterExecutable): Promise<vscode.DebugAdapterDescriptor> {
if (session.configuration.noDebug) {
if (noDebugSupported(session.configuration)) {
return new vscode.DebugAdapterInlineImplementation(new RunWithoutDebuggingAdapter());
}
// If the configuration is not supported, gracefully fall back to a regular debug session and log a message to the user.
logReasonForNoDebugNotSupported(session.configuration);
}
async createDebugAdapterDescriptor(_session: vscode.DebugSession, _executable?: vscode.DebugAdapterExecutable): Promise<vscode.DebugAdapterDescriptor> {
const adapter: string = "./debugAdapters/bin/OpenDebugAD7" + (os.platform() === 'win32' ? ".exe" : "");
const command: string = path.join(this.context.extensionPath, adapter);
@@ -37,8 +46,15 @@ export class CppdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDes
}
export class CppvsdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterDescriptorFactory {
async createDebugAdapterDescriptor(session: vscode.DebugSession, _executable?: vscode.DebugAdapterExecutable): Promise<vscode.DebugAdapterDescriptor | null> {
if (session.configuration.noDebug) {
if (noDebugSupported(session.configuration)) {
return new vscode.DebugAdapterInlineImplementation(new RunWithoutDebuggingAdapter());
}
// If the configuration is not supported, gracefully fall back to a regular debug session and log a message to the user.
logReasonForNoDebugNotSupported(session.configuration);
}
async createDebugAdapterDescriptor(_session: vscode.DebugSession, _executable?: vscode.DebugAdapterExecutable): Promise<vscode.DebugAdapterDescriptor | null> {
if (os.platform() !== 'win32') {
void vscode.window.showErrorMessage(localize("debugger.not.available", "Debugger type '{0}' is not available for non-Windows machines.", "cppvsdbg"));
return null;
@@ -50,3 +66,28 @@ export class CppvsdbgDebugAdapterDescriptorFactory extends AbstractDebugAdapterD
}
}
}
function noDebugSupported(configuration: vscode.DebugConfiguration): boolean {
// Don't attempt to start a noDebug session if the configuration has any of these properties, which require a debug adapter to function.
return configuration.request === 'launch' && !configuration.pipeTransport && !configuration.debugServerPath && !configuration.miDebuggerServerAddress && !configuration.coreDumpPath;
}
function logReasonForNoDebugNotSupported(configuration: vscode.DebugConfiguration): void {
const outputChannel = getOutputChannel();
if (configuration.request !== 'launch') {
outputChannel.appendLine(localize("debugger.noDebug.requestType.not.supported", "Run Without Debugging is only supported for launch configurations."));
}
if (configuration.pipeTransport) {
outputChannel.appendLine(localize("debugger.noDebug.pipeTransport.not.supported", "Run Without Debugging is not supported for configurations with 'pipeTransport' set."));
}
if (configuration.debugServerPath) {
outputChannel.appendLine(localize("debugger.noDebug.debugServerPath.not.supported", "Run Without Debugging is not supported for configurations with 'debugServerPath' set."));
}
if (configuration.miDebuggerServerAddress) {
outputChannel.appendLine(localize("debugger.noDebug.miDebuggerServerAddress.not.supported", "Run Without Debugging is not supported for configurations with 'miDebuggerServerAddress' set."));
}
if (configuration.coreDumpPath) {
outputChannel.appendLine(localize("debugger.noDebug.coreDumpPath.not.supported", "Run Without Debugging is not supported for configurations with 'coreDumpPath' set."));
}
outputChannel.show(true);
}
@@ -0,0 +1,302 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as cp from 'child_process';
import * as os from 'os';
import * as path from 'path';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { buildShellCommandLine, sessionIsWsl } from '../common';
import { isWindows } from '../constants';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize = nls.loadMessageBundle();
/**
* A minimal inline Debug Adapter that runs the target program directly without a debug adapter
* when the user invokes "Run Without Debugging".
*/
export class RunWithoutDebuggingAdapter implements vscode.DebugAdapter {
private readonly sendMessageEmitter = new vscode.EventEmitter<vscode.DebugProtocolMessage>();
public readonly onDidSendMessage: vscode.Event<vscode.DebugProtocolMessage> = this.sendMessageEmitter.event;
private readonly terminalListeners: vscode.Disposable[] = [];
private seq: number = 1;
private childProcess?: cp.ChildProcess;
private terminal?: vscode.Terminal;
private terminalExecution?: vscode.TerminalShellExecution;
private hasTerminated: boolean = false;
public handleMessage(message: vscode.DebugProtocolMessage): void {
const msg = message as { type: string; command: string; seq: number; arguments?: any; };
if (msg.type === 'request') {
void this.handleRequest(msg);
}
}
private async handleRequest(request: { command: string; seq: number; arguments?: any; }): Promise<void> {
switch (request.command) {
case 'initialize':
this.sendResponse(request, {});
this.sendEvent('initialized');
break;
case 'launch':
await this.launch(request);
break;
case 'configurationDone':
this.sendResponse(request, {});
break;
case 'disconnect':
case 'terminate':
this.sendResponse(request, {});
break;
default:
this.sendResponse(request, {});
break;
}
}
private async launch(request: { command: string; seq: number; arguments?: any; }): Promise<void> {
const config = request.arguments as {
program?: string;
args?: string[];
cwd?: string;
environment?: { name: string; value: string; }[];
console?: string;
externalConsole?: boolean;
};
const program: string = config.program ?? '';
const args: string[] = config.args ?? [];
const cwd: string | undefined = config.cwd;
const environment: { name: string; value: string; }[] = config.environment ?? [];
const consoleMode: string = config.console ?? (config.externalConsole ? 'externalTerminal' : 'integratedTerminal');
// Merge the launch config's environment variables on top of the inherited process environment.
const env: NodeJS.ProcessEnv = { ...process.env };
for (const e of environment) {
env[e.name] = e.value;
}
this.sendResponse(request, {});
if (consoleMode === 'integratedTerminal' || consoleMode === 'internalConsole') {
await this.launchIntegratedTerminal(program, args, cwd, env);
} else if (consoleMode === 'externalTerminal') {
this.launchExternalTerminal(program, args, cwd, env);
}
}
/**
* Launch the program in a VS Code integrated terminal.
* The terminal will remain open after the program exits and be reused for the next session, if applicable.
*/
private async launchIntegratedTerminal(program: string, args: string[], cwd: string | undefined, env: NodeJS.ProcessEnv): Promise<void> {
const terminalName = path.normalize(program);
const existingTerminal = vscode.window.terminals.find(t => t.name === terminalName);
this.terminal = existingTerminal ?? vscode.window.createTerminal({
name: terminalName,
cwd,
env: env as Record<string, string>
});
this.terminal.show(true);
const shellIntegration: vscode.TerminalShellIntegration | undefined =
this.terminal.shellIntegration ?? await this.waitForShellIntegration(this.terminal, 3000);
// Not all terminals support shell integration. If it's not available, we'll just send the command as text though we won't be able to monitor its execution.
if (shellIntegration) {
this.monitorIntegratedTerminal(this.terminal);
let executable: string = program;
let executableArgs: string[] = args;
if (!program.match(/["']/) && program.match(/\s/)) {
// VS Code does not automatically quote the program path if it has spaces.
const shellPath: string | undefined = 'shellPath' in this.terminal.creationOptions
? this.terminal.creationOptions.shellPath?.toLowerCase()
: undefined;
const terminalShell: string | undefined = this.terminal.state.shell?.toLowerCase();
const defaultTerminalProfile: string | undefined = isWindows
? vscode.workspace.getConfiguration('terminal.integrated').get<string>('defaultProfile.windows')?.toLowerCase()
: undefined;
const isPowerShell: boolean | undefined =
shellPath?.endsWith('pwsh.exe') || shellPath?.endsWith('powershell.exe') || shellPath?.endsWith('pwsh') ||
terminalShell?.includes('powershell') || terminalShell?.includes('pwsh') ||
defaultTerminalProfile?.includes('powershell') || defaultTerminalProfile?.includes('pwsh');
if (isPowerShell || (isWindows && isPowerShell === undefined)) { // PowerShell is the default on Windows if we can't determine the shell.
executable = '&';
executableArgs = [program, ...args];
} else {
executable = `"${program}"`;
}
}
this.terminalExecution = shellIntegration.executeCommand(executable, executableArgs);
} else {
const cmdLine: string = buildShellCommandLine('', program, args, true);
this.terminal.sendText(cmdLine);
// The terminal manages its own lifecycle; notify VS Code the "debug" session is done.
this.sendEvent('terminated');
}
}
/**
* Launch the program in an external terminal. We do not keep track of this terminal or the spawned process.
*/
private launchExternalTerminal(program: string, args: string[], cwd: string | undefined, env: NodeJS.ProcessEnv): void {
const cmdLine: string = buildShellCommandLine('', program, args, true);
const platform: string = os.platform();
if (platform === 'win32') {
cp.spawn('cmd.exe', ['/c', 'start', 'cmd.exe', '/K', `"${cmdLine}"`], { cwd, env, windowsVerbatimArguments: true, detached: true, stdio: 'ignore' }).unref();
} else if (platform === 'darwin') {
cp.spawn('osascript', ['-e', `tell application "Terminal" to do script "${this.escapeQuotes(cmdLine)}"`], { cwd, env, detached: true, stdio: 'ignore' }).unref();
} else if (platform === 'linux' && sessionIsWsl()) {
cp.spawn('/mnt/c/Windows/System32/cmd.exe', ['/c', 'start', 'bash', '-c', `${cmdLine};read -p 'Press enter to continue...'`], { env, detached: true, stdio: 'ignore' }).unref();
} else { // platform === 'linux'
this.launchLinuxExternalTerminal(cmdLine, cwd, env);
}
this.sendEvent('terminated');
}
/**
* On Linux, find and launch an available terminal emulator to run the command.
*/
private launchLinuxExternalTerminal(cmdLine: string, cwd: string | undefined, env: NodeJS.ProcessEnv): void {
const bashCmd = `${cmdLine}; echo; read -p 'Press enter to continue...'`;
const bashArgs = ['bash', '-c', bashCmd];
// Terminal emulators in order of preference, with the correct flag style for each.
const candidates: { cmd: string; buildArgs(): string[] }[] = [
{ cmd: 'x-terminal-emulator', buildArgs: () => ['-e', ...bashArgs] },
{ cmd: 'gnome-terminal', buildArgs: () => ['-e', ...bashArgs] },
{ cmd: 'konsole', buildArgs: () => ['-e', ...bashArgs] },
{ cmd: 'xterm', buildArgs: () => ['-e', ...bashArgs] }
];
// Honor the $TERMINAL environment variable if set.
const terminalEnv = process.env['TERMINAL'];
if (terminalEnv) {
candidates.unshift({ cmd: terminalEnv, buildArgs: () => ['-e', ...bashArgs] });
}
for (const candidate of candidates) {
try {
const result = cp.spawnSync('which', [candidate.cmd], { stdio: 'pipe' });
if (result.status === 0) {
cp.spawn(candidate.cmd, candidate.buildArgs(), { cwd, env, detached: true, stdio: 'ignore' }).unref();
return;
}
} catch {
continue;
}
}
const message = localize('no.terminal.emulator', 'No terminal emulator found. Please set the $TERMINAL environment variable to your terminal emulator of choice, or install one of the following: x-terminal-emulator, gnome-terminal, konsole, xterm.');
vscode.window.showErrorMessage(message);
}
private escapeQuotes(arg: string): string {
return arg.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
}
private waitForShellIntegration(terminal: vscode.Terminal, timeoutMs: number): Promise<vscode.TerminalShellIntegration | undefined> {
return new Promise(resolve => {
let resolved: boolean = false;
const done = (shellIntegration: vscode.TerminalShellIntegration | undefined): void => {
if (resolved) {
return;
}
resolved = true;
clearTimeout(timeout);
shellIntegrationChanged.dispose();
terminalClosed.dispose();
resolve(shellIntegration);
};
const timeout = setTimeout(() => done(undefined), timeoutMs);
const shellIntegrationChanged = vscode.window.onDidChangeTerminalShellIntegration(event => {
if (event.terminal === terminal) {
done(event.shellIntegration);
}
});
const terminalClosed = vscode.window.onDidCloseTerminal(closedTerminal => {
if (closedTerminal === terminal) {
done(undefined);
}
});
});
}
private monitorIntegratedTerminal(terminal: vscode.Terminal): void {
this.disposeTerminalListeners();
this.terminalListeners.push(
vscode.window.onDidEndTerminalShellExecution(event => {
if (event.terminal !== terminal || event.execution !== this.terminalExecution || this.hasTerminated) {
return;
}
if (event.exitCode !== undefined) {
this.sendEvent('exited', { exitCode: event.exitCode });
}
this.sendEvent('terminated');
}),
vscode.window.onDidCloseTerminal(closedTerminal => {
if (closedTerminal !== terminal || this.hasTerminated) {
return;
}
this.sendEvent('terminated');
})
);
}
private disposeTerminalListeners(): void {
while (this.terminalListeners.length > 0) {
this.terminalListeners.pop()?.dispose();
}
}
private sendResponse(request: { command: string; seq: number; }, body: object): void {
this.sendMessageEmitter.fire({
type: 'response',
seq: this.seq++,
request_seq: request.seq,
success: true,
command: request.command,
body
} as vscode.DebugProtocolMessage);
}
private sendEvent(event: string, body?: object): void {
if (event === 'terminated') {
if (this.hasTerminated) {
return;
}
this.hasTerminated = true;
this.disposeTerminalListeners();
}
this.sendMessageEmitter.fire({
type: 'event',
seq: this.seq++,
event,
body
} as vscode.DebugProtocolMessage);
}
public dispose(): void {
this.terminateProcess();
this.disposeTerminalListeners();
this.sendMessageEmitter.dispose();
}
private terminateProcess(): void {
this.childProcess?.kill();
this.childProcess = undefined;
}
}
@@ -26,10 +26,69 @@ export class CopilotHoverProvider implements vscode.HoverProvider {
private cancelledDocument: vscode.TextDocument | undefined;
private cancelledPosition: vscode.Position | undefined;
private content: string | undefined;
private chatModel: vscode.LanguageModelChat | undefined;
private chatModelId: string | undefined; // Save the selected model ID to avoid trying the same unavailable model repeatedly.
// Flag to avoid querying the LanguageModelChat repeatedly if no model is found
private checkedChatModel: boolean = false;
constructor(client: DefaultClient) {
this.client = client;
}
public async getCachedChatModel(): Promise<vscode.LanguageModelChat | undefined> {
if (this.checkedChatModel) {
return this.chatModel;
}
const vscodelm = getVSCodeLanguageModel();
if (vscodelm) {
try {
let model: vscode.LanguageModelChat | undefined;
if (this.chatModelId === undefined) {
// First look for GPT-4o which should be available to all
// users and have a 0x multiplier on paid plans.
// GPT-4o is faster than the x0 GPT-5-mini (which seems too slow for hover, e.g. 10+ seconds).
this.chatModelId = 'gpt-4o';
[model] = await vscodelm.selectChatModels({ ...modelSelector, id: this.chatModelId });
if (!model) {
// If GPT-4o is not available, fallback to GPT-5.4-mini (x0.33 and fast).
this.chatModelId = 'gpt-5.4-mini';
[model] = await vscodelm.selectChatModels({ ...modelSelector, id: this.chatModelId });
}
if (!model) {
// If GPT-5.4-mini is not available, fallback to the first available model.
this.chatModelId = 'default';
[model] = await vscodelm.selectChatModels(modelSelector);
}
} else {
if (this.chatModelId === 'default') {
[model] = await vscodelm.selectChatModels(modelSelector);
} else {
[model] = await vscodelm.selectChatModels({ ...modelSelector, id: this.chatModelId });
}
}
if (!model) {
telemetry.logLanguageServerEvent('CopilotHoverNoModelSelected', { remoteName: vscode.env.remoteName || 'local' });
} else {
this.chatModel = model;
}
} catch (e: any) {
const exceptionType = e?.name || e?.constructor?.name || typeof e;
telemetry.logLanguageServerEvent('CopilotHoverSelectModelFailed', {
remoteName: vscode.env.remoteName || 'local',
exceptionType: String(exceptionType)
});
}
}
this.checkedChatModel = true;
return this.chatModel;
}
public async refreshCachedChatModel(): Promise<vscode.LanguageModelChat | undefined> {
this.chatModel = undefined;
this.checkedChatModel = false;
return this.getCachedChatModel();
}
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover | undefined> {
await this.client.ready;
@@ -43,12 +102,9 @@ export class CopilotHoverProvider implements vscode.HoverProvider {
}
// Ensure the user has access to Copilot.
const vscodelm = getVSCodeLanguageModel();
if (vscodelm) {
const [model] = await vscodelm.selectChatModels(modelSelector);
if (!model) {
return undefined;
}
const model = await this.getCachedChatModel();
if (!model) {
return undefined;
}
const newHover = this.isNewHover(document, position);
@@ -88,6 +88,129 @@ const CallHierarchyCallsToRequest: RequestType<CallHierarchyParams, CallHierarch
const CallHierarchyCallsFromRequest: RequestType<CallHierarchyParams, CallHierarchyCallsItemResult, void> =
new RequestType<CallHierarchyParams, CallHierarchyCallsItemResult, void>('cpptools/callHierarchyCallsFrom');
function makeVscodeCallHierarchyItem(client: DefaultClient, item: CallHierarchyItem): vscode.CallHierarchyItem {
const containerDetail: string = (item.detail !== "") ? `${item.detail} - ` : "";
const itemUri: vscode.Uri = vscode.Uri.file(item.file);
// Get file detail
const isInWorkspace: boolean = client.RootUri !== undefined &&
itemUri.fsPath.startsWith(client.RootUri.fsPath);
const dirPath: string = isInWorkspace ?
path.relative(client.RootPath, path.dirname(item.file)) : path.dirname(item.file);
const fileDetail: string = dirPath.length === 0 ?
`${path.basename(item.file)}` : `${path.basename(item.file)} (${dirPath})`;
return new vscode.CallHierarchyItem(
item.kind,
item.name,
containerDetail + fileDetail,
itemUri,
makeVscodeRange(item.range),
makeVscodeRange(item.selectionRange));
}
function createIncomingCalls(client: DefaultClient, calls: CallHierarchyCallsItem[]): vscode.CallHierarchyIncomingCall[] {
const result: vscode.CallHierarchyIncomingCall[] = [];
for (const call of calls) {
const item: vscode.CallHierarchyItem = makeVscodeCallHierarchyItem(client, call.item);
const ranges: vscode.Range[] = [];
call.fromRanges.forEach(r => {
ranges.push(makeVscodeRange(r));
});
const incomingCall: vscode.CallHierarchyIncomingCall =
new vscode.CallHierarchyIncomingCall(item, ranges);
result.push(incomingCall);
}
return result;
}
function createOutgoingCalls(client: DefaultClient, calls: CallHierarchyCallsItem[]): vscode.CallHierarchyOutgoingCall[] {
const result: vscode.CallHierarchyOutgoingCall[] = [];
for (const call of calls) {
const item: vscode.CallHierarchyItem = makeVscodeCallHierarchyItem(client, call.item);
const ranges: vscode.Range[] = [];
call.fromRanges.forEach(r => {
ranges.push(makeVscodeRange(r));
});
const outgoingCall: vscode.CallHierarchyOutgoingCall =
new vscode.CallHierarchyOutgoingCall(item, ranges);
result.push(outgoingCall);
}
return result;
}
export async function sendPrepareCallHierarchyRequest(client: DefaultClient, uri: vscode.Uri, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.CallHierarchyItem[] | undefined> {
const params: CallHierarchyParams = {
textDocument: { uri: uri.toString() },
position: Position.create(position.line, position.character)
};
let response: CallHierarchyItemResult;
try {
response = await client.languageClient.sendRequest(CallHierarchyItemRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
return undefined;
}
throw e;
}
if (token.isCancellationRequested) {
return undefined;
}
return response.item === undefined ? [] : [makeVscodeCallHierarchyItem(client, response.item)];
}
export async function sendCallHierarchyCallsToRequest(client: DefaultClient, item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
const params: CallHierarchyParams = {
textDocument: { uri: item.uri.toString() },
position: Position.create(item.selectionRange.start.line, item.selectionRange.start.character)
};
let response: CallHierarchyCallsItemResult;
try {
response = await client.languageClient.sendRequest(CallHierarchyCallsToRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
return undefined;
}
throw e;
}
if (token.isCancellationRequested) {
return undefined;
}
return response.calls.length !== 0 ? createIncomingCalls(client, response.calls) : [];
}
export async function sendCallHierarchyCallsFromRequest(client: DefaultClient, item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
const params: CallHierarchyParams = {
textDocument: { uri: item.uri.toString() },
position: Position.create(item.selectionRange.start.line, item.selectionRange.start.character)
};
let response: CallHierarchyCallsItemResult;
try {
response = await client.languageClient.sendRequest(CallHierarchyCallsFromRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
return undefined;
}
throw e;
}
if (token.isCancellationRequested) {
return undefined;
}
return response.calls.length !== 0 ? createOutgoingCalls(client, response.calls) : [];
}
export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
// Indicates whether a request is from an entry root node (e.g. top function in the call tree).
private isEntryRootNodeTelemetry: boolean = false;
@@ -118,20 +241,10 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
cancelSource.cancel();
});
const params: CallHierarchyParams = {
textDocument: { uri: document.uri.toString() },
position: Position.create(position.line, position.character)
};
let response: CallHierarchyItemResult;
let result: vscode.CallHierarchyItem[] | undefined;
try {
response = await this.client.languageClient.sendRequest(CallHierarchyItemRequest, params, cancelSource.token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
return undefined;
}
throw e;
}
finally {
result = await sendPrepareCallHierarchyRequest(this.client, document.uri, position, cancelSource.token);
} finally {
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}
@@ -139,12 +252,12 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
if (cancelSource.token.isCancellationRequested) {
throw new vscode.CancellationError();
}
if (response.item === undefined) {
if (!result || result.length === 0) {
return undefined;
}
this.isEntryRootNodeTelemetry = true;
return this.makeVscodeCallHierarchyItem(response.item);
return result[0];
}
public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
@@ -172,39 +285,28 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
// Send the request to the language server.
let result: vscode.CallHierarchyIncomingCall[] | undefined;
const params: CallHierarchyParams = {
textDocument: { uri: item.uri.toString() },
position: Position.create(item.selectionRange.start.line, item.selectionRange.start.character)
};
let response: CallHierarchyCallsItemResult | undefined;
let cancelled: boolean = false;
let progressBarDuration: number | undefined;
try {
response = await this.client.languageClient.sendRequest(CallHierarchyCallsToRequest, params, cancelSource.token);
} catch (e: any) {
cancelled = e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled);
if (!cancelled) {
throw e;
}
result = await sendCallHierarchyCallsToRequest(this.client, item, cancelSource.token);
} finally {
// Reset anything that can be cleared before processing the result.
progressBarDuration = workspaceReferences.getCallHierarchyProgressBarDuration();
workspaceReferences.resetProgressBar();
workspaceReferences.resetReferences();
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
}
// Reset anything that can be cleared before processing the result.
const progressBarDuration: number | undefined = workspaceReferences.getCallHierarchyProgressBarDuration();
workspaceReferences.resetProgressBar();
workspaceReferences.resetReferences();
cancellationTokenListener.dispose();
requestCanceledListener.dispose();
// Process the result.
if (cancelSource.token.isCancellationRequested || cancelled || requestCanceled !== undefined) {
if (cancelSource.token.isCancellationRequested || result === undefined || requestCanceled !== undefined) {
const requestStatus: CallHierarchyRequestStatus = requestCanceled === CancellationSender.User ?
CallHierarchyRequestStatus.CanceledByUser : CallHierarchyRequestStatus.Canceled;
this.logTelemetry(CallHierarchyCallsToEvent, requestStatus, progressBarDuration);
throw new vscode.CancellationError();
} else if (response && response.calls.length !== 0) {
result = this.createIncomingCalls(response.calls);
}
this.logTelemetry(CallHierarchyCallsToEvent, CallHierarchyRequestStatus.Succeeded, progressBarDuration);
return result;
return result.length !== 0 ? result : undefined;
}
public async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
@@ -216,87 +318,15 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
await this.client.ready;
let result: vscode.CallHierarchyOutgoingCall[] | undefined;
const params: CallHierarchyParams = {
textDocument: { uri: item.uri.toString() },
position: Position.create(item.selectionRange.start.line, item.selectionRange.start.character)
};
let response: CallHierarchyCallsItemResult | undefined;
let cancelled: boolean = false;
try {
response = await this.client.languageClient.sendRequest(CallHierarchyCallsFromRequest, params, token);
} catch (e: any) {
cancelled = e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled);
if (!cancelled) {
throw e;
}
}
if (token.isCancellationRequested || cancelled) {
const result: vscode.CallHierarchyOutgoingCall[] | undefined =
await sendCallHierarchyCallsFromRequest(this.client, item, token);
if (token.isCancellationRequested || result === undefined) {
this.logTelemetry(CallHierarchyCallsFromEvent, CallHierarchyRequestStatus.Canceled);
throw new vscode.CancellationError();
} else if (response && response.calls.length !== 0) {
result = this.createOutgoingCalls(response.calls);
}
this.logTelemetry(CallHierarchyCallsFromEvent, CallHierarchyRequestStatus.Succeeded);
return result;
}
private makeVscodeCallHierarchyItem(item: CallHierarchyItem): vscode.CallHierarchyItem {
const containerDetail: string = (item.detail !== "") ? `${item.detail} - ` : "";
const itemUri: vscode.Uri = vscode.Uri.file(item.file);
// Get file detail
const isInWorkspace: boolean = this.client.RootUri !== undefined &&
itemUri.fsPath.startsWith(this.client.RootUri?.fsPath);
const dirPath: string = isInWorkspace ?
path.relative(this.client.RootPath, path.dirname(item.file)) : path.dirname(item.file);
const fileDetail: string = dirPath.length === 0 ?
`${path.basename(item.file)}` : `${path.basename(item.file)} (${dirPath})`;
return new vscode.CallHierarchyItem(
item.kind,
item.name,
containerDetail + fileDetail,
itemUri,
makeVscodeRange(item.range),
makeVscodeRange(item.selectionRange));
}
private createIncomingCalls(calls: CallHierarchyCallsItem[]): vscode.CallHierarchyIncomingCall[] {
const result: vscode.CallHierarchyIncomingCall[] = [];
for (const call of calls) {
const item: vscode.CallHierarchyItem = this.makeVscodeCallHierarchyItem(call.item);
const ranges: vscode.Range[] = [];
call.fromRanges.forEach(r => {
ranges.push(makeVscodeRange(r));
});
const incomingCall: vscode.CallHierarchyIncomingCall =
new vscode.CallHierarchyIncomingCall(item, ranges);
result.push(incomingCall);
}
return result;
}
private createOutgoingCalls(calls: CallHierarchyCallsItem[]): vscode.CallHierarchyOutgoingCall[] {
const result: vscode.CallHierarchyOutgoingCall[] = [];
for (const call of calls) {
const item: vscode.CallHierarchyItem = this.makeVscodeCallHierarchyItem(call.item);
const ranges: vscode.Range[] = [];
call.fromRanges.forEach(r => {
ranges.push(makeVscodeRange(r));
});
const outgoingCall: vscode.CallHierarchyOutgoingCall =
new vscode.CallHierarchyOutgoingCall(item, ranges);
result.push(outgoingCall);
}
return result;
return result.length !== 0 ? result : undefined;
}
private logTelemetry(eventName: string, requestStatus: CallHierarchyRequestStatus, progressBarDuration?: number): void {
@@ -11,6 +11,50 @@ import { CancellationSender, ReferenceInfo, ReferenceType, ReferencesParams, Ref
const FindAllReferencesRequest: RequestType<ReferencesParams, ReferencesResult, void> =
new RequestType<ReferencesParams, ReferencesResult, void>('cpptools/findAllReferences');
export interface FindAllReferencesResult {
referencesResult: ReferencesResult;
locations: vscode.Location[];
}
function convertConfirmedReferencesToLocations(referencesResult: ReferencesResult): vscode.Location[] {
const locationsResult: vscode.Location[] = [];
referencesResult.referenceInfos.forEach((referenceInfo: ReferenceInfo) => {
if (referenceInfo.type === ReferenceType.Confirmed) {
const uri: vscode.Uri = vscode.Uri.file(referenceInfo.file);
const range: vscode.Range = new vscode.Range(referenceInfo.position.line, referenceInfo.position.character,
referenceInfo.position.line, referenceInfo.position.character + referencesResult.text.length);
locationsResult.push(new vscode.Location(uri, range));
}
});
return locationsResult;
}
export async function sendFindAllReferencesRequest(client: DefaultClient, uri: vscode.Uri, position: vscode.Position, token: vscode.CancellationToken): Promise<FindAllReferencesResult | undefined> {
const params: ReferencesParams = {
newName: "",
position: Position.create(position.line, position.character),
textDocument: { uri: uri.toString() }
};
let response: ReferencesResult;
try {
response = await client.languageClient.sendRequest(FindAllReferencesRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
return undefined;
}
throw e;
}
if (token.isCancellationRequested || response.isCanceled) {
return undefined;
}
return {
referencesResult: response,
locations: convertConfirmedReferencesToLocations(response)
};
}
export class FindAllReferencesProvider implements vscode.ReferenceProvider {
private client: DefaultClient;
@@ -29,23 +73,10 @@ export class FindAllReferencesProvider implements vscode.ReferenceProvider {
const requestCanceledListener: vscode.Disposable = workspaceReferences.onCancellationRequested(_sender => { cancelSource.cancel(); });
// Send the request to the language server.
const locationsResult: vscode.Location[] = [];
const params: ReferencesParams = {
newName: "",
position: Position.create(position.line, position.character),
textDocument: { uri: document.uri.toString() }
};
let response: ReferencesResult | undefined;
let cancelled: boolean = false;
let result: FindAllReferencesResult | undefined;
try {
response = await this.client.languageClient.sendRequest(FindAllReferencesRequest, params, cancelSource.token);
} catch (e: any) {
cancelled = e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled);
if (!cancelled) {
throw e;
}
}
finally {
result = await sendFindAllReferencesRequest(this.client, document.uri, position, cancelSource.token);
} finally {
// Reset anything that can be cleared before processing the result.
workspaceReferences.resetProgressBar();
cancellationTokenListener.dispose();
@@ -53,30 +84,21 @@ export class FindAllReferencesProvider implements vscode.ReferenceProvider {
}
// Process the result.
if (cancelSource.token.isCancellationRequested || cancelled || (response && response.isCanceled)) {
if (cancelSource.token.isCancellationRequested || !result) {
// Return undefined instead of vscode.CancellationError to avoid the following error message from VS Code:
// "Cannot destructure property 'range' of 'e.location' as it is undefined."
// TODO: per issue https://github.com/microsoft/vscode/issues/169698
// vscode.CancellationError is expected, so when VS Code fixes the error use vscode.CancellationError again.
workspaceReferences.resetReferences();
return undefined;
} else if (response && response.referenceInfos.length > 0) {
response.referenceInfos.forEach((referenceInfo: ReferenceInfo) => {
if (referenceInfo.type === ReferenceType.Confirmed) {
const uri: vscode.Uri = vscode.Uri.file(referenceInfo.file);
const range: vscode.Range = new vscode.Range(referenceInfo.position.line, referenceInfo.position.character,
referenceInfo.position.line, referenceInfo.position.character + response.text.length);
locationsResult.push(new vscode.Location(uri, range));
}
});
} else if (result.referencesResult.referenceInfos.length > 0) {
// Display other reference types in panel or channel view.
// Note: ReferencesManager.resetReferences is called in ReferencesManager.showResultsInPanelView
workspaceReferences.showResultsInPanelView(response);
workspaceReferences.showResultsInPanelView(result.referencesResult);
} else {
workspaceReferences.resetReferences();
}
return locationsResult;
return result.locations;
}
}
@@ -0,0 +1,57 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { Definition, DefinitionLink, DefinitionRequest, Position, ResponseError, TextDocumentPositionParams } from 'vscode-languageclient';
import { DefaultClient } from '../client';
import { RequestCancelled, ServerCancelled } from '../protocolFilter';
function convertDefinitionsToLocations(definitionsResult: vscode.Definition | vscode.DefinitionLink[] | undefined): vscode.Location[] {
if (!definitionsResult) {
return [];
}
if (!Array.isArray(definitionsResult)) {
return [definitionsResult];
}
const result: vscode.Location[] = [];
for (const definition of definitionsResult) {
if (definition instanceof vscode.Location) {
result.push(definition);
} else {
result.push(new vscode.Location(definition.targetUri, definition.targetSelectionRange ?? definition.targetRange));
}
}
return result;
}
export async function sendGoToDefinitionRequest(client: DefaultClient, uri: vscode.Uri, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
const params: TextDocumentPositionParams = {
position: Position.create(position.line, position.character),
textDocument: { uri: uri.toString() }
};
let response: Definition | DefinitionLink[] | null;
try {
response = await client.languageClient.sendRequest(DefinitionRequest.type, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
return undefined;
}
throw e;
}
if (token.isCancellationRequested) {
return undefined;
}
const result: vscode.Definition | vscode.DefinitionLink[] | undefined =
await client.languageClient.protocol2CodeConverter.asDefinitionResult(response, token);
if (token.isCancellationRequested) {
return undefined;
}
return convertDefinitionsToLocations(result);
}
+1 -62
View File
@@ -805,7 +805,6 @@ export interface Client {
setCurrentConfigName(configurationName: string): Thenable<void>;
getCurrentConfigName(): Thenable<string | undefined>;
getCurrentConfigCustomVariable(variableName: string): Thenable<string>;
waitForIdle(timeout?: number): Promise<boolean>;
getVcpkgInstalled(): Thenable<boolean>;
getVcpkgEnabled(): Thenable<boolean>;
getCurrentCompilerPathAndArgs(): Thenable<util.CompilerPathAndArgs | undefined>;
@@ -920,7 +919,6 @@ export class DefaultClient implements Client {
private configStateReceived: ConfigStateReceived = { compilers: false, compileCommands: false, configProviders: undefined, timeout: false };
private showConfigureIntelliSenseButton: boolean = false;
private pendingIdleCalls: { promise: ManualPromise<boolean>; timer?: NodeJS.Timeout }[] = [];
/** A queue of asynchronous tasks that need to be processed befofe ready is considered active. */
private static queue = new Array<[ManualPromise<unknown>, () => Promise<unknown>] | [ManualPromise<unknown>]>();
@@ -1010,56 +1008,6 @@ export class DefaultClient implements Client {
};
}
private isIdle(): boolean {
return !this.model.isInitializingWorkspace.Value
&& !this.model.isIndexingWorkspace.Value
&& !this.model.isParsingWorkspace.Value
&& !this.model.isParsingFiles.Value
&& !this.model.isUpdatingIntelliSense.Value;
}
private resolvePendingIdleCallsIfReady(): void {
if (!this.pendingIdleCalls.length || !this.isIdle()) {
return;
}
const pendingCalls: { promise: ManualPromise<boolean>; timer?: NodeJS.Timeout }[] = this.pendingIdleCalls;
this.pendingIdleCalls = [];
pendingCalls.forEach(pendingCall => {
if (pendingCall.timer) {
clearTimeout(pendingCall.timer);
}
pendingCall.promise.resolve(true);
});
}
public async waitForIdle(timeout?: number): Promise<boolean> {
if (this.isIdle()) {
return true;
}
if (timeout !== undefined && timeout <= 0) {
return false;
}
const pendingCall: { promise: ManualPromise<boolean>; timer?: NodeJS.Timeout } = {
promise: new ManualPromise<boolean>()
};
if (timeout !== undefined) {
pendingCall.timer = global.setTimeout(() => {
const index: number = this.pendingIdleCalls.indexOf(pendingCall);
if (index !== -1) {
this.pendingIdleCalls.splice(index, 1);
}
pendingCall.promise.resolve(false);
}, timeout);
}
this.pendingIdleCalls.push(pendingCall);
return pendingCall.promise;
}
private getName(workspaceFolder?: vscode.WorkspaceFolder): string {
return workspaceFolder ? workspaceFolder.name : "untitled";
}
@@ -1589,6 +1537,7 @@ export class DefaultClient implements Client {
vcFormatSpaceAroundTernaryOperator: settings.vcFormatSpaceAroundTernaryOperator,
vcFormatWrapPreserveBlocks: settings.vcFormatWrapPreserveBlocks,
doxygenGenerateOnType: settings.doxygenGenerateOnType,
doxygenGenerateOnCodeAction: settings.doxygenGenerateOnCodeAction,
doxygenGeneratedStyle: settings.doxygenGeneratedCommentStyle,
doxygenSectionTags: settings.doxygenSectionTags,
filesExclude: otherSettings.filesExclude,
@@ -2944,8 +2893,6 @@ export class DefaultClient implements Client {
} else if (message.includes("/")) {
this.lastInvokedLspMessage = message;
}
this.resolvePendingIdleCallsIfReady();
}
private updateTagParseStatus(tagParseStatus: TagParseStatus): void {
@@ -4261,13 +4208,6 @@ export class DefaultClient implements Client {
}
public dispose(): void {
this.pendingIdleCalls.forEach(pendingCall => {
if (pendingCall.timer) {
clearTimeout(pendingCall.timer);
}
pendingCall.promise.resolve(false);
});
this.pendingIdleCalls = [];
this.disposables.forEach((d) => d.dispose());
this.disposables = [];
if (this.documentFormattingProviderDisposable) {
@@ -4420,7 +4360,6 @@ class NullClient implements Client {
setCurrentConfigName(configurationName: string): Thenable<void> { return Promise.resolve(); }
getCurrentConfigName(): Thenable<string> { return Promise.resolve(""); }
getCurrentConfigCustomVariable(variableName: string): Thenable<string> { return Promise.resolve(""); }
waitForIdle(timeout?: number): Promise<boolean> { return Promise.resolve(true); }
getVcpkgInstalled(): Thenable<boolean> { return Promise.resolve(false); }
getVcpkgEnabled(): Thenable<boolean> { return Promise.resolve(false); }
getCurrentCompilerPathAndArgs(): Thenable<util.CompilerPathAndArgs | undefined> { return Promise.resolve(undefined); }
+86 -12
View File
@@ -17,12 +17,15 @@ import { TargetPopulation } from 'vscode-tas-client';
import * as which from 'which';
import { logAndReturn } from '../Utility/Async/returns';
import * as util from '../common';
import { isWindows, modelSelector } from '../constants';
import { isWindows } from '../constants';
import { instrument } from '../instrumentation';
import { getCrashCallStacksChannel } from '../logger';
import { PlatformInformation } from '../platform';
import * as telemetry from '../telemetry';
import { CopilotHoverProvider } from './Providers/CopilotHoverProvider';
import { sendCallHierarchyCallsFromRequest, sendCallHierarchyCallsToRequest, sendPrepareCallHierarchyRequest } from './Providers/callHierarchyProvider';
import { sendFindAllReferencesRequest } from './Providers/findAllReferencesProvider';
import { sendGoToDefinitionRequest } from './Providers/goToDefinitionProvider';
import { Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client';
import { ClientCollection } from './clientCollection';
import { CodeActionDiagnosticInfo, CodeAnalysisDiagnosticIdentifiersAndUri, codeAnalysisAllFixes, codeAnalysisCodeToFixes, codeAnalysisFileToCodeActions } from './codeAnalysis';
@@ -272,7 +275,6 @@ export async function activate(): Promise<void> {
}
await registerRelatedFilesProvider();
await vscode.commands.executeCommand('setContext', 'cpptools.languageServerActivated', true);
}
export function updateLanguageConfigurations(): void {
@@ -398,6 +400,11 @@ export async function registerCommands(enabled: boolean): Promise<void> {
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.ShowActiveCodeAnalysisCommands', enabled ? onShowActiveCodeAnalysisCommands : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.ShowIdleCodeAnalysisCommands', enabled ? onShowIdleCodeAnalysisCommands : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.ShowReferencesProgress', enabled ? onShowReferencesProgress : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.FindAllReferences', enabled ? onFindAllReferences : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.GoToDefinition', enabled ? onGoToDefinition : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.PrepareCallHierarchy', enabled ? onPrepareCallHierarchy : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.CallHierarchyCallsTo', enabled ? onCallHierarchyCallsTo : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.CallHierarchyCallsFrom', enabled ? onCallHierarchyCallsFrom : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.TakeSurvey', enabled ? onTakeSurvey : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.LogDiagnostics', enabled ? onLogDiagnostics : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.RescanWorkspace', enabled ? onRescanWorkspace : onDisabledCommand));
@@ -422,7 +429,6 @@ export async function registerCommands(enabled: boolean): Promise<void> {
commandDisposables.push(vscode.commands.registerCommand('cpptools.activeConfigName', enabled ? onGetActiveConfigName : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('cpptools.activeConfigCustomVariable', enabled ? onGetActiveConfigCustomVariable : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('cpptools.setActiveConfigName', enabled ? onSetActiveConfigName : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.waitForIdle', enabled ? onWaitForIdle : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.RestartIntelliSenseForFile', enabled ? onRestartIntelliSenseForFile : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.GenerateDoxygenComment', enabled ? onGenerateDoxygenComment : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.CreateDeclarationOrDefinition', enabled ? onCreateDeclarationOrDefinition : onDisabledCommand));
@@ -810,6 +816,77 @@ function onShowReferencesProgress(): void {
void clients.ActiveClient.handleReferencesIcon().catch(logAndReturn.undefined);
}
async function onFindAllReferences(uri: vscode.Uri, position: vscode.Position, token?: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
if (!uri || !position) {
throw new Error("C_Cpp.FindAllReferences requires both a uri and position.");
}
const client: Client = clients.getClientFor(uri);
if (!(client instanceof DefaultClient)) {
return undefined;
}
await client.ready;
const result = await sendFindAllReferencesRequest(client, uri, position, token ?? CancellationToken.None);
return result?.locations;
}
async function onGoToDefinition(uri: vscode.Uri, position: vscode.Position, token?: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
if (!uri || !position) {
throw new Error("C_Cpp.GoToDefinition requires both a uri and position.");
}
const client: Client = clients.getClientFor(uri);
if (!(client instanceof DefaultClient)) {
return undefined;
}
await client.ready;
return sendGoToDefinitionRequest(client, uri, position, token ?? CancellationToken.None);
}
async function onPrepareCallHierarchy(uri: vscode.Uri, position: vscode.Position, token?: vscode.CancellationToken): Promise<vscode.CallHierarchyItem[] | undefined> {
if (!uri || !position) {
throw new Error("C_Cpp.PrepareCallHierarchy requires both a uri and position.");
}
const client: Client = clients.getClientFor(uri);
if (!(client instanceof DefaultClient)) {
return undefined;
}
await client.ready;
return sendPrepareCallHierarchyRequest(client, uri, position, token ?? CancellationToken.None);
}
async function onCallHierarchyCallsTo(item: vscode.CallHierarchyItem, token?: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
if (!item) {
throw new Error("C_Cpp.CallHierarchyCallsTo requires an item.");
}
const client: Client = clients.getClientFor(item.uri);
if (!(client instanceof DefaultClient)) {
return undefined;
}
await client.ready;
return sendCallHierarchyCallsToRequest(client, item, token ?? CancellationToken.None);
}
async function onCallHierarchyCallsFrom(item: vscode.CallHierarchyItem, token?: vscode.CancellationToken): Promise<vscode.CallHierarchyOutgoingCall[] | undefined> {
if (!item) {
throw new Error("C_Cpp.CallHierarchyCallsFrom requires an item.");
}
const client: Client = clients.getClientFor(item.uri);
if (!(client instanceof DefaultClient)) {
return undefined;
}
await client.ready;
return sendCallHierarchyCallsFromRequest(client, item, token ?? CancellationToken.None);
}
function onToggleRefGroupView(): void {
// Set context to switch icons
const client: Client = getActiveClient();
@@ -907,13 +984,6 @@ function onRescanWorkspace(): Promise<void> {
return clients.ActiveClient.rescanFolder();
}
async function onWaitForIdle(timeout?: number): Promise<boolean> {
const pending: Promise<boolean>[] = [];
clients.forEach(client => pending.push(client.waitForIdle(timeout)));
const results: boolean[] = await Promise.all(pending);
return results.every(result => result);
}
function onShowRefCommand(arg?: TreeNode): void {
if (!arg) {
return;
@@ -1480,8 +1550,12 @@ async function onCopilotHover(): Promise<void> {
let chatResponse: vscode.LanguageModelChatResponse | undefined;
try {
// Select the chat model.
const [model] = await vscodelm.selectChatModels(modelSelector);
// Select the chat model (refresh from cache).
const model = await copilotHoverProvider.refreshCachedChatModel();
if (!model) {
await reportCopilotFailure(copilotHoverProvider, hoverDocument, hoverPosition, "Copilot model not available.");
return;
}
chatResponse = await model.sendRequest(
messages,
+2
View File
@@ -126,6 +126,7 @@ export interface WorkspaceFolderSettingsParams {
vcFormatSpaceAroundTernaryOperator: string;
vcFormatWrapPreserveBlocks: string;
doxygenGenerateOnType: boolean;
doxygenGenerateOnCodeAction: boolean;
doxygenGeneratedStyle: string;
doxygenSectionTags: string[];
filesExclude: Excludes;
@@ -383,6 +384,7 @@ export class CppSettings extends Settings {
public get simplifyStructuredComments(): boolean { return this.getAsBoolean("simplifyStructuredComments"); }
public get doxygenGeneratedCommentStyle(): string { return this.getAsString("doxygen.generatedStyle"); }
public get doxygenGenerateOnType(): boolean { return this.getAsBoolean("doxygen.generateOnType"); }
public get doxygenGenerateOnCodeAction(): boolean { return this.getAsBoolean("doxygen.generateOnCodeAction"); }
public get commentContinuationPatterns(): (string | CommentPattern)[] {
const value: any = super.Section.get<any>("commentContinuationPatterns");
if (this.isArrayOfCommentContinuationPatterns(value)) {
+41 -3
View File
@@ -1549,7 +1549,6 @@ export function hasMsvcEnvironment(): boolean {
'INCLUDE',
'LIB',
'LIBPATH',
'UCRTVersion',
'UniversalCRTSdkDir',
'VCIDEInstallDir',
'VCINSTALLDIR',
@@ -1568,6 +1567,34 @@ export function hasMsvcEnvironment(): boolean {
);
}
export function getMissingMsvcEnvironmentVariables(): string[] {
const msvcEnvVars: string[] = [
'DevEnvDir',
'Framework40Version',
'FrameworkDir',
'FrameworkVersion',
'INCLUDE',
'LIB',
'LIBPATH',
'UCRTVersion',
'UniversalCRTSdkDir',
'VCIDEInstallDir',
'VCINSTALLDIR',
'VCToolsRedistDir',
'VisualStudioVersion',
'VSINSTALLDIR',
'WindowsLibPath',
'WindowsSdkBinPath',
'WindowsSdkDir',
'WindowsSDKLibVersion',
'WindowsSDKVersion'
];
return msvcEnvVars.filter(envVarName =>
(process.env[envVarName] === undefined || process.env[envVarName] === '') &&
extensionContext?.environmentVariableCollection?.get(envVarName) === undefined
);
}
function isIntegral(str: string): boolean {
const regex = /^-?\d+$/;
return regex.test(str);
@@ -1668,7 +1695,7 @@ export interface IQuotedString {
export type CommandString = string | IQuotedString;
export function buildShellCommandLine(originalCommand: CommandString, command: CommandString, args: CommandString[]): string {
export function buildShellCommandLine(originalCommand: CommandString, command: CommandString, args: CommandString[], singleCommandOnly: boolean = false): string {
let shellQuoteOptions: IShellQuotingOptions;
const isWindows: boolean = os.platform() === 'win32';
@@ -1782,7 +1809,7 @@ export function buildShellCommandLine(originalCommand: CommandString, command: C
let commandLine = result.join(' ');
// There are special rules quoted command line in cmd.exe
if (isWindows) {
if (isWindows && !singleCommandOnly) {
commandLine = `chcp 65001>nul && ${commandLine}`;
if (commandQuoted && argQuoted) {
commandLine = '"' + commandLine + '"';
@@ -1850,3 +1877,14 @@ export function getVSCodeLanguageModel(): any | undefined {
}
return vscodelm;
}
export function sessionIsWsl(): boolean {
if (process.env.WSL_DISTRO_NAME) {
return true;
}
try {
return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft');
} catch {
return false;
}
}
@@ -0,0 +1,21 @@
#include <fstream>
int main(int argc, char *argv[]) {
if (argc < 2) {
return 1;
}
std::ofstream resultFile(argv[1]);
if (!resultFile) {
return 2;
}
for (int i = 2; i < argc; ++i) {
resultFile << argv[i];
if (i + 1 < argc) {
resultFile << '\n';
}
}
return 0;
}
@@ -0,0 +1,11 @@
#include <fstream>
int main() {
std::ofstream resultFile("runWithoutDebuggingResult.txt");
if (!resultFile) {
return 1;
}
resultFile << 37;
return 0;
}
@@ -0,0 +1,72 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../../../../vscode.d.ts" />
import * as assert from 'assert';
import * as cp from 'child_process';
import * as vscode from 'vscode';
import * as util from '../../../../src/common';
import { isLinux, isMacOS, isWindows } from '../../../../src/constants';
import { getEffectiveEnvironment } from '../../../../src/LanguageServer/devcmd';
interface ProcessResult {
code: number | null;
stdout: string;
stderr: string;
}
function runProcess(command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<ProcessResult> {
return new Promise((resolve, reject) => {
const child = cp.spawn(command, args, { cwd, env });
let stdout = '';
let stderr = '';
child.stdout.on('data', (data: Buffer) => {
stdout += data.toString();
});
child.stderr.on('data', (data: Buffer) => {
stderr += data.toString();
});
child.on('error', reject);
child.on('close', (code) => resolve({ code, stdout, stderr }));
});
}
async function setWindowsBuildEnvironment(): Promise<void> {
const promise = vscode.commands.executeCommand('C_Cpp.SetVsDeveloperEnvironment', 'test');
const timer = setInterval(() => {
void vscode.commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
}, 1000);
await promise;
clearInterval(timer);
const missingVars = util.getMissingMsvcEnvironmentVariables();
assert.strictEqual(missingVars.length, 0, `MSVC environment missing: ${missingVars.join(', ')}`);
}
export async function compileProgram(workspacePath: string, sourcePath: string, outputPath: string): Promise<void> {
if (isWindows) {
await setWindowsBuildEnvironment();
const env = getEffectiveEnvironment();
const result = await runProcess('cl.exe', ['/nologo', '/EHsc', '/Zi', '/std:c++17', `/Fe:${outputPath}`, sourcePath], workspacePath, env);
assert.strictEqual(result.code, 0, `MSVC compilation failed. stdout: ${result.stdout}\nstderr: ${result.stderr}`);
return;
}
if (isMacOS) {
const result = await runProcess('clang++', ['-std=c++17', '-g', sourcePath, '-o', outputPath], workspacePath);
assert.strictEqual(result.code, 0, `clang++ compilation failed. stdout: ${result.stdout}\nstderr: ${result.stderr}`);
return;
}
if (isLinux) {
const result = await runProcess('g++', ['-std=c++17', '-g', sourcePath, '-o', outputPath], workspacePath);
assert.strictEqual(result.code, 0, `g++ compilation failed. stdout: ${result.stdout}\nstderr: ${result.stderr}`);
return;
}
assert.fail(`Unsupported test platform: ${process.platform}`);
}
@@ -0,0 +1,267 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../../../../vscode.d.ts" />
import * as assert from 'assert';
import { suite } from 'mocha';
import * as path from 'path';
import * as vscode from 'vscode';
import * as util from '../../../../src/common';
import { isMacOS, isWindows } from '../../../../src/constants';
import { compileProgram } from './compileProgram';
interface TrackerState {
setBreakpointsRequestReceived: boolean;
stoppedEventReceived: boolean;
exitedEventReceived: boolean;
exitedBeforeStop: boolean;
}
interface TrackerController {
state: TrackerState;
lastEvent: Promise<'stopped' | 'exited'>;
dispose(): void;
}
async function createBreakpointAtResultWriteStatement(sourceUri: vscode.Uri): Promise<vscode.SourceBreakpoint> {
const document = await vscode.workspace.openTextDocument(sourceUri);
const resultWriteLine = document.getText().split(/\r?\n/).findIndex((line) => line.includes('resultFile << 37;'));
assert.notStrictEqual(resultWriteLine, -1, 'Unable to find expected result-write statement for breakpoint placement.');
const breakpoint = new vscode.SourceBreakpoint(new vscode.Location(sourceUri, new vscode.Position(resultWriteLine, 0)), true);
vscode.debug.addBreakpoints([breakpoint]);
return breakpoint;
}
function createSessionTerminatedPromise(sessionName: string): Promise<void> {
return new Promise<void>((resolve) => {
const terminateSubscription = vscode.debug.onDidTerminateDebugSession((session) => {
if (session.name === sessionName) {
terminateSubscription.dispose();
resolve();
}
});
});
}
function createTracker(debugType: string, sessionName: string, timeoutMs: number, timeoutMessage: string): TrackerController {
const state: TrackerState = {
setBreakpointsRequestReceived: false,
stoppedEventReceived: false,
exitedEventReceived: false,
exitedBeforeStop: false
};
let trackerRegistration: vscode.Disposable | undefined;
let timeoutHandle: NodeJS.Timeout | undefined;
const lastEvent = new Promise<'stopped' | 'exited'>((resolve, reject) => {
timeoutHandle = setTimeout(() => {
trackerRegistration?.dispose();
trackerRegistration = undefined;
reject(new Error(timeoutMessage));
}, timeoutMs);
trackerRegistration = vscode.debug.registerDebugAdapterTrackerFactory(debugType, {
createDebugAdapterTracker: (session: vscode.DebugSession): vscode.DebugAdapterTracker | undefined => {
if (session.name !== sessionName) {
return undefined;
}
return {
onWillReceiveMessage: (message: any): void => {
if (message?.type === 'request' && message?.command === 'setBreakpoints') {
state.setBreakpointsRequestReceived = true;
}
},
onDidSendMessage: (message: any): void => {
if (message?.type !== 'event') {
return;
}
if (message.event === 'stopped') {
state.stoppedEventReceived = true;
if (timeoutHandle) {
clearTimeout(timeoutHandle);
timeoutHandle = undefined;
}
resolve('stopped');
}
if ((message.event === 'terminated' || message.event === 'exited') && !state.exitedEventReceived) {
state.exitedEventReceived = true;
if (!state.stoppedEventReceived) {
state.exitedBeforeStop = true;
}
if (timeoutHandle) {
clearTimeout(timeoutHandle);
timeoutHandle = undefined;
}
resolve('exited');
}
}
};
}
});
});
return {
state,
lastEvent,
dispose(): void {
if (timeoutHandle) {
clearTimeout(timeoutHandle);
timeoutHandle = undefined;
}
trackerRegistration?.dispose();
trackerRegistration = undefined;
}
};
}
async function waitForResultFileValue(filePath: string, timeoutMs: number): Promise<number> {
const deadline = Date.now() + timeoutMs;
let lastContents = '';
while (Date.now() < deadline) {
try {
lastContents = await util.readFileText(filePath, 'utf8');
const trimmedContents = lastContents.trim();
if (trimmedContents.length > 0) {
const value = Number.parseInt(trimmedContents, 10);
if (!Number.isNaN(value)) {
return value;
}
}
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
throw error;
}
}
await new Promise<void>(resolve => setTimeout(resolve, 100));
}
assert.fail(`Timed out waiting for numeric result in ${filePath}. Last contents: ${lastContents}`);
}
suite('Run Without Debugging Test', function (): void {
const expectedResultValue = 37;
const workspaceFolder = vscode.workspace.workspaceFolders?.[0] ?? assert.fail('No workspace folder available');
const workspacePath = workspaceFolder.uri.fsPath;
const sourceFile = path.join(workspacePath, 'debugTest.cpp');
const sourceUri = vscode.Uri.file(sourceFile);
const resultFilePath = path.join(workspacePath, 'runWithoutDebuggingResult.txt');
const executableName = isWindows ? 'debugTestProgram.exe' : 'debugTestProgram';
const executablePath = path.join(workspacePath, executableName);
const sessionName = 'Run Without Debugging Result File';
const debugType = isWindows ? 'cppvsdbg' : 'cppdbg';
const miMode = isMacOS ? 'lldb' : 'gdb';
suiteSetup(async function (): Promise<void> {
const extension: vscode.Extension<any> = vscode.extensions.getExtension('ms-vscode.cpptools') || assert.fail('Extension not found');
if (!extension.isActive) {
await extension.activate();
}
await compileProgram(workspacePath, sourceFile, executablePath);
});
suiteTeardown(async function (): Promise<void> {
if (isWindows) {
await vscode.commands.executeCommand('C_Cpp.ClearVsDeveloperEnvironment');
}
});
setup(async function (): Promise<void> {
await util.deleteFile(resultFilePath);
});
test('Run Without Debugging should not break on breakpoints and write the expected result file', async () => {
const breakpoint = await createBreakpointAtResultWriteStatement(sourceUri);
const tracker = createTracker(debugType, sessionName, 30000, 'Timed out waiting for debugger event.');
const debugSessionTerminated = createSessionTerminatedPromise(sessionName);
try {
const started = await vscode.debug.startDebugging(
workspaceFolder,
{
name: sessionName,
type: debugType,
request: 'launch',
program: executablePath,
args: [],
cwd: workspacePath,
externalConsole: debugType === 'cppdbg' ? false : undefined,
console: debugType === 'cppvsdbg' ? 'internalConsole' : undefined
},
{ noDebug: true });
assert.strictEqual(started, true, 'The noDebug launch did not start successfully.');
const lastEvent = await tracker.lastEvent;
await debugSessionTerminated;
const actualResultValue = await waitForResultFileValue(resultFilePath, 10000);
assert.strictEqual(lastEvent, 'exited', 'No-debug launch should exit rather than stop on a breakpoint.');
assert.strictEqual(tracker.state.setBreakpointsRequestReceived, false, 'a "no debug" session should not send setBreakpoints requests.');
assert.strictEqual(tracker.state.stoppedEventReceived, false, 'a "no debug" session should not emit stopped events.');
assert.strictEqual(actualResultValue, expectedResultValue, 'Unexpected result value from run without debugging launch.');
} finally {
tracker.dispose();
vscode.debug.removeBreakpoints([breakpoint]);
await util.deleteFile(resultFilePath);
}
});
test('Debug launch should bind and stop at the breakpoint', async () => {
const breakpoint = await createBreakpointAtResultWriteStatement(sourceUri);
const tracker = createTracker(debugType, sessionName, 30000, 'Timed out waiting for debugger event in normal debug mode.');
const debugSessionTerminated = createSessionTerminatedPromise(sessionName);
let launchedSession: vscode.DebugSession | undefined;
const startedSubscription = vscode.debug.onDidStartDebugSession((session) => {
if (session.name === sessionName) {
launchedSession = session;
}
});
try {
const started = await vscode.debug.startDebugging(
workspaceFolder,
{
name: sessionName,
type: debugType,
request: 'launch',
program: executablePath,
args: [],
cwd: workspacePath,
MIMode: debugType === 'cppdbg' ? miMode : undefined,
externalConsole: debugType === 'cppdbg' ? false : undefined,
console: debugType === 'cppvsdbg' ? 'internalConsole' : undefined
},
{ noDebug: false });
assert.strictEqual(started, true, 'The debug launch did not start successfully.');
const lastEvent = await tracker.lastEvent;
assert.strictEqual(lastEvent, 'stopped', 'Debug launch should stop at the breakpoint before exit.');
assert.strictEqual(tracker.state.setBreakpointsRequestReceived, true, 'Debug mode should send setBreakpoints requests.');
assert.strictEqual(tracker.state.stoppedEventReceived, true, 'Debug mode should emit a stopped event at the breakpoint.');
assert.strictEqual(tracker.state.exitedBeforeStop, false, 'Program exited before stopping at breakpoint in debug mode.');
assert.strictEqual(vscode.debug.activeDebugSession?.name, sessionName, 'Debug session should still be active at breakpoint.');
const stoppedSession = launchedSession ?? vscode.debug.activeDebugSession;
assert.ok(stoppedSession, 'Unable to identify the running debug session for termination.');
await vscode.debug.stopDebugging(stoppedSession);
await debugSessionTerminated;
} finally {
startedSubscription.dispose();
tracker.dispose();
vscode.debug.removeBreakpoints([breakpoint]);
await util.deleteFile(resultFilePath);
}
});
});
@@ -0,0 +1,190 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../../../../vscode.d.ts" />
import * as assert from 'assert';
import { suite } from 'mocha';
import * as path from 'path';
import * as vscode from 'vscode';
import * as util from '../../../../src/common';
import { isWindows } from '../../../../src/constants';
import { compileProgram } from './compileProgram';
type ConsoleMode = 'integratedTerminal' | 'externalTerminal';
type WindowsTerminalProfile = 'Command Prompt' | 'PowerShell';
/**
* Waits for the output of a program to be written to a file and returns the lines of output.
* @param filePath The path to the file containing the program output.
* @param timeoutMs The maximum time to wait for the output, in milliseconds.
* @returns A promise that resolves to an array of output lines.
* @throws An error if the output is not available within the specified timeout.
*/
async function waitForOutput(filePath: string, timeoutMs: number): Promise<string[]> {
const deadline = Date.now() + timeoutMs;
let lastContents = '';
while (Date.now() < deadline) {
try {
lastContents = await util.readFileText(filePath, 'utf8');
const trimmedContents = lastContents.trimEnd();
if (trimmedContents.length > 0) {
return trimmedContents.split(/\r?\n/);
}
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
throw error;
}
}
await new Promise<void>(resolve => setTimeout(resolve, 100));
}
assert.fail(`Timed out waiting for argument output in ${filePath}. Last contents: ${lastContents}`);
}
/**
* Disposes of any terminals whose names match the given program paths. These are the terminals that were created to run the specified programs.
* @param programs An array of program paths whose corresponding terminals should be disposed.
*/
function disposeTerminals(programs: string[]): void {
const terminalNames = new Set(programs.map(program => path.normalize(program)));
for (const terminal of vscode.window.terminals) {
if (terminalNames.has(terminal.name)) {
terminal.dispose();
}
}
}
/**
* Sets or clears the setting for the default Windows terminal profile.
* @param profile The terminal profile to set as the default, or undefined to clear the setting.
*/
async function setWindowsDefaultTerminalProfile(profile?: WindowsTerminalProfile): Promise<void> {
if (!isWindows) {
return;
}
const config = vscode.workspace.getConfiguration('terminal.integrated');
await config.update('defaultProfile.windows', profile, vscode.ConfigurationTarget.Workspace);
}
async function runNoDebugLaunch(workspaceFolder: vscode.WorkspaceFolder, sessionName: string, program: string, consoleMode: ConsoleMode, resultFilePath: string, args: string[]): Promise<string[]> {
const debugType = isWindows ? 'cppvsdbg' : 'cppdbg';
const launchConfig: vscode.DebugConfiguration = {
name: sessionName,
type: debugType,
request: 'launch',
program: program,
args: [resultFilePath, ...args],
cwd: workspaceFolder.uri.fsPath
};
if (debugType === 'cppvsdbg') {
launchConfig.console = consoleMode;
} else {
launchConfig.externalConsole = consoleMode === 'externalTerminal';
}
const started = await vscode.debug.startDebugging(workspaceFolder, launchConfig, { noDebug: true });
assert.strictEqual(started, true, `The ${consoleMode} noDebug launch did not start successfully.`);
return waitForOutput(resultFilePath, 15000);
}
suite('Run Without Debugging Terminal and Arguments Test', function (this: Mocha.Suite): void {
this.timeout(120000);
const workspaceFolder = vscode.workspace.workspaceFolders?.[0] ?? assert.fail('No workspace folder available');
const workspacePath = workspaceFolder.uri.fsPath;
const sourceFile = path.join(workspacePath, 'argsTest.cpp');
const resultFilePath = path.join(workspacePath, 'test_output.txt');
const executablePath = path.join(workspacePath, isWindows ? 'argsTestProgram.exe' : 'argsTestProgram');
const spacedExecutablePath = path.join(workspacePath, isWindows ? 'args Test Program.exe' : 'args Test Program');
const executablePaths = [executablePath, spacedExecutablePath];
const expectedArgs = [
'alpha',
'two words',
path.join(workspacePath, 'input folder', 'three words.txt')
];
suiteSetup(async function (): Promise<void> {
const extension: vscode.Extension<any> = vscode.extensions.getExtension('ms-vscode.cpptools') || assert.fail('Extension not found');
if (!extension.isActive) {
await extension.activate();
}
await compileProgram(workspacePath, sourceFile, executablePath);
await compileProgram(workspacePath, sourceFile, spacedExecutablePath);
});
teardown(async function (): Promise<void> {
await util.deleteFile(resultFilePath);
disposeTerminals(executablePaths);
});
setup(async function (): Promise<void> {
if (await util.checkFileExists(resultFilePath)) {
await util.deleteFile(resultFilePath);
}
});
suiteTeardown(async function (): Promise<void> {
await util.deleteFile(resultFilePath);
disposeTerminals(executablePaths);
if (isWindows) {
await vscode.commands.executeCommand('C_Cpp.ClearVsDeveloperEnvironment');
await util.deleteFile(path.join(workspacePath, '.vscode', 'settings.json'));
}
});
const consoleCases: { label: string; consoleMode: ConsoleMode; windowsProfiles?: (WindowsTerminalProfile | undefined)[] }[] = [
{
label: 'integrated terminal',
consoleMode: 'integratedTerminal',
windowsProfiles: [undefined, 'Command Prompt', 'PowerShell']
},
{
label: 'external terminal',
consoleMode: 'externalTerminal'
}
];
const programCases = [
{
label: 'a program name without spaces',
programPath: executablePath
},
{
label: 'a program name with spaces',
programPath: spacedExecutablePath
}
];
for (const consoleCase of consoleCases) {
for (const programCase of programCases) {
const profiles: (WindowsTerminalProfile | undefined)[] = isWindows && consoleCase.consoleMode === 'integratedTerminal' ? consoleCase.windowsProfiles ?? [undefined] : [undefined];
for (const profile of profiles) {
const profileSuffix = profile ? ` with ${profile} as the default terminal` : consoleCase.consoleMode === 'integratedTerminal' ? ' with default terminal' : '';
test(`No-debug launch via ${consoleCase.label} handles ${programCase.label}${profileSuffix}`, async () => {
await setWindowsDefaultTerminalProfile(profile);
disposeTerminals(executablePaths);
const sessionName = `Run Without Debugging Args (${consoleCase.consoleMode}, ${path.basename(programCase.programPath)}${profile ? `, ${profile}` : ''})`;
const actualArgs = await runNoDebugLaunch(
workspaceFolder,
sessionName,
programCase.programPath,
consoleCase.consoleMode,
resultFilePath,
expectedArgs);
assert.deepStrictEqual(actualArgs, expectedArgs, `Unexpected arguments received for ${consoleCase.label} using ${programCase.label}${profileSuffix}.`);
});
}
}
}
});
@@ -1,9 +1,8 @@
<h1 data-loc-id="walkthrough.windows.install.compiler">Install a C++ compiler on Windows</h1>
<p data-loc-id="walkthrough.windows.text1">If you&#39;re doing C++ development for Windows, we recommend installing the Microsoft Visual C++ (MSVC) compiler.</p>
<ol>
<li><p data-loc-id="walkthrough.windows.text2">To install MSVC, open the VS Code terminal (CTRL + `) and paste in the following command:
<pre><code style="white-space: pre-wrap;">winget install Microsoft.VisualStudio.2022.BuildTools --force --override "--wait --passive --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows10SDK.20348"</code></pre>
</li>
<li><p data-loc-id="walkthrough.windows.text2">To install MSVC, open the VS Code terminal (CTRL + `) and paste in the following command:</p>
<p><code>winget install Microsoft.<wbr>VisualStudio.<wbr>2022.<wbr>BuildTools --force --override "--wait --passive --add Microsoft.<wbr>VisualStudio.<wbr>Workload.<wbr>VCTools --add Microsoft.<wbr>VisualStudio.<wbr>Component.<wbr>VC.<wbr>Tools.<wbr>x86.<wbr>x64 --add Microsoft.<wbr>VisualStudio.<wbr>Component.<wbr>Windows10SDK.<wbr>19041"</code></p>
<blockquote>
<p><strong data-loc-id="walkthrough.windows.note1">Note</strong>: <span data-loc-id="walkthrough.windows.note1.text">You can use the C++ toolset from Visual Studio Build Tools along with Visual Studio Code to compile, build, and verify any C++ codebase as long as you also have a valid Visual Studio license (either Community, Pro, or Enterprise) that you are actively using to develop that C++ codebase.</span></p>
</blockquote>
@@ -1,9 +1,8 @@
<h1 data-loc-id="walkthrough.windows.install.compiler">Install a C++ compiler on Windows</h1>
<p data-loc-id="walkthrough.windows.text1">If you&#39;re doing C++ development for Windows, we recommend installing the Microsoft Visual C++ (MSVC) compiler.</p>
<ol>
<li><p data-loc-id="walkthrough.windows.text2">To install MSVC, open the VS Code terminal (CTRL + `) and paste in the following command:
<pre><code style="white-space: pre-wrap;">winget install Microsoft.VisualStudio.2022.BuildTools --force --override "--wait --passive --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100"</code></pre>
</li>
<li><p data-loc-id="walkthrough.windows.text2">To install MSVC, open the VS Code terminal (CTRL + `) and paste in the following command:</p>
<p><code>winget install Microsoft.<wbr>VisualStudio.<wbr>2022.<wbr>BuildTools --force --override "--wait --passive --add Microsoft.<wbr>VisualStudio.<wbr>Workload.<wbr>VCTools --add Microsoft.<wbr>VisualStudio.<wbr>Component.<wbr>VC.<wbr>Tools.<wbr>x86.<wbr>x64 --add Microsoft.<wbr>VisualStudio.<wbr>Component.<wbr>Windows11SDK.<wbr>26100"</code></p>
<blockquote>
<p><strong data-loc-id="walkthrough.windows.note1">Note</strong>: <span data-loc-id="walkthrough.windows.note1.text">You can use the C++ toolset from Visual Studio Build Tools along with Visual Studio Code to compile, build, and verify any C++ codebase as long as you also have a valid Visual Studio license (either Community, Pro, or Enterprise) that you are actively using to develop that C++ codebase.</span></p>
</blockquote>
+3 -1
View File
@@ -1,2 +1,4 @@
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
always-auth=true
always-auth=true
# Disable postinstall scripts for supply chain security. Allowlist exceptions with npm trust: https://docs.npmjs.com/cli/v11/commands/npm-trust
ignore-scripts=true
+3 -1
View File
@@ -1,2 +1,4 @@
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
always-auth=true
always-auth=true
# Disable postinstall scripts for supply chain security. Allowlist exceptions with npm trust: https://docs.npmjs.com/cli/v11/commands/npm-trust
ignore-scripts=true