Compare commits

...
175 Commits
Author SHA1 Message Date
Sean McManus 88a0494ce5 Merge pull request #1766 from Microsoft/master
Merge for 0.16.1 release
2018-03-30 17:08:02 -07:00
Sean McManus b32debdb76 Update package-lock.json version. (#1765) 2018-03-30 16:27:55 -07:00
Sean McManus 480af0c155 Dev/seanmcm/0 16 1 update (#1762)
* Update for 0.16.1.
2018-03-30 15:45:36 -07:00
Andrew Wang b65a89733c Adding file validation for download and unzip. (#1751)
* Adding file validation for download and unzip.

Refactored the download retry code.

Added error handlers for read and write streams.

WriteStream writes to a *.tmp file and then renames. This catches the
case if VSCode dies in the middle of this process and the file is
partially written. We will continue where we left off.

* Adding return to resolve/reject calls.

* Fix retry loop and check err in unlink and rename

* Actually wait for those promises

* Fix TSLint error
2018-03-28 15:58:08 -07:00
Bob Brown 3bbfed643f Merge pull request #1746 from Microsoft/master
Merge to release 0.16.0
2018-03-27 20:36:40 -07:00
Sean McManus 638fd678dc Update changelog date. (#1745) 2018-03-27 20:34:35 -07:00
Sean McManus ff5d363926 Don't set the compilerPath if the default is empty. (#1741)
* Don't set the compilerPath if the default is empty or compile commands is set.
* Guard against empty std.
2018-03-27 18:43:07 -07:00
Andrew Wang e0bb796423 Boolean default types should be boolean not string (#1732) 2018-03-23 13:27:59 -07:00
Bob Brown d079892710 Merge pull request #1726 from Microsoft/master
Merge to release for 0.16.0
2018-03-22 12:23:03 -07:00
Sean McManus 56fd1e7076 Update changelog. (#1721)
* Update changelog.

* Minor edit.

* Forgot a bug fix.

* Add debugger bug.
2018-03-22 07:50:58 -07:00
Andrew Wang 1699ec02cd Adding -c flag to WSL configurations (#1722)
Missing the -c flag for bash.exe
2018-03-21 19:18:53 -07:00
Shubham Bhattar 97a635bf2d "taskName" changed to "label" as per version 2.0.0 (#1713)
Reference Link: https://code.visualstudio.com/docs/editor/tasks#_migrating-to-tasks-200
2018-03-21 12:44:47 -07:00
Bob Brown f5a2192235 update documentation (#1710) 2018-03-20 17:14:56 -07:00
Bob Brown 5d85eae737 Database icon is not using the theme color (#1638) (#1711) 2018-03-20 17:14:04 -07:00
Sean McManus 4fe2ec1bfe Dev/seanmcm/fix blank config with file watcher limit (#1709)
Fix blank config in the status bar (and browse engine stuck initializing) when the file watcher limit is hit.
2018-03-20 16:14:27 -07:00
Bob Brown 83a9cb2b02 anticipating release (#1703) 2018-03-19 15:58:57 -07:00
Bob Brown 905041068f More guards against crashes in configuration processing (#1702) 2018-03-19 15:58:25 -07:00
Sean McManus c68ad37d98 Seanmcm/change compiler path comments (#1688)
* Modify compilerPath description.

* Modification.
2018-03-15 13:04:29 -07:00
Bob Brown f857bc45c3 deal with error cases in configurations (#1687) 2018-03-14 13:28:48 -07:00
Bob Brown 1177ab5cee don't repeatedly mark the c_cpp_properties.json file as dirty on Windows (#1653) 2018-03-08 15:16:19 -08:00
Sean McManus 17d19a93e0 Fix bug with compilerPath/cppVersion. (#1650) 2018-03-07 20:32:28 -08:00
Sean McManus 5fb96a6d02 Fix launch.json and activation stuck on cpptools.json downloading. (#1649)
* Fix launch.json and activation stuck on cpptools.json downloading.
2018-03-07 17:45:11 -08:00
Bob Brown 5e88dbfd79 Merge branch 'insiders' into master 2018-03-07 15:28:50 -08:00
Griffin Downs 35e002756e Check whether propertiesFile is null before accessing (#1647)
Travis looks like it's stalled. I'm going to force this in so we can build an insiders package.
2018-03-07 12:54:33 -08:00
Bob Brown 70cff29645 replace workspaceRoot with workspaceFolder (#1641)
* replace workspaceRoot with workspaceFolder (actual support is on the server side)
* update changelog
2018-03-06 08:35:03 -08:00
Sean McManus bd181c3b8f add compilerPath, cStandard, and cppStandard settings, fix inactive region deletion bug (#1549)
* Add compilerPath setting.
* Add code to query the default compiler.
* Add cStandard and cppStandard settings.
* Fix bug with inactive region deletion.
2018-03-02 16:29:27 -08:00
Bob Brown 00f70aed7c add support for force includes in c_cpp_properties.json (#1630) 2018-03-02 15:11:00 -08:00
Bob Brown bea033ef67 TypeScript compile needs to happen as part of prepublish step. (#1629) 2018-03-01 10:46:27 -08:00
Pierson Lee b05e8c5627 Correct Fix to make sure debugger dependencies are copied (#1621)
* Correct Fix to make sure debugger dependencies are copied

Fix double compile and make sure that it is only run once.

* Fix log

* Andrew requested outDir
2018-02-28 14:32:26 -08:00
Pierson Lee 523e8c9c26 Fixing misisng compile step before executing .js file (#1618) 2018-02-27 17:04:36 -08:00
Andrew Wang 6ad4814173 copySourceDependencies needs to be run every time (#1617)
This fixes the nightly builds
2018-02-27 15:58:20 -08:00
Bob Brown 6756be66d5 update c_cpp_properties.json documentation to version 3 (#1615) 2018-02-27 13:29:40 -08:00
Bob Brown a6c6c7e691 Add a setting to manage inactive region colorization (#1604) 2018-02-26 15:56:44 -08:00
Bob Brown 9937753e3a Add setting to enable multiline comment customizations (#1583)
* Work in progress.  Wrote framework for comment pattern handling.  Implementation incomplete and some bugs remain.

* address TODOs

* incorrect disposal

* incorrect type decorations

* WIP: update changelog, add a test

* test updates

* rename the setting, update package.json and add more tests

* deal with whitespace continuations

* address PR feedback
2018-02-21 13:35:51 -08:00
Andrew Wang 03cc6b26ec Adding setupCommands to attach configuraitons (#1593)
Addressing #1581
2018-02-20 17:11:29 -08:00
Hogyun Yu  (aka Philographer) 8cb05ed0cb Update ReleaseNotes.html (#1572) 2018-02-16 08:59:48 -08:00
Bob Brown d5fb6a1d15 faster launch times for extension debugging (#1555)
* add a way to speed up subsequent launches of the extension.

* A cleaner way to exit

* update package.json

* read the environment variable to short-circuit the node_modules check.
2018-02-15 12:44:05 -08:00
Sean McManus e5976d2656 Merge pull request #1557 from Microsoft/master
Merge for release.
2018-02-14 16:55:56 -08:00
Bob Brown e70f625212 release notes (#1566) 2018-02-14 16:42:48 -08:00
Bob Brown 625e5478be define __CHAR_BIT__ for Mac (#1564)
* define `__CHAR_BIT__` for Mac
* update changelog
2018-02-14 12:49:44 -08:00
Sean McManus e825292931 Update changelog. (#1556)
* Update changelog.
2018-02-13 17:29:36 -08:00
Charles Milette 2fcd4b4943 Add _UNICODE to default defines on Windows (#1540)
* Add _UNICODE to default defines on Windows
Fixes #1538
2018-02-08 17:42:22 -08:00
ronglums f5b2d30182 Moved the extension building instructions into a separate file. (#1537)
Moved the extension building instructions into a separate file.
2018-02-08 12:02:32 -08:00
Joshua Cannon d5af9a1b45 Adding configuration variable replacement in c_cpp_properties.json. (#1529)
* Adding configuration variable replacement in c_cpp_properties.json. #314

* Fixing issues brought up by linter
2018-02-07 10:35:31 -08:00
Faheel Ahmad e6d8d1fb28 Improve documentation (#1515)
* improve Markdown formatting
* use consistent formatting rules for all Markdown files
* fix typos
* fix broken links
2018-02-07 08:04:18 -08:00
Sean McManus 536182cf1f Change for insiders. 2018-02-01 12:58:43 -08:00
Bob Brown 7a39edaf65 Fix crash in client module (#1506)
Temporary key name was lost outside of the switch block, resulting in an attempt to access .length of 'undefined'
2018-01-31 14:29:16 -08:00
Griffin Downs fd7b691885 Inactive region highlight (#1505)
* Add intermediary type to safely construct vscode.Ranges for use

* Fix incorrect object definition

* Fix file empty edge case; refactor + comment out code while testing

* Use InputRegions (lines only); Remove commented out code

* Commenting

* Fix linter error from merge with master
2018-01-31 14:02:01 -08:00
Sean McManus 42ddf188f3 Fix for https://github.com/Microsoft/vscode-extension-telemetry/issues/7 (#1499)
* Fix for https://github.com/Microsoft/vscode-extension-telemetry/issues/7 .
* Filter out settings values that don't match enum values.
2018-01-29 17:24:08 -08:00
Sean McManus 3512cb370b Seanmcm/telemetry fix (#1494)
* Fix telemetry.
2018-01-29 12:56:43 -08:00
Andrew Wang aa0f613dfb Force semicolon in object literal (#1493) 2018-01-26 11:01:44 -08:00
Griffin Downs b68d1e173e Add intermediary type to safely construct vscode.Ranges for use (#1492)
* Add intermediary type to safely construct vscode.Ranges for use

* Fix incorrect object definition
2018-01-25 16:46:24 -08:00
Sean McManus 58e403d9e0 Merge pull request #1490 from Microsoft/seanmcm/update0_15_0
Update stuff for 0.15.0 in preparation for the insider release.
2018-01-25 15:52:14 -08:00
Sean McManus d46c0594b5 Merge branch 'seanmcm/update0_15_0' of https://github.com/Microsoft/vscode-cpptools into seanmcm/update0_15_0 2018-01-25 14:35:19 -08:00
Sean McManus 44f65f2e14 Merge. 2018-01-25 14:35:01 -08:00
Bob Brown fca11d63c4 Merge branch 'master' into seanmcm/update0_15_0 2018-01-25 14:33:44 -08:00
grdowns 572f21a7e2 Merge pull request #1482 from Microsoft/inactive-region-highlight
Inactive region highlight
2018-01-25 14:31:09 -08:00
Sean McManus c2c84aaf7f Change date to 14th. 2018-01-25 14:13:46 -08:00
Griffin Downs 0eae7fd7a3 Rename method; Re-word commenting 2018-01-25 14:11:22 -08:00
Sean McManus ca777a2172 Change date. 2018-01-25 13:12:51 -08:00
Sean McManus c57da0d645 Change error limit to 25000. 2018-01-25 12:27:51 -08:00
Griffin Downs dd2ca57532 Compare each range by value instead of by reference 2018-01-25 11:52:43 -08:00
Griffin Downs f614c75ab6 Fix no return error 2018-01-25 11:05:42 -08:00
Griffin Downs be1bae2321 *Correctly* use guard 2018-01-25 10:37:25 -08:00
Griffin Downs 0af3069091 Guard against decorations being set on update but without changes 2018-01-25 10:26:30 -08:00
Sean McManus 8e86dd333a Update stuff for 0.15.0. 2018-01-24 19:47:17 -08:00
Griffin Downs 31a53bd95f Merge branch 'inactive-region-highlight' of https://github.com/Microsoft/vscode-cpptools into inactive-region-highlight 2018-01-24 14:27:02 -08:00
Griffin Downs 4d0490edf7 Merge branch 'master' of https://github.com/Microsoft/vscode-cpptools into inactive-region-highlight 2018-01-24 14:25:52 -08:00
Griffin Downs 02dc3fecda Express conditional more idiomatically 2018-01-24 14:25:20 -08:00
Griffin Downs 84fd6a21eb Uncomment guard block; Move comment 2018-01-24 14:11:55 -08:00
Griffin Downs b1c332ba34 Move interface + capitalize 2018-01-24 13:57:09 -08:00
grdowns 1e8ea4a656 Merge branch 'master' into inactive-region-highlight 2018-01-24 13:54:44 -08:00
Bob Brown 510094a71d fix a bug in resolveVariables util function (#1488) 2018-01-24 13:54:17 -08:00
Griffin Downs 6f9a8e10a8 Modify light theme coloration; Add decorationRangePair interface; Guard against undefined return value 2018-01-24 13:45:56 -08:00
Griffin Downs 4ab47bd2c9 Var rename for consistence + commenting 2018-01-24 10:23:16 -08:00
Griffin Downs 1ccc670265 Wording on comment 2018-01-24 10:08:35 -08:00
Griffin Downs e4634395c3 Refactor updateInactiveRegions + comment 2018-01-24 10:04:25 -08:00
Griffin Downs 3c012719c6 Use Map to track text editors and apply decorations as they become visible 2018-01-24 09:41:10 -08:00
Griffin Downs 74f567db16 Rename and move decoration object 2018-01-23 14:14:20 -08:00
Griffin Downs d444874f0d Remove auto-generated files/changes; Properly set text decorations 2018-01-23 13:38:44 -08:00
Griffin Downs 762de3ff28 Merge branch 'master' of https://github.com/Microsoft/vscode-cpptools into inactive-region-highlight 2018-01-22 17:03:38 -08:00
Griffin Downs 24c4f7f8c3 Add TODO 2018-01-22 15:59:25 -08:00
Griffin Downs 0622ade175 Fix deprecated launch.json; Add auto-generated files 2018-01-22 15:58:13 -08:00
Andrew Wang ecd1b06bef Adding triple-equals to tslint (#1480)
https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true
2018-01-22 11:12:45 -08:00
jogo- dfec64f233 Fix typos in CHANGELOG.md (#1478) 2018-01-22 08:51:36 -08:00
Griffin Downs 0bdd303978 Add notification for inactive regions; Respond by changing text color 2018-01-19 16:15:46 -08:00
Bob Brown 6c21e5445b Create CODE_OF_CONDUCT.md 2018-01-19 08:47:11 -08:00
Seokhwan Song 02201d3961 fix wrong URL (msvscode -> vscode) (#1470) 2018-01-19 08:12:46 -08:00
Pierson Lee (PIE) cdab065ded Merge remote-tracking branch 'origin/master' into release 2018-01-17 13:09:00 -08:00
Andrew Wang be11d40e4e Fix rename error and its message and linux build (#1462)
* Fix rename error and its message and linux build

Rename was always outputting an error message since the callback is
always called. Included and error check. For offline install, if
opendebug.exe.config exists, rename needs to happen too. Added function
call for offline installation.

'use strict' was erroring on ubuntu build in copyScript.ts
2018-01-17 13:02:42 -08:00
Sean McManus 3f62c3d244 Merge pull request #1458 from Microsoft/master
0.14.6 release
2018-01-16 15:51:11 -08:00
Bob Brown 5c8fdabe74 rename files.associations.autoAdd setting (#1452) 2018-01-16 14:36:53 -08:00
Sean McManus 2f10eb8fd0 Add CONTRIBUTING.md. (#1456) 2018-01-16 14:33:02 -08:00
Sean McManus 2847a96622 Rename LICENSE.txt. (#1457) 2018-01-16 14:32:37 -08:00
Sean McManus 69282d25e0 Modify changelog. (#1455) 2018-01-16 14:32:05 -08:00
Bob Brown 9ea384fc23 update comment for workspaceParsingPriority setting (#1454) 2018-01-16 13:00:08 -08:00
Bob Brown ca13ab99c9 update release notes for January 2018 (#1451) 2018-01-16 12:59:28 -08:00
Andrew Wang 20e4dd1aa8 Enable support for Integration Tests (#1441)
* Enable support for Integration Tests

Added Logger to help tests retrieve output from the installation of the
extension.
2018-01-12 16:55:01 -08:00
Bob Brown c9ca99423f Merge pull request #1438 from vitosamson/doc-img-links
fix image links in Getting Started docs
2018-01-11 16:59:00 -08:00
Vito 476b5791cc fix image links in Getting Started docs 2018-01-11 18:47:10 -05:00
Andrew Wang 62eb613f12 Fix activating language server for 2nd launch (#1435)
* Fix activating language server for 2nd launch

* Moving check distro to run only on install

Fix function name for getTempRegistrarInstance
2018-01-11 12:37:51 -08:00
Andrew Wang 9232ed8ead Cleanup reload dialog and processRuntimeDependencies flow. (#1428)
* Removing reload code and insert wait code

Lots of refactoring to improve readability.
2018-01-10 17:20:49 -08:00
Sean McManus bc721d3f5a Fix delay in language service activation caused by cpptools.json downloading. (#1433)
* Prevent downloadCpptoolsJsonPkg from delaying activation.
* Also, changed the default workspaceParsingPriority to "highest" and the "normal" enum to "medium".
* And updated the changelog.
2018-01-10 13:56:39 -08:00
Bob Brown 5885388ae4 Merge pull request #1425 from Microsoft/users/seanmcm/fixMacInstall
Fix install on Mac.
2018-01-09 16:41:06 -08:00
Sean McManus eb74a9a834 Change == to ===. 2018-01-09 12:50:39 -08:00
Sean McManus 9e7b370aca Fix install on Mac. 2018-01-09 03:19:08 -08:00
Sean McManus 1bfb2477c1 Add setting to throttle workspace parsing. (#1389)
Add workspaceParsingPriority and exclusionPolicy settings.
2018-01-08 17:54:28 -08:00
Andrew Wang 0b8cdac4a6 rewriteManifest did not actually rewrite package (#1423) 2018-01-08 17:18:25 -08:00
Bob Brown 698d1e4014 Merge pull request #1422 from Microsoft/bobbrow/faq
Add the gcc command to check include paths to the FAQ
2018-01-08 16:14:51 -08:00
Bob Brown 11e0ffcaae Add the gcc command to check include paths to the FAQ 2018-01-08 15:31:04 -08:00
Bob Brown 68b8965dfe Merge pull request #1420 from Microsoft/bobbrow/split-paths
move path-splitting code into TypeScript and add support for browse.path
2018-01-08 14:59:17 -08:00
Bob Brown (DEVDIV) 484051c3d5 tslint 2018-01-08 14:23:13 -08:00
Bob Brown (DEVDIV) ce917b5243 move path-splitting code into TypeScript and add support for browse.path 2018-01-08 14:16:25 -08:00
Andrew Wang c728178de6 Adding tslint and gulp (#1403)
* Adding Gulp and tslint

Adding tslint and the associated changes that it complains about.

Adding gulp to do tests, tslint, and more.

Including package-lock.json that it keeps complaining about.

* Adding back license that was accidently deleted.

* Updating package-lock.json and missing import

* Sorting and fixing commands for npm run

Added npm run test, watch, and tslint.

* Adding rules for whitespace and types for tslint

* Updating .gitignore rules

* Adding more rules and sorting tslint.json

new-parens for forcing all constructor calls to have parenthesis.
no more than 1 consecutive blank lines
no useage of String(), Boolean(), or Number(), use native type.

* Adding rule to force brance on the same line

* tslint rule to add function return types

* Adding tslint as part of travisci
2018-01-05 13:57:55 -08:00
Andrew Wang ab5ff3ccf2 Adding .travis.yml (#1405)
Addition to compile and run tests per PR.
2018-01-04 13:07:22 -08:00
Pierson Lee 965ba124af Add natvis schema and a quick page on natvis (#1400)
* Add natvis schema and a quick page on natvis

* PR Feedback
2018-01-03 12:26:11 -08:00
Andrew Wang f5f7fa17c1 CompletionItemProvider for launch.json (#1401)
* Creating CompletionItemProvider for launch.json

* Address PR issues

* Adding jsonc-paser to ThirdPartyNotice
2018-01-03 12:22:16 -08:00
Pierson Lee 9a83d3e9bb Changes to copy from installed extension if CPPTOOLS_DEV has been set. (#1388)
We still allow overrides for different package locations but this will
use the vscode extension folder as a fallback if you have the extension
installed to get the extension location.
2018-01-02 16:23:33 -08:00
Andrew Wang 11509bed69 Moving from debugProxy to AdapterExecutableCommand (#1387)
* Moving from debugProxy to AdapterExecutableCommand

* Addressing PR issues

Moving registerAdapterExecutableCommand to Debugger/extension.ts

* Updating comment
2017-12-29 17:07:05 -08:00
Sean McManus aa4550c95d Update How to Contribute Changes.md (#1386)
Changed references to old files that got renamed.
2017-12-28 18:00:34 -08:00
Sean McManus 45aaee1a62 Remove CMakeLists.txt. (#1384) 2017-12-28 14:57:12 -08:00
Pierson Lee fb09db9b4b Add debugger code sample - Fib (#1383)
Add debugger code sample - Fib
2017-12-28 14:40:21 -08:00
Pierson Lee 92d0deceb7 Merge pull request #1382 from Microsoft/users/piel/merge
Move extension code to github.
2017-12-28 14:10:21 -08:00
Pierson Lee (PIE) b36642e5dc Move extension code to github.
* Update LICENSE file and license headers

U
2017-12-28 13:55:35 -08:00
ronglums 0fac6a32e1 Merge pull request #1336 from Microsoft/ronglu-edit
updated links
2017-12-11 17:03:58 -08:00
Rong Lu c6842db40c updated links 2017-12-11 17:02:37 -08:00
ronglums 92ac0b4ede Merge pull request #1335 from Microsoft/ronglu-edit
Ronglu edit
2017-12-11 17:00:09 -08:00
Rong Lu 5e4afa93e5 updates 2017-12-11 16:59:17 -08:00
Rong Lu d7ce37e641 minor edit 2017-12-08 15:36:10 -08:00
Rong Lu a2a3fc47ca format update 2017-12-08 15:34:52 -08:00
Rong Lu f613aeb25b added see also links 2017-12-08 15:33:36 -08:00
Rong Lu debfef31cd updated getting started and added intellisense engine page 2017-12-08 15:27:37 -08:00
Pierson Lee 1834e13c46 Update launch.md
Fix description
2017-12-08 11:20:54 -08:00
Pierson Lee 4d948fe03e Add sourceFileMap instructions 2017-12-07 23:25:11 -08:00
Rong Lu cce6db2f5d updated doc 2017-12-07 17:03:45 -08:00
Rong Lu 64288a3661 updated doc 2017-12-07 17:01:12 -08:00
Rong Lu aeccd7c762 updated screenshots 2017-12-07 16:50:06 -08:00
Rong Lu 9fad87f12b updated doc and include error screenshot 2017-12-07 16:26:29 -08:00
Rong Lu 7c5ed6dccb updated the doc 2017-12-07 16:21:47 -08:00
Rong Lu 815c22a0bb update 2017-12-07 16:11:01 -08:00
Rong Lu 20e51dbbb4 updates 2017-12-07 15:32:14 -08:00
Rong Lu 03c6c4df1d updated doc and screenshots 2017-12-07 15:24:09 -08:00
Rong Lu ab6b27759b updated text for c_cpp_properties.json link 2017-12-07 11:00:00 -08:00
Rong Lu 6b602f7914 updated reference links 2017-12-07 10:58:41 -08:00
Rong Lu 40e0563489 updated link to the lightbulb suggestion screenshot 2017-12-07 10:56:17 -08:00
Rong Lu 94b4de096b updated two links 2017-12-07 10:54:27 -08:00
Rong Lu fb4642c0ef Updated getting started page and screenshots. Added IntelliSense engine.md 2017-12-07 10:52:08 -08:00
ronglums 6276de6084 Merge pull request #1320 from Microsoft/ronglu-edit
update screenshots
2017-12-07 10:11:59 -08:00
Rong Lu 43dba74621 More screenshots 2017-12-07 10:09:09 -08:00
Rong Lu 53b48b1286 updated screenshot 2017-12-06 15:49:30 -08:00
ronglums e7b710896c Merge pull request #1314 from Microsoft/ronglu-edit
add images
2017-12-06 11:19:43 -08:00
Rong Lu 66df256fe6 add images 2017-12-06 11:12:29 -08:00
Pierson Lee 20d89ca801 Update launch.md 2017-11-09 13:29:02 -08:00
Bob Brown fbaca72ff5 Merge pull request #1177 from mezzode/wsl-debug
Update docs for WSL debugging
2017-10-31 09:40:24 -07:00
Bob Brown ddcc97ddaa Powershell command for additional distro filesystems
Credit to @icylogic for providing this Powershell command to discover additional distros' filesystems
2017-10-31 09:38:43 -07:00
Bob Brown 6dfa9d6e55 Merge pull request #1176 from mezzode/wsl-config
Update WSL config docs
2017-10-31 09:33:18 -07:00
Sean aa4220c47f Fix using beta config for C example 2017-10-31 11:24:45 +11:00
Bob Brown 53e8072f02 Merge pull request #1179 from russelltg/patch-1
Fix syntax error in JSON
2017-10-30 09:15:39 -07:00
Russell Greene fce806fa02 Fix syntax error in JSON
The `c_cpp_properties.json` example file was missing a comma in the reference for `c_cpp_properties.json`
2017-10-28 13:01:09 -06:00
Sean 22f71eac7a Update docs for WSL debugging 2017-10-28 12:13:30 +11:00
Sean 9556593ce9 Update formatting 2017-10-28 11:23:09 +11:00
Sean 312a14ad59 Update docs for WSL config 2017-10-28 11:17:09 +11:00
Bob Brown d1d81de3e4 Update Enabling logging.md 2017-10-23 08:40:08 -07:00
Bob Brown 9ed1ec6c9d Update Getting started.md 2017-10-23 08:38:31 -07:00
Bob Brown 9b11449fbe Update ISSUE_TEMPLATE.md 2017-10-19 13:42:16 -07:00
Bob Brown 9f1b6d6e3d formatting 2017-10-19 10:33:17 -07:00
Bob Brown b3580ce633 Update c_cpp_properties.json.md 2017-10-19 10:32:37 -07:00
Bob Brown 08fee2c0a7 Add information about the compileCommands property 2017-10-19 10:29:10 -07:00
Bob Brown ea8a02dfd5 Updating logging information 2017-10-19 10:18:28 -07:00
Bob Brown c26d6441be Merge pull request #1142 from csholmq/patch-1
Typo
2017-10-18 07:51:28 -07:00
Sebastian Holmqvist 42ec330978 Typo 2017-10-18 13:00:56 +02:00
Bob Brown 0d88024174 Update MinGW.md 2017-10-17 11:25:54 -07:00
Bob Brown 684b597255 Update MinGW.md 2017-10-17 11:25:12 -07:00
Bob Brown b6f9acd0d7 Merge pull request #1132 from Jaxkr/patch-1
Update MinGW paths to 6.3.0.
2017-10-17 11:24:09 -07:00
Jackson Roberts 3f330fc8a5 Update MinGW paths to 6.3.0.
As the latest recommended version of MinGW is 6.3.0 and MinGW strongly discourages using old versions, I think it's appropriate to update the version numbers for this file and add a notice informing users that they may have to change the MinGW file path to match their version.
2017-10-14 00:40:43 -06:00
111 changed files with 20527 additions and 317 deletions
+43
View File
@@ -0,0 +1,43 @@
language: node_js
node_js:
- "8"
before_install:
# Do not modify. Required for GUI based tests: See https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
- if [ $TRAVIS_OS_NAME == "linux" ]; then
export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
sh -e /etc/init.d/xvfb start;
sleep 3;
fi
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://packages.microsoft.com/repos/microsoft-ubuntu-trusty-prod trusty main'
key_url: 'https://packages.microsoft.com/keys/microsoft.asc'
packages:
- gdb
- g++-4.9
script:
# Download debugAdapters from an existing extension version. See TravisCI settings to set CPPTOOL_VERSION
- mkdir -p ~/.vscode/extensions/ms-vscode.cpptools-$CPPTOOL_VERSION
- wget https://github.com/Microsoft/vscode-cpptools/releases/download/$CPPTOOL_VERSION/cpptools.vsix -O ~/cpptools.vsix
- unzip ~/cpptools.vsix "extension/debugAdapters/*" -d ~/.
- mv ~/extension/debugAdapters ~/.vscode/extensions/ms-vscode.cpptools-$CPPTOOL_VERSION/debugAdapters
# Build and then run tests
- cd Extension
- npm install
- npm run tslint
- npm run compile
- npm run test
after_failure:
- find ~ -name "integrationTests.log" -type f -exec cat {} \;
after_success:
- find ~ -name "integrationTests.log" -type f -exec cat {} \;
+3
View File
@@ -0,0 +1,3 @@
## Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact opencode@microsoft.com with any additional questions or comments.
+20
View File
@@ -0,0 +1,20 @@
# How to Contribute Changes
## Contribution Steps
* [Build and debug the extension](Documentation/Getting%20started.md#build-and-debug-the-cpptools-extension).
* File an [issue](https://github.com/Microsoft/vscode-cpptools/issues) and a [pull request](https://github.com/Microsoft/vscode-cpptools/pulls) with the change and we will review it.
* If the change affects functionality, add a line describing the change to [**CHANGELOG.md**](Extension/CHANGELOG.md).
* Try and add a test in [**test/extension.test.ts**](Extension/test/unitTests/extension.test.ts).
* Run tests via opening the [**Extension**](https://github.com/Microsoft/vscode-cpptools/tree/master/Extension) folder in Visual Studio Code, selecting the "Launch Tests" configuration in the Debug pane, and choosing "Start Debugging".
## About the Code
* Execution starts in the `activate` method in [**main.ts**](Extension/src/main.ts).
* `processRuntimeDependencies` handles the downloading and installation of the OS-dependent files. Downloading code exists in [**packageManager.ts**](Extension/src/packageManager.ts).
* `downloadCpptoolsJsonPkg` handles the **cpptools.json**, which can be used to enable changes to occur mid-update, such as turning the `intelliSenseEngine` to `"Default"` for a certain percentage of users.
* The debugger code is in the [**Debugger**](https://github.com/Microsoft/vscode-cpptools/tree/master/Extension/src/Debugger) folder.
* [**LanguageServer/client.ts**](Extension/src/LanguageServer/client.ts) handles various language server functionality.
* [**LanguageServer/configurations.ts**](Extension/src/LanguageServer/configurations.ts) handles functionality related to **c_cpp_properties.json**.
* [**telemetry.ts**](Extension/src/telemetry.ts): Telemetry data gets sent to either `logLanguageServerEvent` or `logDebuggerEvent`.
* The Tag Parser (symbol database) doesn't automatically expand macros, so the [**cpp.hint**](Extension/cpp.hint) file contains definitions of macros that should be expanded in order for symbols to be parsed correctly.
+40
View File
@@ -0,0 +1,40 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"preLaunchTask": "build",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"logging": {
"engineLogging": false,
"trace": false
},
"windows": {
"program": "${workspaceRoot}/fib.exe",
"MIMode": "gdb",
"miDebuggerPath": "<Path/To/GDB>" // Path to gdb on windows
},
"linux": {
"program": "${workspaceRoot}/fib.out",
"MIMode": "gdb"
},
"osx": {
"program": "${workspaceRoot}/fib.out",
"MIMode": "lldb"
}
}
]
}
+50
View File
@@ -0,0 +1,50 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"taskName": "build",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"windows": {
"command": "${workspaceRoot}/build.cmd",
"args": [
"<Path/To/MinGW/Cygwin/Bin/Folder>", // Path to the bin folder containing g++ to compile
"fib.exe" // Output executable name
]
},
"linux": {
"command": "g++",
"args": [
"-g",
"*.cpp",
"-lpthread",
"--std=c++11",
"-o",
"fib.out"
]
},
"osx": {
"command": "g++",
"args": [
"-g",
"*.cpp",
"-lpthread",
"--std=c++11",
"-o",
"fib.out"
]
}
}
]
}
+3
View File
@@ -0,0 +1,3 @@
# Fib
This code sample is to show debugging. Update `launch.json` and `tasks.json` in the `.vscode` folder to use your setup to build and debug.
+2
View File
@@ -0,0 +1,2 @@
SET PATH=%PATH%;%1
g++ -g *.cpp -lpthread --std=c++11 -O0 -o %2
+58
View File
@@ -0,0 +1,58 @@
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "thread.h"
#define THREAD_COUNT 10
static char block[] = "--block";
int test = 0;
int main(int argc, char **argv)
{
srand(time(NULL));
static char pidText[] = "PID: ";
std::string helpText = "Attach a debugger and execute 'set foo=0' to continue";
char helloText[] = "Hello World!";
std::cout << helloText << std::endl;
pthread_t threads[THREAD_COUNT];
if (argc == 2 && !strcmp(block, argv[1]))
{
std::cout << helpText << std::endl;
volatile int foo = 1;
while (foo)
;
}
if (argc == 2 && !strcmp("--crash", argv[1]))
{
int foo = 0;
int bar = 1 / foo;
}
for (int i = 0; i < THREAD_COUNT; i++)
{
std::cout << "Test " << i << std::endl;
pthread_create(&threads[i], NULL, &thread_proc, NULL);
}
for (int i = 0; i < THREAD_COUNT; i++)
{
pthread_join(threads[i], NULL);
test++;
}
std::cout << "All threads exited!" << std::endl;
return 1;
}
+48
View File
@@ -0,0 +1,48 @@
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "thread.h"
static int g_tid = 0;
static int fib(int n){
switch (n) {
case 0: return 1;
case 1: return 1;
default: return (fib(n-2) + fib(n-1));
}
}
void * thread_proc(void* ctx)
{
int tid = g_tid++;
char thread_name[16];
sprintf(thread_name, "Thread %d", tid);
#ifdef __APPLE__
pthread_setname_np(thread_name);
#else
pthread_setname_np(pthread_self(), thread_name);
#endif
// Random delay, 0 - 0.5 sec
timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 500000000 + ((float)rand() / (float)RAND_MAX) * 500000000;
nanosleep(&ts, NULL);
volatile int i = 0;
while (i <= 30) {
std::cout << "Thread " << tid << ": fib(" << i << ") = " << fib(i) << std::endl;
i++;
nanosleep(&ts, NULL);
}
std::cout << thread_name << " exited!" << std::endl;
}
+1
View File
@@ -0,0 +1 @@
void * thread_proc(void* ctx);
@@ -0,0 +1,2 @@
main.exe
main.exe.dSYM
+17
View File
@@ -0,0 +1,17 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/main.exe", // this is executable to launch the debugger with
"args": ["YourNameHere"],
"stopAtEntry": true, // if true then stop at the main entry (function)
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "lldb"
}
]
}
+19
View File
@@ -0,0 +1,19 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "clang++",
"command": "clang++ --debug -o main.exe main.cpp",
// "--debug" enables debugging symbols
// "-o main.exe" specifies the output executable
// "main.cpp" is the source file to compile
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
+10
View File
@@ -0,0 +1,10 @@
# README
This is a sample debuggable C++ project. It uses the vendor provided version of clang installed. `tasks.json` and `launch.json` have been edited to demonstrate how to create a configuration for a C++ project that builds with clang.
There's a sample build task in `.vscode/tasks.json`; you can also see the build configurations by using the menu option `Configure` -> `Configure Tasks` or by clicking the gear icon in the Debug Panel.
To run a build, use the menu option `Tasks` -> `Run Build Task...`.
There's a sample debug configuration in `.vscode/launch.json`; you can also see the configuration by using the menu option `Debug` -> `Open Configurations`.
To debug the build, use the menu option `Debug` -> `Start Debugging`. The executable will launch and stop in the main function.
+17
View File
@@ -0,0 +1,17 @@
#include <iostream>
#include <string>
using namespace std;
void greet(const string& person) {
cout << "Hello, " << person << "!" << endl;
}
int main(int argc, char** argv) {
if(argc >= 2) {
greet(argv[1]);
} else {
cerr << "insufficient args, usage: " << argv[0] << " personNameHere" << endl;
}
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
## How to build and debug the Microsoft CppTools Extension
These steps will allow you to debug the TypeScript code that is part of the Microsoft CppTools extension for Visual Studio Code.
Prerequisite steps:
* Clone [this](https://github.com/Microsoft/vscode-cpptools) repository.
* Install [npm](https://nodejs.org).
* From a command line, run the following commands from the **Extension** folder in the root of the repository:
* `npm install -g vsce` will install `vsce` globally to create the vsix package.
* `npm install` will install the dependencies needed to build the extension.
* Set an environment variable `CPPTOOLS_DEV=1`.
* This enables the local developer workflow, copying dependencies from the **node_modules** folder.
* Open the **Extension** folder in Visual Studio Code and F5.
* Read the [contributing guidelines](https://github.com/Microsoft/vscode-cpptools/blob/master/CONTRIBUTING.md).
+16 -12
View File
@@ -1,7 +1,8 @@
# How To Debug MIEngine (Work in Progress)
*This is a work in progress. Please create a pull request with updates if there is anything wrong with it.*
MIEngine is one of the components used to enable the C/C++ debugging scenario with the Microsoft C/C++ extension with VS Code. This document is to help enable users who want to debug and contribute to MIEngine to fix issues or extend functionality. MIEngine is used to communicate with `gdb/lldb` using the MI protocol.
MIEngine is one of the components used to enable the C/C++ debugging scenario with the Microsoft C/C++ extension with VS Code. This document is to help enable users who want to debug and contribute to MIEngine to fix issues or extend functionality. MIEngine is used to communicate with `gdb`/`lldb` using the MI protocol.
**Repository:** https://github.com/Microsoft/MIEngine
@@ -9,7 +10,7 @@ MIEngine is one of the components used to enable the C/C++ debugging scenario wi
To build MIEngine, you will either need Visual Studio 2015+ installed or at the very least [MSBuild](https://github.com/Microsoft/msbuild) installed. The configuration you want to build is `Desktop.Debug`.
You can open the solution file `MIDebugEngine.sln` located under `src` and change the configuration and build. You will want to look in the `bin\Desktop.Debug` folder for the compiled bits. You will need to copy the following files to your `.vscode\extensions\ms-vscode.cpptools-<version>\debugadapters\bin` folder in your users/home folder:
You can open the solution file **MIDebugEngine.sln** located under **src** and change the configuration and build. You will want to look in the **bin\Desktop.Debug** folder for the compiled bits. You will need to copy the following files to your **.vscode\extensions\ms-vscode.cpptools-\<version\>\debugadapters\bin** folder in your users/home folder:
* Microsoft.MICore.dll
* Microsoft.MICore.XmlSerializers.dll
@@ -27,7 +28,7 @@ The symbol files are as follows:
### Debugging On Windows
On Windows, the easiest way to debug is to use Visual Studio. Locate the `package.json` file in the extension folder and open it in an editor.
On Windows, the easiest way to debug is to use Visual Studio. Locate the **package.json** file in the **Extension** folder and open it in an editor.
Locate the following line:
```json
@@ -49,29 +50,32 @@ On Linux and Mac OS X, we use `mono` as our framework. You can download Xamarin
2. Install [Xamarin Studio v5.10.1.6](http://download.xamarin.com/studio/Windows/XamarinStudio-5.10.1.6-0.msi)
Remote attach functionality behind a flag. You can run it like this:
```
cd "\Program Files (x86)\MonoDevelop\bin"
set MONODEVELOP_SDB_TEST=1
MonoDevelop.exe
```PowerShell
cd "\Program Files (x86)\MonoDevelop\bin"
set MONODEVELOP_SDB_TEST=1
MonoDevelop.exe
```
#### Create an empty project for attaching (one-time setup)
1. Launch MonoDevelop
2. File -> New Solution
3. Misc/Generic Project
4. Name project and hit "Create"
5. Right-click the project node (blue square) and do "Options"
6. Under Run -> Custom Commands, select "Execute" in the lower dropdown and choose a command (I use c:\windows\notepad.exe - it doesn't matter what the command is, but MonoDevelop requires it to exist before it'll light up the Run menu).
6. Under Run -> Custom Commands, select "Execute" in the lower dropdown and choose a command (I use `c:\windows\notepad.exe` - it doesn't matter what the command is, but MonoDevelop requires it to exist before it'll light up the Run menu).
#### Configure the extension to enable remote debugging
Open the `~/.vscode/extensions/ms-vscode.cpptools-<version>/debugAdapters/OpenDebugAD7` file with a text editor and locate and uncomment the line at the bottom. When you start debugging, it will now hang until the remote debugger is attached from Xamarin Studio.
Open the **~/.vscode/extensions/ms-vscode.cpptools-\<version\>/debugAdapters/OpenDebugAD7** file with a text editor and locate and uncomment the line at the bottom. When you start debugging, it will now hang until the remote debugger is attached from Xamarin Studio.
#### Attach the remote debugger
In MonoDevelop: Run -> Run With -> Custom Command Mono Soft Debugger
Fill in the IP and port of the Linux/Mac OS X machine and hit "Connect" to start debugging
After you've done this once, you can hit the MonoDevelop "Play" button or F5 to bring up the connect dialog again.
After you've done this once, you can hit the MonoDevelop "Play" button or <kbd>F5</kbd> to bring up the connect dialog again.
Note: If you are debugging to CentOS, you will need to make an exception in the firewall
* sudo firewall-cmd --zone=public --add-port=1234/tcp --permanent
* sudo firewall-cmd --reload
* `sudo firewall-cmd --zone=public --add-port=1234/tcp --permanent`
* `sudo firewall-cmd --reload`
+36 -34
View File
@@ -1,52 +1,54 @@
# Pipe Transport
Pipe Transport allows communication through a pipe program to a remote shell. An example on linux would be `ssh`.
Pipe Transport allows communication through a pipe program to a remote shell. An example on Linux would be `ssh`.
## How-To
We have added `"pipeTransport"` as an option within the `launch.json` file. The structure looks as follows:
```
"pipeTransport": {
"pipeCwd": "/usr/bin",
"pipeProgram": "/usr/bin/ssh",
"pipeArgs": [
"-pw",
"<password>",
"[email protected]"
],
"debuggerPath": "/usr/bin/gdb"
},
We have added `"pipeTransport"` as an option within the **launch.json** file. The structure looks as follows:
```json
"pipeTransport": {
"pipeCwd": "/usr/bin",
"pipeProgram": "/usr/bin/ssh",
"pipeArgs": [
"-pw",
"<password>",
"[email protected]"
],
"debuggerPath": "/usr/bin/gdb"
},
```
The `pipeArgs` can be any set of arguments necessary to setup and authenticate the pipe connection. In the example, a password is used but you can also use an ssh key.
You may also need to add a `sourceFileMap` to map the path of where the code exists on the remote shell to where it is locally:
```
"sourceFileMap": {
// "remote": "local"
"/home/user/src": "/src/projectA/src"
}
```json
"sourceFileMap": {
// "remote": "local"
"/home/user/src": "/src/projectA/src"
}
```
## Attach
You can also use the above `pipeTransport` block to attach to a remote process. In the attach case, you will need to specify a `processId`. We have added the ability to query processes from the remote machine. To do this, change `"processId": "${command.pickProcess}"` to `"processId": "${command.pickRemoteProcess}"`. The `pipeTransport` settings will be used to query the processes on the remote machine. Then select the process from the drop down list. As with `launch`, you may need to configure `sourceFileMap`.
## Docker example
The `pipeTransport` can also be used to debug a process in a Docker container. For an attach, the `launch.json` will include:
The `pipeTransport` can also be used to debug a process in a Docker container. For an attach, **launch.json** will include:
```json
"pipeTransport": {
"pipeCwd": "${workspaceRoot}",
"pipeProgram": "docker",
"pipeArgs": [
"exec",
"-i",
"hello_gdb",
"sh",
"-c"
],
"debuggerPath": "/usr/bin/gdb"
},
```
"pipeTransport": {
"pipeCwd": "${workspaceRoot}",
"pipeProgram": "docker",
"pipeArgs": [
"exec",
"-i",
"hello_gdb",
"sh",
"-c"
],
"debuggerPath": "/usr/bin/gdb"
},
```
Where `hello_gdb` is the name of your container.
Launching a process is accomplished by starting a container and then using the same `pipeTransport` launch additional processes in the container. See this [`launch.json`](https://github.com/andyneff/hello-world-gdb/blob/master/.vscode/launch.json) for a [full example](https://github.com/andyneff/hello-world-gdb/)
Launching a process is accomplished by starting a container and then using the same `pipeTransport` launch additional processes in the container. See this [**launch.json**](https://github.com/andyneff/hello-world-gdb/blob/master/.vscode/launch.json) for a [full example](https://github.com/andyneff/hello-world-gdb/).
@@ -1,86 +1,91 @@
# Windows 10's Windows Subsystem for Linux
With the release of Windows 10 Creators Update (Build 15063), you will now be able to use Visual Studio Code and the Microsoft C/C++ extension to debug your `Windows Subsystem for Linux (WSL)` [Bash on Ubuntu](https://msdn.microsoft.com/en-us/commandline/wsl/about) projects.
Code can be written on Windows itself using VSCode and debugged through `bash.exe` to the Bash on Windows layer.
With the release of Windows 10 Creators Update (Build 15063), you will now be able to use Visual Studio Code and the Microsoft C/C++ extension to debug your [Windows Subsystem for Linux (WSL)](https://msdn.microsoft.com/en-us/commandline/wsl/about) projects.
**NOTE: Creator's Update (Build 15063 or later) is required due to bugfixes within the subsystem that we rely on to provide debugging. Debugging using a previous version of WSL is unsupported and likely will not work. To check your Windows version, enter `winver` in a command prompt.**
Code can be written on Windows itself using VSCode and debugged through `bash.exe` to the Bash on Windows layer.
As of the Fall Creator's Update, you can have multiple distros installed, but `bash.exe` and `wsl.exe` use the default distro. Use [WSL Config](https://msdn.microsoft.com/en-us/commandline/wsl/wsl-config) to set your default distro.
**NOTE: Creator's Update (Build 15063 or later) is required due to bug-fixes within the subsystem that we rely on to provide debugging. Debugging using a previous version of WSL is unsupported and likely will not work. To check your Windows version, enter `winver` in a command prompt.**
## Prerequisites
* [Windows 10 Creators Update with Windows Subsystem for Linux and Bash](https://msdn.microsoft.com/en-us/commandline/wsl/install_guide) installed.
* [Windows 10 Creators Update or later with Windows Subsystem for Linux](https://msdn.microsoft.com/en-us/commandline/wsl/install_guide) installed.
* Install g++/gcc and gdb within `WSL` to allow compiling and debugging. You can use the package manager to do this. For example, to install g++, you can run `sudo apt install g++` in the Bash window.
* [Visual Studio Code](https://code.visualstudio.com) + Microsoft C/C++ extension for VSCode.
## How-To
To debug, commands will be routed from Windows through `bash.exe` to set up debugging. Because our extension runs as a 32-bit process, it will need to use the `C:\Windows\SysNative` folder to access the `bash.exe` executable that is normally in `C:\Windows\System32`. We will be using the `"pipeTransport"` ability within the extension to do debugging and `"sourceFileMap"` to map the source from the subsystem's paths back to Windows path.
To debug, commands will be routed from Windows through `bash.exe` to set up debugging. Because our extension runs as a 32-bit process, it will need to use the `C:\Windows\SysNative` folder to access the `bash.exe` executable that is normally in `C:\Windows\System32`. We will be using the `"pipeTransport"` ability within the extension to do debugging and `"sourceFileMap"` to map the source from the subsystem's paths back to Windows path.
**NOTE: Applications will need to be compiled in the `Windows Subsystem for Linux (WSL)` prior to debugging.**
### Example `launch.json` for Launching
In the following example, I have a local drive, `Z:\` that has my source code within windows for an app called kitchensink. I have set up the `"program"` and `"cwd"` paths to point to the directory within `WSL`. I have set up the `"pipeTransport"` to use `bash.exe`. I have also set up a `"sourceFileMap"` to have everything that is returned by `gdb` that starts with `/mnt/z` to point to `Z:\\` in Windows.
In the following example, I have a local drive, `Z:\` that has my source code within windows for an app called _kitchensink_. I have set up the `"program"` and `"cwd"` paths to point to the directory within `WSL`. I have set up the `"pipeTransport"` to use `bash.exe`. I have also set up a `"sourceFileMap"` to have everything that is returned by `gdb` that starts with `/mnt/z` to point to `Z:\\` in Windows.
```
{
"name": "C++ Launch",
"type": "cppdbg",
"request": "launch",
"program": "/mnt/z/Bash/kitchensink/a.out",
"args": ["-fThreading"],
"stopAtEntry": false,
"cwd": "/mnt/z/Bash/kitchensink",
"environment": [],
"externalConsole": true,
"windows": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
"pipeTransport": {
"pipeCwd": "",
"pipeProgram": "c:\\windows\\sysnative\\bash.exe",
"pipeArgs": ["-c"],
"debuggerPath": "/usr/bin/gdb"
},
"sourceFileMap": {
"/mnt/z": "z:\\"
```json
{
"name": "C++ Launch",
"type": "cppdbg",
"request": "launch",
"program": "/mnt/z/Bash/kitchensink/a.out",
"args": ["-fThreading"],
"stopAtEntry": false,
"cwd": "/mnt/z/Bash/kitchensink",
"environment": [],
"externalConsole": true,
"windows": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
}
]
},
"pipeTransport": {
"pipeCwd": "",
"pipeProgram": "c:\\windows\\sysnative\\bash.exe",
"pipeArgs": ["-c"],
"debuggerPath": "/usr/bin/gdb"
},
"sourceFileMap": {
"/mnt/z": "z:\\"
}
}
```
### Example `launch.json` for Attaching to an Existing Process
This configuration similar to the launch process above. I have chosen to start the same application above from the Bash command line and now I want to attach to it for debugging. I have changed the `"processID"` to use the remote process picker by specifying the command `"${command:pickRemoteProcess}"` and set up the same `"sourceFileMap"`. When I press F5 to attach, I get a picker drop down showing the running processes within `WSL`. I can scroll or search for the process I want to attach to and start debugging.
This configuration similar to the launch process above. I have chosen to start the same application above from the Bash command line and now I want to attach to it for debugging. I have changed the `"processID"` to use the remote process picker by specifying the command `"${command:pickRemoteProcess}"` and set up the same `"sourceFileMap"`. When I press <kbd>F5</kbd> to attach, I get a picker drop down showing the running processes within `WSL`. I can scroll or search for the process I want to attach to and start debugging.
```
{
"name": "C++ Attach",
"type": "cppdbg",
"request": "attach",
"program": "/mnt/z/Bash/kitchensink/a.out",
"processId": "${command:pickRemoteProcess}",
"windows": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
"pipeTransport": {
"pipeCwd": "",
"pipeProgram": "c:\\windows\\sysnative\\bash.exe",
"pipeArgs": ["-c"],
"debuggerPath": "/usr/bin/gdb"
},
"sourceFileMap": {
"/mnt/z": "z:\\"
```json
{
"name": "C++ Attach",
"type": "cppdbg",
"request": "attach",
"program": "/mnt/z/Bash/kitchensink/a.out",
"processId": "${command:pickRemoteProcess}",
"windows": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
}
]
},
"pipeTransport": {
"pipeCwd": "",
"pipeProgram": "c:\\windows\\sysnative\\bash.exe",
"pipeArgs": ["-c"],
"debuggerPath": "/usr/bin/gdb"
},
"sourceFileMap": {
"/mnt/z": "z:\\"
}
}
```
+15
View File
@@ -0,0 +1,15 @@
# Natvis - Custom views for native objects
The Natvis framework allows developers to write custom schemas to help visualize native objects.
For gdb/lldb debugging (`"type": "cppdbg"`), a subset of the Natvis framework has been ported to the C/C++ extension and the code resides in the [MIEngine](https://github.com/Microsoft/MIEngine) shared component. If additional features that are not implemented are requested, please file an [issue](https://github.com/Microsoft/MIEngine/issues) on the MIEngine GitHub page with details of what is missing.
For Visual C++ debugging (`"type": "cppvsdbg"`), the debugger contains the full implementation of the Natvis framework as Visual Studio.
## Documentation
The official documentation can be found [here](https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects).
## Schema
The Natvis schema can be found [here](natvis.xsd).
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
# FAQs
## Table of Contents
* Setup: [Debugging Setup](#debugging-setup)
* Debugger: [Why is debugging not working?](#why-is-debugging-not-working)
* Build: [How to enable debug symbols?](#how-to-enable-debug-symbols)
## Debugging Setup
The debugger needs to be configured to know which executable and debugger to use:
Click menu item: `Debug` -> `Add Configuration...`
The file **launch.json** will now be open for editing with a new configuration. The default settings will *probably* work except that you need to specify the **program** setting.
See the [**Documentation/Debugger**](https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation/Debugger) folder in this repository for more in-depth documentation on how to configure the debugger.
## Why is debugging not working?
### My breakpoints aren't being hit
When you start debugging, if it is showing that your breakpoints aren't bound (solid red circle) or they are not being hit, you may need to enable [debug symbols](#how-to-enable-debug-symbols) during compilation.
### Debugging starts but all the lines in my stack trace are grey
If your debugger is showing a grey stacktrace or won't stop at a breakpoint,or the symbols in the call stack are grey then your executable was compiled without [debug symbols](#how-to-enable-debug-symbols).
## How to enable debug symbols?
Enabling debug symbols are dependent on the type of compiler you are using. Below are some of the compilers and the compiler options necessary to enable debug symbols.
When in doubt, please check your compiler's documentation for the options necessary to include debug symbols in the output. This may be some variant of `-g` or `--debug`.
* #### Clang (C++)
* If you invoke the compiler manually then add the `--debug` option.
* If you're using a script then make sure the `CXXFLAGS` environment variable is set; e.g. `export CXXFLAGS="${CXXFLAGS} --debug"`
* If you're using CMake then set make sure the `CMAKE_CXX_FLAGS` is set; e.g. `export CMAKE_CXX_FLAGS=${CXXFLAGS}`
* #### Clang (C)
See Clang C++ but use `CFLAGS` instead of `CXXFLAGS`.
* #### gcc or g++
If you invoke the compiler manually, add the `-g` option.
* #### cl.exe
Symbols are located in the `*.pdb` file.
@@ -0,0 +1,56 @@
# Configuring includePath for better IntelliSense results
This page describes how to configure include paths for folders containing C or C++ files to get the full IntelliSense experience. If you're seeing the following message when opening a folder in VS Code, it means the C++ IntelliSense engine needs additional information about the paths in which your include files are located.
![Configure includePath for better IntelliSense](https://github.com/Microsoft/vscode-cpptools/raw/master/Images/configure%20includepath.jpg)
## Where are the include paths defined?
The include paths are defined in the `"includePath"` setting in a file called **c_cpp_properties.json** located in the **.vscode** directory in the opened folder.
You can create or open this file by either using the `"C/Cpp: Edit Configurations"` command in the command palette or by selecting `"Edit "includePath" setting"` in the lightbulb menu (see the screenshot below). The quickest way to locate a lightbulb is to scroll to the top of the source file and click on any green squiggle that shows up under a #include statement.
![lightbulb menu "Edit "includePath" setting"](https://github.com/Microsoft/vscode-cpptools/raw/master/Images/Lightbulb.png)
When a folder is opened, the extension attempts to locate your system headers based on your operating system, but it does not know about any other libraries that your project depends on. You can hover over the green squiggles or open the Problems window to understand which headers the IntelliSense engine is unable to open - sometimes it's the dependent headers that can't be located.
![include error message](https://github.com/Microsoft/vscode-cpptools/raw/master/Images/Include%20errors.png)
## How to specify the include paths?
You can specify the remaining paths using one of the techniques described below.
#### 1. Use `compile_commands.json` file to supply includePaths and defines information
The extension can get the information for `"includePath"` and `"defines"` from a **compile_commands.json** file, which can be auto-generated by many build systems such as CMake and Ninja. Look for the section where your current configuration is defined (by default there's one configuration per OS, such as "Win32 or "Mac"), and set the `"compileCommands"` property in **c_cpp_properties.json** to the full path to your **compile_commands.json** file and the extension will use that instead of the `"includes"` and `"defines"` properties for IntelliSense.
![use compileCommands setting](https://github.com/Microsoft/vscode-cpptools/raw/master/Images/compile_commands.png)
#### 2. Use the lightbulb suggestions to auto-resolve includePath
The first thing to try is to leverage the lightbulb path suggestions to auto-resolve the include paths. When you open a folder, the extension will **recursively** search for potential include paths that match the header files your code is using based on the paths set by the `"browse.path"` setting in **c_cpp_properties.json**. Click on the green squiggles under #include statements and you'll see a lightbulb offering suggestions of paths that will allow IntelliSense to resolve the included file.
![lightbulb suggestions](https://github.com/Microsoft/vscode-cpptools/raw/master/Images/lightbulb%20suggestion.png)
If you don't see path suggestions in the lightbulb, try adding the root folder where the headers are likely located in to the `"browse.path"` setting in **c_cpp_properties.json**. This allows the extension to **recursively** search in these folders and offer more suggestions in the lightbulb as the search process goes on.
#### 3. Manually add include paths
If none of the above fully resolves the paths, you could manually specify the paths to the headers that your project depends on in the **c_cpp_properties.json** file. Look for the section where your current configuration is defined (by default there's one configuration per OS, such as "Win32 or "Mac"), and add your paths in the `"includePath"` setting and defines in the `"defines"` setting. For example, the following screenshot shows a snippet of the file specifying path for the Mac configuration.
![c_cpp_properties file snippet](https://github.com/Microsoft/vscode-cpptools/raw/master/Images/c_cpp_properties%20file.PNG)
## Verify the include paths are correctly resolved
There are two ways to verify that the include paths are correctly resolved:
1. The green squiggles in the source file are no longer showing
2. Error messages are cleared in the Problems window
This indicates that the IntelliSense engine has got the include paths resolved so you can start enjoying the full IntelliSense for your C or C++ code for the current translation unit. Note that you may still see errors on other files if they belong to a different translation unit that requires additional include paths to be configured.
## See Also
[IntelliSense engines](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/IntelliSense%20engine.md)
[**c_cpp_properties.json** reference guide](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/c_cpp_properties.json.md)
-21
View File
@@ -1,21 +0,0 @@
# Getting started
## Configuring IntelliSense
**Quick summary**: Open your settings file and add `"C_Cpp.intelliSenseEngine": "Default"` to preview the new and improved IntelliSense. Then add the necessary include paths and preprocessor defines to your c_cpp_properties.json file so that IntelliSense can find your symbols.
#### The IntelliSense engines
When the extension was first released, we shipped an IntelliSense engine that provided quick, but "fuzzy" results for common operations like auto-complete, parameter help, quick info tooltips, and goto definition. This "tag parser" built up a database of symbols by parsing the most important "tags" from your source files, ignoring preprocessor blocks, local variables, and most errors. More recently, we have begun the process of porting the MSVC IntelliSense engine from Visual Studio to VS Code to provide more accurate results.
You can choose the engine that works best for your projects by editing your [user or workspace settings](https://code.visualstudio.com/docs/getstarted/settings). The setting you should modify is `"C_Cpp.intelliSenseEngine"`. There are two values for this setting:
* `"Default"` - use Visual Studio's IntelliSense engine (in preview, the default for VS Code Insiders)
* `"Tag Parser"` - use the "fuzzy" IntelliSense engine (the default for users on the stable VS Code build)
#### Include paths
In order to get accurate IntelliSense results with either engine, the extension needs some information about your project. When you open a folder, the extension will attempt to locate your system headers based on your operating system, but it does not know about any auxiliary libraries that your project depends on. You can specify the remaining paths by using the `"C/Cpp: Edit Configurations"` command in the command palette.
This command will create or open a file called **c_cpp_properties.json** in your workspace. In this file, you can specify the paths to the headers that your project depends on. There are two settings in this file that you should pay particular attention to: `"includePath"` and `"browse.path"`. `"includePath"` is the setting used by the `"Default"` IntelliSense engine and `"browse.path"` is the setting used by the tag parser engine. [More information about these settings is documented here](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/FAQ.md#what-is-the-difference-between-includepath-and-browsepath-in-c_cpp_propertiesjson).
@@ -2,6 +2,13 @@
If you are experiencing a problem that we are unable to diagnose based on information in your issue report, we might ask you to enable logging and send us your logs.
As of version 0.14.0 of the extension, logging information is now delivered directly to the Output window in VSCode. To turn on full logging for an issue report, add `"C_Cpp.loggingLevel": "Information"` to your **settings.json**.
![image](https://user-images.githubusercontent.com/12818240/31898313-b32ff284-b7cd-11e7-97f5-89df93b5d9de.png)
#### Old information (it still works, but is no longer recommended):
<del>
Logging is controlled by environment variables and is disabled by default. To enable logging, launch VS Code from an environment that contains the following variables:
```
@@ -9,8 +16,9 @@ VSCODE_CPP_LOGDIR=c:\path\to\logfolder
VSCODE_CPP_LOGFILE_LEVEL=5
```
When you open your folder in VS Code, we will create a vscode.cpp.log.\<pid\>.txt file for each extension process launched (\<pid\> = process id).
When you open your folder in VS Code, we will create a **vscode.cpp.log.\<pid\>.txt** file for each extension process launched (\<pid\> = process id).
The log file level is a number that determines how much detail we'll log. Level 5 is generally detailed enough to give us information about what is going on in your session. We don't recommend you set this higher than 7 since the log quickly becomes cluttered with information that doesn't really help us diagnose your issues and actually makes it harder for us to spot problems. It may also slow down the extension considerably and make it harder for you to reproduce your problem.
**Don't forget to remove the environment variables when you are finished providing us with the logs.** You wouldn't want the extension to needlessly spend CPU time and disk space writing data you don't need into log files.
</del>
+22 -20
View File
@@ -1,25 +1,23 @@
# Frequently asked questions
[How do I get IntelliSense to work correctly](#how-do-i-get-intellisense-to-work-correctly)?
[How do I get the new IntelliSense to work with MinGW on Windows](#how-do-i-get-the-new-intellisense-to-work-with-mingw-on-windows)?
[What is the difference between "includePath" and "browse.path" in c\_cpp\_properties.json](#what-is-the-difference-between-includepath-and-browsepath-in-c_cpp_propertiesjson)?
[How do I re-create the IntelliSense database](#how-do-i-re-create-the-intellisense-database)?
* [How do I get IntelliSense to work correctly?](#how-do-i-get-intellisense-to-work-correctly)
* [Why do I see red squiggles under Standard Library types?](#why-do-i-see-red-squiggles-under-standard-library-types)
* [How do I get the new IntelliSense to work with MinGW on Windows?](#how-do-i-get-the-new-intellisense-to-work-with-mingw-on-windows)
* [What is the difference between `"includePath"` and `"browse.path"` in **c_cpp_properties.json**?](#what-is-the-difference-between-includepath-and-browsepath-in-c_cpp_propertiesjson)
* [How do I re-create the IntelliSense database?](#how-do-i-re-create-the-intellisense-database)
## How do I get IntelliSense to work correctly?
There are two IntelliSense engines present in the extension: the "fuzzy" engine (or Tag Parser), and the new "Default" engine. If you are using version 0.11.0 or higher of the cpptools extension, then you can preview our new IntelliSense engine which has more accurate auto-complete suggestions and tooltips. To use the new engine, you need to ensure that `"C_Cpp.intelliSenseEngine"` is set to `"Default"` in your settings. Since the engine is still in preview it is not on by default for everyone yet.
After selecting the IntelliSense engine that you prefer, take a look at the Problems window in VS Code to see if you need to do any further configuration for your folder. For example, the Default engine will not provide squiggles and auto-complete suggestions for a translation unit (read: a source file and its dependencies) if the include path is not configured properly. You can select any of the problems in the window to navigate to the line when the problem was detected and a lightbulb will appear in the editor with some options (code actions) to help you resolve the problem.
After selecting the IntelliSense engine that you prefer, take a look at the Problems window in VS Code to see if you need to do any further configuration for your folder. For example, the Default engine will not provide squiggles and auto-complete suggestions for a translation unit (read: a source file and its dependencies) if the include path is not configured properly. You can select any of the problems in the window to navigate to the line when the problem was detected and a lightbulb will appear in the editor with some options (code actions) to help you resolve the problem:
1. Update your includePath (and preprocessor defines)
1. Update your `includePath` (and preprocessor defines)
2. Force semantic IntelliSense
#### Update your includePath (and preprocessor defines)
#### Update your `includePath` (and preprocessor defines)
Selecting this option will open a file called c_cpp_properties.json. If you haven't created this file already, it will be created for you in the .vscode folder of your workspace.
Selecting this option will open a file called **c_cpp_properties.json**. If you haven't created this file already, it will be created for you in the **.vscode** folder of your workspace.
Add the necessary paths to your include files to the `"includePath"` array. The `${workspaceRoot}` variable is available to use to get a relative path to the folder you have opened. Also add any required symbols that need to be defined to the `"defines"` array. Both "\<var\>" and "\<var\>=\<value\>" syntax is accepted. When you edit and save this file, the IntelliSense engine will reset and reparse source your source files and headers with the new settings.
@@ -27,25 +25,29 @@ Add the necessary paths to your include files to the `"includePath"` array. The
If you want IntelliSense to operate on your files even when all #include directives do not resolve, then you can choose the `Force semantic IntelliSense` code action to always use the new IntelliSense engine. You can also set the `C_Cpp.intelliSenseEngineFallback` setting to `"Disabled"`.
## Why do I see red squiggles under Standard Library types?
The most common reason for this is missing or sorted include paths. If you are using a compiler in the GCC family, the system includes that you add to your `"includePath"` in **c_cpp_properties.json** should match the output of the following command: `gcc -Wp,-v -E -xc -x c++ /dev/null` (replace 'gcc' with whichever compiler you are using). GCC and its relatives require the paths to be in a specific order too, so sorting the paths for aesthetics will likely result in incorrect IntelliSense results.
## How do I get the new IntelliSense to work with MinGW on Windows?
Since MinGW is a relative of GCC, Microsoft mode compilation (which is the default on Windows) doesn't work very well with it. To use GCC/CLang mode, set the `"intelliSenseMode"` property in your **c_cpp_properties.json** file to `"clang-x64"`. An example **c_cpp_properties.json** [is shared here for your convenience](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/MinGW.md).
## What is the difference between "includePath" and "browse.path" in c\_cpp\_properties.json?
## What is the difference between `"includePath"` and `"browse.path"` in **c_cpp_properties.json**?
Starting with version 0.11.0 of the cpptools extension, there are now two settings in the c\_cpp\_properties.json file. They are used by the different IntelliSense engines that we support and have slightly different meanings for the components that use them.
Starting with version 0.11.0 of the cpptools extension, there are now two settings in the **c_cpp_properties.json** file. They are used by the different IntelliSense engines that we support and have slightly different meanings for the components that use them.
The active IntelliSense engine is controlled via the `"C_Cpp.intelliSenseEngine"` setting in your settings.json file. The valid values for this setting are:
* `"Default"`
* `"Tag Parser"`
The active IntelliSense engine is controlled via the `"C_Cpp.intelliSenseEngine"` setting in your **settings.json** file. The valid values for this setting are `"Default"` and `"Tag Parser"`.
**includePath**: This array of path strings is used by the new "Default" IntelliSense engine that was introduced in version 0.11.0 of the extension. This new engine provides semantic-aware IntelliSense features and will be the eventual replacement for the Tag Parser that has been powering the extension since it was first released. It currently provides tooltips and error squiggles in the editor. The remaining features (e.g. code completion, signature help, go to definition, ...) are implemented using the Tag Parser's database, so it is still important to ensure that the browse.path setting is properly set.
* #### `"includePath"`
This array of path strings is used by the new "Default" IntelliSense engine that was introduced in version 0.11.0 of the extension. This new engine provides semantic-aware IntelliSense features and will be the eventual replacement for the Tag Parser that has been powering the extension since it was first released. It currently provides tooltips and error squiggles in the editor. The remaining features (e.g. code completion, signature help, go to definition, ...) are implemented using the Tag Parser's database, so it is still important to ensure that the browse.path setting is properly set.
The paths that you specify for this setting are the same paths that you would send to your compiler via the `-I` switch. When your source files are parsed, the IntelliSense engine will prepend these paths to the files specified by your `#include` directives while attempting to resolve them. These paths are _not searched recursively_.
The paths that you specify for this setting are the same paths that you would send to your compiler via the `-I` switch. When your source files are parsed, the IntelliSense engine will prepend these paths to the files specified by your #include directives while attempting to resolve them. These paths are **not** searched recursively.
**browse.path**: This array of path strings is used by the "Tag Parser" (a.k.a. "browse engine"). This engine will _recursively_ enumerate all files under the paths specified and track them as potential includes while tag parsing your project folder. To disable recursive enumeration of a path, you can append a `/*` to the path string.
* #### `"browse.path"`
This array of path strings is used by the "Tag Parser" (a.k.a. "browse engine"). This engine will _recursively_ enumerate all files under the paths specified and track them as potential includes while tag parsing your project folder. To disable recursive enumeration of a path, you can append a `/*` to the path string.
When you open a workspace for the first time, the extension adds `${workspaceRoot}` to both arrays. If this is undesirable, you can open your c_cpp_properties.json file and remove it.
When you open a workspace for the first time, the extension adds `${workspaceRoot}` to both arrays. If this is undesirable, you can open your **c_cpp_properties.json** file and remove it.
## How do I re-create the IntelliSense database?
@@ -0,0 +1,44 @@
# IntelliSense engines
There are two IntelliSense engines used to power the C/C++ IntelliSense experience in VS Code.
* `"Default"` - Visual Studio's IntelliSense engine, which is the default engine that provides semantic-aware IntelliSense features
* `"Tag Parser"` - the "fuzzy" IntelliSense engine that provides quick but "fuzzy" results, is used to provide the fallback experience if the default engine is unable to fully resolve include paths
Ultimately all the IntelliSense and code browsing features will be powered by the "Default" engine. The following features have been implemented so far:
* Auto-complete suggestions for class/struct/namespace members
* Parameter hints
* Quick info (hover over tooltip)
* Error squiggles
* Reference highlighting
The other IntelliSense features, such as global auto-complete, and code browsing features, such as Go to definition/declaration, are currently powered by the "Tag Parser" based engine.
### `includePath` and `browse.path`
The two IntelliSense engines use two different settings in the **c_cpp_properties.json** file for specifying include paths. This file is located in the **.vscode** directory in the opened folder. You can create or open this file by either using the "C/Cpp: Edit Configurations" command in the command palette or by selecting "Edit "includePath" setting" in the lightbulb menu. Look for the following settings in the section where your current configuration is defined (by default there's one configuration per OS, such as "Win32 or "Mac").
* #### `"includePath"`
This array of path strings is used by the "Default" IntelliSense engine. The paths that you specify for this setting are the same paths that you would send to your compiler via the -I switch. When your source files are parsed, the IntelliSense engine will prepend these paths to the files specified by your #include directives while attempting to resolve them. These paths are searched **non-recursively**.
* #### `"browse.path"`
This array of path strings is used by the "Tag Parser" (a.k.a. "browse engine"). This engine will **recursively** enumerate all files under the paths specified and track them as potential includes while tag parsing your project folder. To disable recursive enumeration of a path, you can append a `/*` to the path string.
### How fallback works and how to control the behavior
The extension first tries to fully parse any opened file using the "Default" IntelliSense engine. If it discovers that it cannot find a header file or a dependency, it will fall back to the tag parser and provide the fuzzy IntelliSense behavior. The fallback affects a full translation unit (TU), not just a single open file. The Problems panel provides details about unresolved headers and dependencies. Other opened TUs will continue to use the "Default" IntelliSense engine provided that all #include dependencies are resolved.
We recognize that resolving all #includes may not be necessary for all projects and you may still want to experience the productivity benefits of using the "Default" semantic engine without customizing the default include path. For that, the “Force semantic IntelliSense” action can be chosen. When invoked, all unresolved #include squiggles will turn red and semantic member list and linting will be enabled in all files regardless of whether or not #include statements can be resolved.
### IntelliSense engine setting
We recommend using the "Default" engine for the best IntelliSense experience. However, it is possible to explicitly choose the IntelliSense engine by editing your [user or workspace settings](https://code.visualstudio.com/docs/getstarted/settings). The setting you should modify is `"C_Cpp.intelliSenseEngine"`. There are two values for this setting:
* `"Default"` - use Visual Studio's IntelliSense engine
* `"Tag Parser"` - use the "fuzzy" IntelliSense engine
### See Also
[Configuring includePath for better IntelliSense results](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/Getting%20started.md)
[**c_cpp_properties.json** reference guide](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/c_cpp_properties.json.md)
+19 -17
View File
@@ -1,6 +1,8 @@
For developers using MinGW on Windows, we recommend you start with the following **c_cpp_properties.json** template. Select "C/Cpp: Edit Configurations" from the command palette to create this file if you haven't already.
```
Note that you may have to change the MinGW version number to match what you have installed. Eg. `C:/MinGW/lib/gcc/mingw32/5.3.0/` instead of `C:/MinGW/lib/gcc/mingw32/6.3.0/`.
```json
{
"configurations": [
{
@@ -8,23 +10,23 @@ For developers using MinGW on Windows, we recommend you start with the following
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include/c++",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include/c++/mingw32",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include/c++/backward",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++/mingw32",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++/backward",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include",
"C:/MinGW/include",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include-fixed"
"C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed"
],
"defines": [
"_DEBUG",
"UNICODE",
"__GNUC__=5",
"__GNUC__=6",
"__cdecl=__attribute__((__cdecl__))"
],
"browse": {
"path": [
"C:/MinGW/lib/gcc/mingw32/5.3.0/include",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include-fixed",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed",
"C:/MinGW/include/*"
],
"limitSymbolsToIncludedHeaders": true,
@@ -35,11 +37,11 @@ For developers using MinGW on Windows, we recommend you start with the following
}
```
The `includePath` above includes the system header paths that gcc uses in version 5.3.0 for C++ projects and matches the output of `gcc -v -E -x c++ -`. The `intelliSenseMode` should be set to **"clang-x64"** to get MinGW projects to work properly with IntelliSense. The `__GNUC__=#` define should match the major version of the toolchain in your installation (5 in this example).
The `includePath` above includes the system header paths that gcc uses in version 6.3.0 for C++ projects and matches the output of `gcc -v -E -x c++ -`. The `intelliSenseMode` should be set to **"clang-x64"** to get MinGW projects to work properly with IntelliSense. The `__GNUC__=#` define should match the major version of the toolchain in your installation (6 in this example).
For C projects, simply remove the c++ lines:
For C projects, simply remove the C++ lines:
```
```json
{
"configurations": [
{
@@ -47,20 +49,20 @@ For C projects, simply remove the c++ lines:
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include",
"C:/MinGW/include",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include-fixed"
"C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed"
],
"defines": [
"_DEBUG",
"UNICODE",
"__GNUC__=5",
"__GNUC__=6",
"__cdecl=__attribute__((__cdecl__))"
],
"browse": {
"path": [
"C:/MinGW/lib/gcc/mingw32/5.3.0/include",
"C:/MinGW/lib/gcc/mingw32/5.3.0/include-fixed",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include",
"C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed",
"C:/MinGW/include/*"
],
"limitSymbolsToIncludedHeaders": true,
@@ -1,75 +1,139 @@
For developers using the Windows Subsystem for Linux, we recommend you start with the following **c_cpp_properties.json** template. Select "C/Cpp: Edit Configurations" from the command palette to create this file if you haven't already.
# Windows Subsystem for Linux
```
{
"name": "WSL",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"${localappdata}/lxss/rootfs/usr/include/c++/5",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5",
"${localappdata}/lxss/rootfs/usr/include/c++/5/backward",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/lxss/rootfs/usr/local/include",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/lxss/rootfs/usr/include"
],
"defines": [
"__linux__",
"__x86_64__"
],
"browse": {
"path": [
"${localappdata}/lxss/rootfs/usr/include/c++/5",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/lxss/rootfs/usr/local/include",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/lxss/rootfs/usr/include/*"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
To use the Windows Subsystem for Linux with this extension you need to add a configuration to your **c_cpp_properties.json** file which adds the necessary header paths from within the WSL filesystem to the `includePath`.
Select "C/Cpp: Edit Configurations" from the command palette to create the **c_cpp_properties.json** file if you haven't already.
## Release
For developers using Ubuntu with the current version of WSL released with the Fall Creators Update, you can add the following configuration template to your **c_cpp_properties.json** file.
```json
{
"name": "WSL",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu/c++/5",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5/backward",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include"
],
"defines": [
"__linux__",
"__x86_64__"
],
"browse": {
"path": [
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu/c++/5",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/*"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
```
The `includePath` above includes the system header paths that gcc uses for C++ projects and matches the output of `gcc -v -E -x c++ - < /dev/null`. The intelliSenseMode should be set to **"clang-x64"** to get WSL projects to work properly with IntelliSense.
For C projects, simply remove the c++ lines:
Note that `${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/` is the path to the root of the Ubuntu filesystem. This will be different if you are using a different distro. You can discover the paths to your distro's filesystem by using this handy PowerShell command:
```Powershell
PS R:\> ($(get-appxpackage).PackageFamilyName | findstr /i 'SUSE Ubuntu') -replace '^', "$`{localappdata`}/Packages/"
${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc
${localappdata}/Packages/46932SUSE.openSUSELeap42.2_022rs5jcyhyac
${localappdata}/Packages/46932SUSE.SUSELinuxEnterpriseServer12SP2_022rs5jcyhyac
```
{
"name": "WSL",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/lxss/rootfs/usr/local/include",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/lxss/rootfs/usr/include"
],
"defines": [
"__linux__",
"__x86_64__"
],
"browse": {
"path": [
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/lxss/rootfs/usr/local/include",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/lxss/rootfs/usr/include/*"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
For C projects, simply remove the C++ lines:
```json
{
"name": "WSL",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include"
],
"defines": [
"__linux__",
"__x86_64__"
],
"browse": {
"path": [
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/*"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
```
## Beta
For developers using Bash on Ubuntu on Windows with the beta version of WSL from before the Fall Creators Update, you can add the following configuration template to your **c_cpp_properties.json** file.
```json
{
"name": "WSL (Beta)",
"intelliSenseMode": "clang-x64",
"includePath": [
"${workspaceRoot}",
"${localappdata}/lxss/rootfs/usr/include/c++/5",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5",
"${localappdata}/lxss/rootfs/usr/include/c++/5/backward",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/lxss/rootfs/usr/local/include",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/lxss/rootfs/usr/include"
],
"defines": [
"__linux__",
"__x86_64__"
],
"browse": {
"path": [
"${localappdata}/lxss/rootfs/usr/include/c++/5",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include",
"${localappdata}/lxss/rootfs/usr/local/include",
"${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu",
"${localappdata}/lxss/rootfs/usr/include/*"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
```
The `includePath` above includes the system header paths that gcc uses for C++ projects and matches the output of `gcc -v -E -x c++ - < /dev/null`. The intelliSenseMode should be set to **"clang-x64"** to get WSL projects to work properly with IntelliSense.
Note that `${localappdata}/lxss/rootfs/` is the path to the root of the filesystem for Bash on Ubuntu on Windows.
For C projects, simply remove the C++ lines as in the previous example.
---
With these configurations, you should be all set up to use the new IntelliSense engine for linting, memberlist autocomplete, and quick info (tooltips). Add `"C_Cpp.intelliSenseEngine": "Default"` to your **settings.json** file to try out the new IntelliSense engine.
And remember to [heed the warnings of the Windows team about not creating or editing Linux files from a Windows app](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)!
And remember to [heed the warnings of the Windows team about not creating or editing Linux files from a Windows app](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)!
@@ -1,47 +1,84 @@
# c_cpp_properties.json Reference Guide
# `c_cpp_properties.json` Reference Guide
### Example:
```
### Example
```json
{
"configurations": [
{
"name": "Win32",
"intelliSenseMode": "msvc-x64",
"includePath": [ "${workspaceRoot}" ],
"includePath": [ "${workspaceFolder}" ],
"macFrameworkPath": [ "/System/Library/Frameworks" ],
"defines": [ "FOO", "BAR=100" ],
"forcedInclude": [ "${workspaceFolder}/include/config.h" ],
"compilerPath": "/usr/bin/clang",
"cStandard": "c11",
"cppStandard": "c++17",
"compileCommands": "/path/to/compile_commands.json",
"browse": {
"path": [ "${workspaceRoot}" ],
"path": [ "${workspaceFolder}" ],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 2
"version": 3
}
```
## Top-level properties
**configurations**: An array of configuration objects that provide the IntelliSense engine with information about your project and your preferences. By default, the extension creates 3 configurations for you, one each for Linux, Mac, and Windows, but it is not required to keep them all. You may also add additional configurations if necessary.
* #### `configurations`
An array of configuration objects that provide the IntelliSense engine with information about your project and your preferences. By default, the extension creates 3 configurations for you, one each for Linux, Mac, and Windows, but it is not required to keep them all. You may also add additional configurations if necessary.
**version**: We recommend you don't edit this field. It tracks the current version of the c_cpp_properties.json file so that the extension knows what properties and settings should be present and how to upgrade this file to the latest version.
* #### `version`
We recommend you don't edit this field. It tracks the current version of the **c_cpp_properties.json** file so that the extension knows what properties and settings should be present and how to upgrade this file to the latest version.
## Configuration properties
**name**: A friendly name for the configuration. "Linux", "Mac", and "Win32" are special names that instruct the extension to load that configuration by default on the associated operating system unless additional configurations have been created. The status bar in VS Code will show you which configuration is active. You can also click on the label in the status bar to change the active configuration.
* #### `name`
A friendly name for the configuration. "Linux", "Mac", and "Win32" are special names that instruct the extension to load that configuration by default on the associated operating system unless additional configurations have been created. The status bar in VS Code will show you which configuration is active. You can also click on the label in the status bar to change the active configuration.
**intelliSenseMode**: If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this property determines which mode the IntelliSense engine will run in. `"msvc-x64"` maps to Visual Studio mode with 64-bit pointer sizes. `"clang-x64"` maps to GCC/CLang mode with 64-bit pointer sizes. Windows uses `"msvc-x64"` by default and Linux/Mac use `"clang-x64"` by default.
* #### `intelliSenseMode`
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this property determines which mode the IntelliSense engine will run in. `"msvc-x64"` maps to Visual Studio mode with 64-bit pointer sizes. `"clang-x64"` maps to GCC/CLang mode with 64-bit pointer sizes. Windows uses `"msvc-x64"` by default and Linux/Mac use `"clang-x64"` by default.
**includePath**: If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of paths will be used by IntelliSense to search for headers included by your source files. This is basically the same as the list of paths you pass to your compiler with the `-I` switch; the IntelliSense engine will not do a recursive search in these paths for includes.
* #### `includePath`
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of paths will be used by IntelliSense to search for headers included by your source files. This is basically the same as the list of paths you pass to your compiler with the `-I` switch; the IntelliSense engine will not do a recursive search in these paths for includes. If a GCC/CLang compiler is specified in the `compilerPath` setting, it is not necessary to list the system include paths in this list.
**defines**: If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of preprocessor symbols will be used by IntelliSense during the compilation of your source files. This is basically the same as the list of symbols you pass to your compiler with the `-D` switch.
* #### `macFrameworkPath`
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of paths will be used by IntelliSense to search for framework headers included by your source files. This is basically the same as the list of paths you pass to your compiler with the `-F` switch; the IntelliSense engine will not do a recursive search in these paths for includes.
**browse**: The set of properties used when `"C_Cpp.intelliSenseEngine"` is set to `"Tag Parser"` (also referred to as "fuzzy" IntelliSense, or the "browse" engine).
* #### `defines`
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, this list of preprocessor symbols will be used by IntelliSense during the compilation of your source files. This is basically the same as the list of symbols you pass to your compiler with the `-D` switch.
* #### `forcedInclude` (optional)
A list of files that should be included before any other characters in the source file are processed. Files are included in the order listed.
* #### `compilerPath` (optional)
The absolute path to the compiler you use to build your project. The extension will query the compiler to determine the system include paths and default defines to use for IntelliSense. Args can be added to modify the includes/defines used, e.g. `-nostdinc++`, `-m32`, etc., but paths with spaces must be surrounded by double quotes (`"`) if args are used.
* #### `cStandard`
The C standard revision to use for IntelliSense in your project.
* #### `cppStandard`
The C++ standard revision to use for IntelliSense in your project.
* #### `compileCommands` (optional)
If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, the includes and defines discovered in this file will be used instead of the values set for `includePath` and `defines`. If the compile commands database does not contain an entry for the translation unit that corresponds to the file you opened in the editor, then a warning message will appear and the extension will use the `includePath` and `defines` settings instead.
*For more information about the file format, see the [Clang documentation](https://clang.llvm.org/docs/JSONCompilationDatabase.html). Some build systems, such as CMake, [simplify generating this file](https://cmake.org/cmake/help/v3.5/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html).*
* #### `browse`
The set of properties used when `"C_Cpp.intelliSenseEngine"` is set to `"Tag Parser"` (also referred to as "fuzzy" IntelliSense, or the "browse" engine). These properties are also used by the Go To Definition/Declaration features, or when the "Default" IntelliSense engine is unable to resolve the #includes in your source files.
### Browse properties
**path**: This list of paths will be used by the Tag Parser to search for headers included by your source files. The Tag Parser will automatically search all subfolders in these paths unless the path ends with a `/*` or `\*`. For example, `/usr/include` directs the Tag Parser to search the `include` folder and its subfolders for headers while `/usr/include/*` directs the Tag Parser not to look in any subfolders of `/usr/include`.
* #### `path`
This list of paths will be used by the Tag Parser to search for headers included by your source files. The Tag Parser will automatically search all subfolders in these paths unless the path ends with a `/*` or `\*`. For example, `/usr/include` directs the Tag Parser to search the `include` folder and its subfolders for headers while `/usr/include/*` directs the Tag Parser not to look in any subfolders of `/usr/include`.
**limitSymbolsToIncludedHeaders**: When true, the Tag Parser will only parse code files that have been directly or indirectly included by a source file in the ${workspaceRoot}. When false, the Tag Parser will parse all code files found in the paths specified in the **path** list.
* #### `limitSymbolsToIncludedHeaders`
When true, the Tag Parser will only parse code files that have been directly or indirectly included by a source file in `${workspaceRoot}`. When false, the Tag Parser will parse all code files found in the paths specified in the **path** list.
**databaseFilename**: When set, this instructs the extension to save the Tag Parser's symbol database somewhere other than the workspace's default storage location. If a relative path is specified, it will be made relative to the workspace's default storage location, not the workspace folder itself. The ${workspaceRoot} variable can be used to specify a path relative to the workspace folder (e.g. $[workspaceRoot}/.vscode/browse.vc.db)
* #### `databaseFilename`
When set, this instructs the extension to save the Tag Parser's symbol database somewhere other than the workspace's default storage location. If a relative path is specified, it will be made relative to the workspace's default storage location, not the workspace folder itself. The `${workspaceRoot}` variable can be used to specify a path relative to the workspace folder (e.g. `$[workspaceRoot}/.vscode/browse.vc.db`)
+3
View File
@@ -0,0 +1,3 @@
*.sh text eol=lf
OpenDebugAD7 text eol=lf
link-binaries text eol=lf
+20
View File
@@ -0,0 +1,20 @@
# ignore dependency packages
node_modules
# ignore compliled typescript
out
# ignore downloaded extension files and folders
server
debugAdapters
LLVM
bin/Microsoft.VSCode.CPP.*
# ignore lock files
install.lock
# ignore generated packages
*.vsix
# ignore vscode test
.vscode-test/
+59
View File
@@ -0,0 +1,59 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "npm"
},
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "npm"
},
{
"name": "Node Attach",
"type": "node",
"request": "attach",
"port": 5858
},
{
"name": "Launch Integration Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/test/integrationTests/testAssets/SimpleCppProject",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
]
},
]
}
+10
View File
@@ -0,0 +1,10 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
"typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
}
+30
View File
@@ -0,0 +1,30 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "0.1.0",
// we want to run npm
"command": "npm",
// the command is a shell script
"isShellCommand": true,
// show the output window only if unrecognized errors occur.
"showOutput": "silent",
// we run the custom script "compile" as defined in package.json
"args": ["run", "compile", "--loglevel", "silent"],
// The tsc compiler is started in watching mode
"isWatching": true,
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
"problemMatcher": "$tsc-watch"
}
+14
View File
@@ -0,0 +1,14 @@
obj/**
.vscode/**
typings/**
out/test/**
test/**
src/**
**/*.map
.gitignore
tsconfig.json
CMakeLists.txt
debugAdapters/install.lock*
out/src/Debugger/copyScript.js
tools/**
notices/**
+351
View File
@@ -0,0 +1,351 @@
# C/C++ for Visual Studio Code Change Log
## Version 0.16.1: March 30, 2018
* Fix random deadlock caused by logging code on Linux/Mac. [#1759](https://github.com/Microsoft/vscode-cpptools/issues/1759)
* Fix compiler from `compileCommands` not being queried for includes/defines if `compilerPath` isn't set on Windows. [#1754](https://github.com/Microsoft/vscode-cpptools/issues/1754)
* Fix OSX `UseShellExecute` I/O bug. [#1756](https://github.com/Microsoft/vscode-cpptools/issues/1756)
* Invalidate partially unzipped files from package manager. [#1757](https://github.com/Microsoft/vscode-cpptools/issues/1757)
## Version 0.16.0: March 28, 2018
* Enable autocomplete for local and global scopes. [#13](https://github.com/Microsoft/vscode-cpptools/issues/13)
* Add a setting to define multiline comment patterns: `C_Cpp.commentContinuationPatterns`. [#1100](https://github.com/Microsoft/vscode-cpptools/issues/1100), [#1539](https://github.com/Microsoft/vscode-cpptools/issues/1539)
* Add a setting to disable inactive region highlighting: `C_Cpp.dimInactiveRegions`. [#1592](https://github.com/Microsoft/vscode-cpptools/issues/1592)
* Add `forcedInclude` configuration setting. [#852](https://github.com/Microsoft/vscode-cpptools/issues/852)
* Add `compilerPath`, `cStandard`, and `cppStandard` configuration settings, and query gcc/clang-based compilers for default defines. [#1293](https://github.com/Microsoft/vscode-cpptools/issues/1293), [#1251](https://github.com/Microsoft/vscode-cpptools/issues/1251), [#1448](https://github.com/Microsoft/vscode-cpptools/issues/1448), [#1465](https://github.com/Microsoft/vscode-cpptools/issues/1465), [#1484](https://github.com/Microsoft/vscode-cpptools/issues/1484)
* Fix text being temporarily gray when an inactive region is deleted. [Microsoft/vscode#44872](https://github.com/Microsoft/vscode/issues/44872)
* Add support for `${workspaceFolder}` variable in **c_cpp_properties.json**. [#1392](https://github.com/Microsoft/vscode-cpptools/issues/1392)
* Fix IntelliSense not updating in source files after dependent header files are changed. [#1501](https://github.com/Microsoft/vscode-cpptools/issues/1501)
* Change database icon to use the `statusBar.foreground` color. [#1638](https://github.com/Microsoft/vscode-cpptools/issues/1638)
* Enable C++/CLI IntelliSense mode via adding the `/clr` arg to the `compilerPath`. [#1596](https://github.com/Microsoft/vscode-cpptools/issues/1596)
* Fix delay in language service activation caused by **cpptools.json** downloading. [#1640](https://github.com/Microsoft/vscode-cpptools/issues/1640)
* Fix debugger failure when a single quote is in the path. [#1554](https://github.com/Microsoft/vscode-cpptools/issues/1554)
* Fix terminal stdout and stderr redirection to not send to VS Code. [#1348](https://github.com/Microsoft/vscode-cpptools/issues/1348)
* Fix blank config and endless "Initializing..." if the file watcher limit is hit when using `compileCommands`. [PR #1709](https://github.com/Microsoft/vscode-cpptools/pull/1709)
* Fix error squiggles re-appearing after editing then closing a file. [#1712](https://github.com/Microsoft/vscode-cpptools/issues/1712)
* Show error output from clang-format. [#1259](https://github.com/Microsoft/vscode-cpptools/issues/1259)
* Fix `add_expression_to_index` crash (most frequent crash in 0.15.0). [#1396](https://github.com/Microsoft/vscode-cpptools/issues/1396)
* Fix incorrect error squiggle `explicitly instantiated more than once`. [#871](https://github.com/Microsoft/vscode-cpptools/issues/871)
## Version 0.15.0: February 15, 2018
* Add colorization for inactive regions. [#1466](https://github.com/Microsoft/vscode-cpptools/issues/1466)
* Fix 3 highest hitting crashes. [#1137](https://github.com/Microsoft/vscode-cpptools/issues/1137), [#1337](https://github.com/Microsoft/vscode-cpptools/issues/1337), [#1497](https://github.com/Microsoft/vscode-cpptools/issues/1497)
* Update IntelliSense compiler (bug fixes and more C++17 support). [#1067](https://github.com/Microsoft/vscode-cpptools/issues/1067), [#1313](https://github.com/Microsoft/vscode-cpptools/issues/1313)
* Fix duplicate `cannot open source file` errors. [#1469](https://github.com/Microsoft/vscode-cpptools/issues/1469)
* Fix `Go to Symbol in File...` being slow for large workspaces. [#1472](https://github.com/Microsoft/vscode-cpptools/issues/1472)
* Fix stuck processes during shutdown. [#1474](https://github.com/Microsoft/vscode-cpptools/issues/1474)
* Fix error popup appearing with non-workspace files when using `compile_commands.json`. [#1475](https://github.com/Microsoft/vscode-cpptools/issues/1475)
* Fix snippet completions being blocked after `#`. [#1531](https://github.com/Microsoft/vscode-cpptools/issues/1531)
* Add more macros to `cpp.hint` (fixing missing symbols).
* Add `__CHAR_BIT__=8` to default defines on Mac. [#1510](https://github.com/Microsoft/vscode-cpptools/issues/1510)
* Added support for config variables to `c_cpp_properties.json`. [#314](https://github.com/Microsoft/vscode-cpptools/issues/314)
* Joshua Cannon (@thejcannon) [PR #1529](https://github.com/Microsoft/vscode-cpptools/pull/1529)
* Define `_UNICODE` by default on Windows platforms. [#1538](https://github.com/Microsoft/vscode-cpptools/issues/1538)
* Charles Milette (@sylveon) [PR #1540](https://github.com/Microsoft/vscode-cpptools/pull/1540)
## Version 0.14.6: January 17, 2018
* Fix tag parser failing (and continuing to fail after edits) when it shouldn't. [#1367](https://github.com/Microsoft/vscode-cpptools/issues/1367)
* Fix tag parser taking too long due to redundant processing. [#1288](https://github.com/Microsoft/vscode-cpptools/issues/1288)
* Fix debugging silently failing the 1st time if a C/C++ file isn't opened. [#1366](https://github.com/Microsoft/vscode-cpptools/issues/1366)
* Skip automatically adding to `files.associations` if it matches an existing glob pattern or if `C_Cpp.autoAddFileAssociations` is `false`. [#722](https://github.com/Microsoft/vscode-cpptools/issues/722)
* The debugger no longer requires an extra reload. [#1362](https://github.com/Microsoft/vscode-cpptools/issues/1362)
* Fix incorrect "Warning: Expected file ... is missing" message after installing on Linux. [#1334](https://github.com/Microsoft/vscode-cpptools/issues/1334)
* Fix "Include file not found" messages not re-appearing after settings changes. [#1363](https://github.com/Microsoft/vscode-cpptools/issues/1363)
* Performance improvements with `browse.path` parsing, and stop showing "Parsing files" when there's no actual parsing. [#1393](https://github.com/Microsoft/vscode-cpptools/issues/1393)
* Fix crash when settings with the wrong type are used. [#1396](https://github.com/Microsoft/vscode-cpptools/issues/1396)
* Allow semicolons in `browse.path`. [#1415](https://github.com/Microsoft/vscode-cpptools/issues/1415)
* Fix to handle relative pathing in source file paths properly when normalizing. [#1228](https://github.com/Microsoft/vscode-cpptools/issues/1228)
* Fix delay in language service activation caused by cpptools.json downloading. [#1429](https://github.com/Microsoft/vscode-cpptools/issues/1429)
* Add `C_Cpp.workspaceParsingPriority` setting to enable using less than 100% CPU during parsing of workspace files.
* Add `C_Cpp.exclusionPolicy` default to `checkFolders` to avoid expensive `files.exclude` checking on every file.
## Version 0.14.5: December 18, 2017
* Fix for stackwalk `NullReferenceException`. [#1339](https://github.com/Microsoft/vscode-cpptools/issues/1339)
* Fix for `-isystem` (or `-I`) not being used in `compile_commands.json` if there's a space after it. [#1343](https://github.com/Microsoft/vscode-cpptools/issues/1343)
* Fix for header switching from `.cc` to `.hpp` files (and other cases). [#1341](https://github.com/Microsoft/vscode-cpptools/issues/1341)
* Fix reload prompts not appearing in debugging scenarios (after the initial installation). [#1344](https://github.com/Microsoft/vscode-cpptools/issues/1344)
* Add a "wait" message when commands are invoked during download/installation. [#1344](https://github.com/Microsoft/vscode-cpptools/issues/1344)
* Prevent blank "C/C++ Configuration" from appearing when debugging is started but the language service is not. [#1353](https://github.com/Microsoft/vscode-cpptools/issues/1353)
## Version 0.14.4: December 11, 2017
* Enable the language service processes to run without glibc 2.18. [#19](https://github.com/Microsoft/vscode-cpptools/issues/19)
* Enable the language service processes to run on 32-bit Linux. [#424](https://github.com/Microsoft/vscode-cpptools/issues/424)
* Fix extension process not working on Windows with non-ASCII usernames. [#1319](https://github.com/Microsoft/vscode-cpptools/issues/1319)
* Fix IntelliSense on single processor VMs. [#1321](https://github.com/Microsoft/vscode-cpptools/issues/1321)
* Enable offline installation of the extension. [#298](https://github.com/Microsoft/vscode-cpptools/issues/298)
* Add support for `-isystem` in `compile_commands.json`. [#1156](https://github.com/Microsoft/vscode-cpptools/issues/1156)
* Remember the selected configuration across launches of VS Code. [#1273](https://github.com/Microsoft/vscode-cpptools/issues/1273)
* Fix 'Add Configuration...` entries not appearing if the extension wasn't previously activated. [#1287](https://github.com/Microsoft/vscode-cpptools/issues/1287)
* Add `(declaration)` to declarations in the navigation list. [#1311](https://github.com/Microsoft/vscode-cpptools/issues/1311)
* Fix function definition body not being visible after navigation. [#1311](https://github.com/Microsoft/vscode-cpptools/issues/1311)
* Improve performance for fetching call stacks with large arguments. [#363](https://github.com/Microsoft/vscode-cpptools/issues/363)
## Version 0.14.3: November 27, 2017
* Fix for disappearing parameter hints tooltip. [#1165](https://github.com/Microsoft/vscode-cpptools/issues/1165)
* Fix for parameter hints only showing up after the opening parenthesis. [#902](https://github.com/Microsoft/vscode-cpptools/issues/902), [#819](https://github.com/Microsoft/vscode-cpptools/issues/819)
* Fix for customer reported crashes in the TypeScript extension code. [#1240](https://github.com/Microsoft/vscode-cpptools/issues/1240), [#1245](https://github.com/Microsoft/vscode-cpptools/issues/1245)
* Fix .browse.VC-#.db files being unnecessarily created when an shm file exists. [#1234](https://github.com/Microsoft/vscode-cpptools/issues/1234)
* Fix language service to only activate after a C/C++ file is opened or a C/Cpp command is used (not onDebug).
* Fix database resetting if shutdown got blocked by an IntelliSense operation. [#1260](https://github.com/Microsoft/vscode-cpptools/issues/1260)
* Fix deadlock that can occur when switching configurations.
* Fix browse.databaseFilename changing not taking effect until a reload.
## Version 0.14.2: November 9, 2017
* Unsupported Linux clients sending excessive telemetry when the language server fails to start. [#1227](https://github.com/Microsoft/vscode-cpptools/issues/1227)
## Version 0.14.1: November 9, 2017
* Add support for multi-root workspaces. [#1070](https://github.com/Microsoft/vscode-cpptools/issues/1070)
* Fix files temporarily being unsavable after Save As and other scenarios on Windows. [Microsoft/vscode#27329](https://github.com/Microsoft/vscode/issues/27329)
* Fix files "permanently" being unsavable if the IntelliSense process launches during tag parsing of the file. [#1040](https://github.com/Microsoft/vscode-cpptools/issues/1040)
* Show pause and resume parsing commands after clicking the database icon. [#1141](https://github.com/Microsoft/vscode-cpptools/issues/1141)
* Don't show the install output unless an error occurs. [#1160](https://github.com/Microsoft/vscode-cpptools/issues/1160)
* Fix bug with `${workspaceRoot}` symbols not getting added if a parent folder is in the `browse.path`. [#1185](https://github.com/Microsoft/vscode-cpptools/issues/1185)
* Fix `Add configuration` C++ launch.json on Insiders. [#1191](https://github.com/Microsoft/vscode-cpptools/issues/1191)
* Fix extension restart logic so that the extension doesn't get stuck on "Initializing..." when it crashes. [#893](https://github.com/Microsoft/vscode-cpptools/issues/893)
* Remove the Reload window prompt after installation (it only appears if launch.json is active).
* Prevent browse database from being reset if shutdown takes > 1 second.
* Remove the `UnloadLanguageServer` command and the `clang_format_formatOnSave` setting.
* Fix bugs with include path suggestions.
* Fix max files to parse status number being too big, due to including non-`${workspaceRoot}` files.
* Update default `launch.json` configurations to use `${workspaceFolder}` instead of `${workspaceRoot}`.
* Update how default initial configurations for `launch.json` are being provided. [Microsoft/vscode#33794](https://github.com/Microsoft/vscode/issues/33794)
* Add support for normalizing source file locations. (Windows [#272](https://github.com/Microsoft/vscode-cpptools/issues/272)), (Mac OS X [#1095](https://github.com/Microsoft/vscode-cpptools/issues/1095))
## Version 0.14.0: October 19, 2017
* Add support for `compile_commands.json`. [#156](https://github.com/Microsoft/vscode-cpptools/issues/156)
* Fix crash with signature help. [#1076](https://github.com/Microsoft/vscode-cpptools/issues/1076)
* Skip parsing redundant browse.path directories. [#1106](https://github.com/Microsoft/vscode-cpptools/issues/1106)
* Fix `limitSymbolsToIncludedHeaders` not working with single files. [#1109](https://github.com/Microsoft/vscode-cpptools/issues/1109)
* Add logging to Output window. Errors will be logged by default. Verbosity is controlled by the `"C_Cpp.loggingLevel"` setting.
* Add new database status bar icon for "Indexing" or "Parsing" with progress numbers, and the previous flame icon is now just for "Updating IntelliSense".
* Stop showing `(Global Scope)` if there's actually an error in identifying the correct scope.
* Fix crash with the IntelliSense process when parsing certain template code (the most frequently hit crash).
* Fix main thread being blocked while searching for files to remove after changing `files.exclude`.
* Fix incorrect code action include path suggestion when a folder comes after "..".
* Fix a crash on shutdown.
## Version 0.13.1: October 5, 2017
* Delete unused symbol databases when `browse.databaseFilename` in `c_cpp_properties.json` changes. [#558](https://github.com/Microsoft/vscode-cpptools/issues/558)
* Fix infinite loop during IntelliSense parsing. [#981](https://github.com/Microsoft/vscode-cpptools/issues/981)
* Fix database resetting due to the extension process not shutting down fast enough. [#1060](https://github.com/Microsoft/vscode-cpptools/issues/1060)
* Fix crash with document highlighting [#1076](https://github.com/Microsoft/vscode-cpptools/issues/1076)
* Fix bug that could cause symbols to be missing when shutdown occurs during tag parsing.
* Fix bug that could cause included files to not be reparsed if they were modified after the initial parsing.
* Fix potential buffer overrun when logging is enabled.
* Add logging to help diagnose cause of document corruption after formatting.
## Version 0.13.0: September 25, 2017
* Reference highlighting is now provided by the extension for both IntelliSense engines.
* Parameter help is now provided by both IntelliSense engines.
* Light bulbs (code actions) for #include errors now suggest potential paths to add to the `includePath` based on a recursive search of the `browse.path`. [#846](https://github.com/Microsoft/vscode-cpptools/issues/846)
* Browse database now removes old symbols when `browse.path` changes. [#262](https://github.com/Microsoft/vscode-cpptools/issues/262)
* Add `*` on new lines after a multiline comment with `/**` is started. [#579](https://github.com/Microsoft/vscode-cpptools/issues/579)
* Fix Go to Definition, completion, and parameter hints for partially scoped members. [#635](https://github.com/Microsoft/vscode-cpptools/issues/635)
* Fix bug in `macFrameworkPath` not resolving variables.
## Version 0.12.4: September 12, 2017
* Fix a crash in IntelliSense for users with non-ASCII user names (Windows-only). [#910](https://github.com/Microsoft/vscode-cpptools/issues/910)
* Add `macFrameworkPath` to `c_cpp_properties.json`. [#970](https://github.com/Microsoft/vscode-cpptools/issues/970)
* Fix incorrect auto-complete suggestions when using template types with the scope operator `::`. [#988](https://github.com/Microsoft/vscode-cpptools/issues/988)
* Fix potential config file parsing failure. [#989](https://github.com/Microsoft/vscode-cpptools/issues/989)
* Support `${env:VAR}` syntax for environment variables in `c_cpp_properties.json`. [#1000](https://github.com/Microsoft/vscode-cpptools/issues/1000)
* Support semicolon delimiters for include paths in `c_cpp_properties.json` to better support environment variables. [#1001](https://github.com/Microsoft/vscode-cpptools/issues/1001)
* Add `__LITTLE_ENDIAN__=1` to default defines so that "endian.h" is not needed on Mac projects. [#1005](https://github.com/Microsoft/vscode-cpptools/issues/1005)
* Fix for source code files on Windows with incorrect casing. [#984](https://github.com/Microsoft/vscode-cpptools/issues/984)
## Version 0.12.3: August 17, 2017
* Fix regression for paths containing multibyte characters. [#958](https://github.com/Microsoft/vscode-cpptools/issues/958)
* Fix bug with the Tag Parser completion missing results. [#943](https://github.com/Microsoft/vscode-cpptools/issues/943)
* Add /usr/include/machine or i386 to the default Mac `includePath`. [#944](https://github.com/Microsoft/vscode-cpptools/issues/944)
* Add a command to reset the Tag Parser database. [#601](https://github.com/Microsoft/vscode-cpptools/issues/601), [#464](https://github.com/Microsoft/vscode-cpptools/issues/464)
* Fix bug with error-related code actions remaining after the errors are cleared.
* Fix bug with Tag Parser completion not working when :: preceded an identifier.
* Upgrade SQLite (for better reliability and performance).
## Version 0.12.2: August 2, 2017
* Fix bug in our build system causing Windows binaries to build against the wrong version of the Windows SDK. [#325](https://github.com/Microsoft/vscode-cpptools/issues/325)
* Added a gcc problemMatcher. [#854](https://github.com/Microsoft/vscode-cpptools/issues/854)
* Fix bug where .c/.cpp files could get added to `files.associations` as the opposite "cpp"/"c" language after `Go to Definition` on a symbol. [#884](https://github.com/Microsoft/vscode-cpptools/issues/884)
* Remove completion results after `#pragma`. [#886](https://github.com/Microsoft/vscode-cpptools/issues/886)
* Fix a possible infinite loop when viewing Boost sources. [#888](https://github.com/Microsoft/vscode-cpptools/issues/888)
* Fix `Go to Definition` not working for files in `#include_next`. [#906](https://github.com/Microsoft/vscode-cpptools/issues/906)
* Also fix incorrect preprocessor suggestions at the end of a `#include_next`.
* Skip automatically adding to `files.associations` if they already match global patterns. [Microsoft/vscode#27404](https://github.com/Microsoft/vscode/issues/27404)
* Fix a crash with the IntelliSense process (responsible for ~25% of all crashes).
## Version 0.12.1: July 18, 2017
* Fix Tag Parser features not working with some MinGW library code.
* Fix a symbol search crash.
* Fix an IntelliSense engine compiler crash.
* Fix `Go to Declaration` to return `Go to Definition` results if the declarations have no results.
* Fix formatting with non-ASCII characters in the path. [#870](https://github.com/Microsoft/vscode-cpptools/issues/870)
* Fix handling of symbolic links to files on Linux/Mac. [#872](https://github.com/Microsoft/vscode-cpptools/issues/872)
* Move red flame icon to its own section so the configuration text is always readable. [#875](https://github.com/Microsoft/vscode-cpptools/issues/875)
* Remove `addWorkspaceRootToIncludePath` setting and instead make `${workspaceRoot}` in `browse.path` explicit.
* Add `Show Release Notes` command.
* Add `Edit Configurations...` command to the `Select a Configuration...` dropdown.
* Update Microsoft Visual C++ debugger to Visual Studio 2017 released components.
* Fix issue with showing wrong thread. [#550](https://github.com/Microsoft/vscode-cpptools/issues/550)
* Fix issue with binaries compiled with /FASTLINK causing debugger to hang. [#484](https://github.com/Microsoft/vscode-cpptools/issues/484)
* Fix issue in MinGW/Cygwin debugging where stop debugging causes VS Code to hang. [Microsoft/MIEngine#636](https://github.com/Microsoft/MIEngine/pull/636)
## Version 0.12.0: June 26, 2017
* The default IntelliSense engine now provides semantic-aware autocomplete suggestions for `.`, `->`, and `::` operators. [#13](https://github.com/Microsoft/vscode-cpptools/issues/13)
* The default IntelliSense engine now reports the unresolved include files in referenced headers and falls back to the Tag Parser until headers are resolved.
* This behavior can be overridden by setting `"C_Cpp.intelliSenseEngineFallback": "Disabled"`
* Added `"intelliSenseMode"` property to `c_cpp_properties.json` to allow switching between MSVC and Clang modes. [#710](https://github.com/Microsoft/vscode-cpptools/issues/710), [#757](https://github.com/Microsoft/vscode-cpptools/issues/757)
* A crashed IntelliSense engine no longer gives the popup message, and it automatically restarts after an edit to the translation unit occurs.
* Fix the IntelliSense engine to use "c" mode if a C header is opened before the C file.
* Fix a bug which could cause the IntelliSense engine to not update results if changes are made to multiple files of a translation unit.
* Auto `files.association` registers "c" language headers when `Go to Definition` is used in a C file.
* Downloading extension dependencies will retry up to 5 times in the event of a failure. [#694](https://github.com/Microsoft/vscode-cpptools/issues/694)
* Changes to `c_cpp_properties.json` are detected even if file watchers fail.
* Update default IntelliSense options for MSVC mode to make Boost projects work better. [#775](https://github.com/Microsoft/vscode-cpptools/issues/775)
* Fix `Go to Definition` not working until all `browse.path` files are re-scanned. [#788](https://github.com/Microsoft/vscode-cpptools/issues/788)
## Version 0.11.4: June 2, 2017
* Fix for `System.Xml.Serialization.XmlSerializationReader threw an exception` when debugging on Linux. [#792](https://github.com/Microsoft/vscode-cpptools/issues/792)
* Fix for escaping for `${workspaceRoot}` in `launch.json`.
## Version 0.11.3: May 31, 2017
* Fix `x86_64-pc-linux-gnu` and `x86_64-linux-gnu` paths missing from the default `includePath`.
## Version 0.11.2: May 24, 2017
* Revert the default `C_Cpp.intelliSenseEngine` setting back to "Tag Parser" for non-Insiders while we work on improving the migration experience.
## Version 0.11.1: May 19, 2017
* Add keywords to auto-complete (C, C++, or preprocessor). [#120](https://github.com/Microsoft/vscode-cpptools/issues/120)
* Fix non-recursive `browse.path` on Linux/Mac. [#546](https://github.com/Microsoft/vscode-cpptools/issues/546)
* Fix .clang-format file not being used on Linux/Mac. [#604](https://github.com/Microsoft/vscode-cpptools/issues/604)
* Stop setting the c/cpp `editor.quickSuggestions` to false. [#606](https://github.com/Microsoft/vscode-cpptools/issues/606)
* We also do a one-time clearing of that user setting, which will also copy any other c/cpp workspace settings to user settings. The workspace setting isn't cleared.
* Fix selection range off by one with `Peek Definition`. [#648](https://github.com/Microsoft/vscode-cpptools/issues/648)
* Upgrade the installed clang-format to 4.0 [#656](https://github.com/Microsoft/vscode-cpptools/issues/656)
* Make keyboard shortcuts only apply to c/cpp files. [#662](https://github.com/Microsoft/vscode-cpptools/issues/662)
* Fix autocomplete with qstring.h. [#666](https://github.com/Microsoft/vscode-cpptools/issues/666)
* Fix C files without a ".c" extension from being treated like C++ for `errorSquiggles`. [#673](https://github.com/Microsoft/vscode-cpptools/issues/673)
* Make the C IntelliSense engine use C11 instead of C89. [#685](https://github.com/Microsoft/vscode-cpptools/issues/685)
* Fix bug with clang-format not working with non-trimmed styles. [#691](https://github.com/Microsoft/vscode-cpptools/issues/691)
* Enable the C++ IntelliSense engine to use six C++17 features. [#699](https://github.com/Microsoft/vscode-cpptools/issues/699)
* Add reload prompt when a settings change requires it.
* Prevent non-existent files from being returned in `Go To Definition` results.
## Version 0.11.0: April 24, 2017
* Enabled first IntelliSense features based on the MSVC engine.
* Quick info tooltips and compiler errors are provided by the MSVC engine.
* `C_Cpp.intelliSenseEngine` property controls whether the new engine is used or not.
* `C_Cpp.errorSquiggles` property controls whether compiler errors are made visible in the editor.
* Add `Go to Declaration` and `Peek Declaration`. [#271](https://github.com/Microsoft/vscode-cpptools/issues/271)
* Fix language-specific workspace settings leaking into user settings. [Microsoft/vscode#23118](https://github.com/Microsoft/vscode/issues/23118)
* Fix `files.exclude` not being used in some cases. [#485](https://github.com/Microsoft/vscode-cpptools/issues/485)
* Fix a couple potential references to an undefined `textEditor`. [#584](https://github.com/Microsoft/vscode-cpptools/issues/584)
* Move changes from `README.md` to `CHANGELOG.md`. [#586](https://github.com/Microsoft/vscode-cpptools/issues/586)
* Fix crash on Mac/Linux when building the browse database and `nftw` fails. [#591](https://github.com/Microsoft/vscode-cpptools/issues/591)
* Add `Alt+N` keyboard shortcut for navigation. [#593](https://github.com/Microsoft/vscode-cpptools/issues/593)
* Fix autocomplete crash when the result has an invalid UTF-8 character. [#608](https://github.com/Microsoft/vscode-cpptools/issues/608)
* Fix symbol search crash with `_` symbol. [#611](https://github.com/Microsoft/vscode-cpptools/issues/611)
* Fix the `Edit Configurations` command when '#' is in the workspace root path. [#625](https://github.com/Microsoft/vscode-cpptools/issues/625)
* Fix clang-format `TabWidth` not being set when formatting with the `Visual Studio` style. [#630](https://github.com/Microsoft/vscode-cpptools/issues/630)
* Enable `clang_format_fallbackStyle` to be a custom style. [#641](https://github.com/Microsoft/vscode-cpptools/issues/641)
* Fix potential `undefined` references when attaching to a process. [#650](https://github.com/Microsoft/vscode-cpptools/issues/650)
* Fix `files.exclude` not working on Mac. [#653](https://github.com/Microsoft/vscode-cpptools/issues/653)
* Fix crashes during edit and hover with unexpected UTF-8 data. [#654](https://github.com/Microsoft/vscode-cpptools/issues/654)
## Version 0.10.5: March 21, 2017
* Fix a crash that randomly occurred when the size of a document increased. [#430](https://github.com/Microsoft/vscode-cpptools/issues/430)
* Fix for browsing not working for Linux/Mac stdlib.h functions. [#578](https://github.com/Microsoft/vscode-cpptools/issues/578)
* Additional fixes for switch header/source not respecting `files.exclude`. [#485](https://github.com/Microsoft/vscode-cpptools/issues/485)
* Made `editor.quickSuggestions` dependent on `C_Cpp.autocomplete`. [#572](https://github.com/Microsoft/vscode-cpptools/issues/572)
* We recommend you close and reopen your settings.json file anytime you change the `C_Cpp.autocomplete` setting. [More info here](https://github.com/Microsoft/vscode-cpptools/releases).
## Version 0.10.4: March 15, 2017
* Fix a crash in signature help. [#525](https://github.com/microsoft/vscode-cpptools/issues/525)
* Re-enable switch header/source when no workspace folder is open. [#541](https://github.com/microsoft/vscode-cpptools/issues/541)
* Fix inline `clang_format_style`. [#536](https://github.com/microsoft/vscode-cpptools/issues/536)
* Some other minor bug fixes.
## Version 0.10.3: March 7, 2017
* Database stability fixes.
* Added enums to the C_Cpp settings so the possible values are displayed in the dropdown.
* Change from `${command.*}` to `${command:*}`. [#521](https://github.com/Microsoft/vscode-cpptools/issues/521)
* Current execution row was not highlighting in debug mode when using gdb. [#526](https://github.com/microsoft/vscode-cpptools/issues/526)
## Version 0.10.2: March 1, 2017
* New `addWorkspaceRootToIncludePath` setting allows users to disable automatic parsing of all files under the workspace root. [#374](https://github.com/Microsoft/vscode-cpptools/issues/374)
* The cpp.hint file was missing from the vsix package. [#508](https://github.com/Microsoft/vscode-cpptools/issues/508)
* Switch header/source now respects `files.exclude`. [#485](https://github.com/Microsoft/vscode-cpptools/issues/485)
* Switch header/source performance improvements. [#231](https://github.com/Microsoft/vscode-cpptools/issues/231)
* Switch header/source now appears in the right-click menu.
* Improvements to signature help.
* Various other bug fixes.
## Version 0.10.1: February 9, 2017
* Bug fixes.
## Version 0.10.0: January 24, 2017
* Suppressed C++ language auto-completion inside a C++ comment or string literal. TextMate based completion is still available.
* Fixed bugs regarding the filtering of files and symbols, including:
* Find-symbol now excludes symbols found in `files.exclude` or `search.exclude` files
* Go-to-definition now excludes symbols found in `files.exclude` files (i.e. `search.exclude` paths are still included).
* Added option to disable `clang-format`-based formatting provided by this extension via `"C_Cpp.formatting" : "disabled"`
* Added new `pipeTransport` functionality within the `launch.json` to support pipe communications with `gdb/lldb` such as using `plink.exe` or `ssh`.
* Added support for `{command.pickRemoteProcess}` to allow picking of processes for remote pipe connections during `attach` scenarios. This is similar to how `{command.pickProcess}` works for local attach.
* Bug fixes.
## Version 0.9.3: December 8, 2016
* [December update](https://aka.ms/cppvscodedec) for C/C++ extension
* Ability to map source files during debugging using `sourceFileMap` property in `launch.json`.
* Enable pretty-printing by default for gdb users in `launch.json`.
* Bug fixes.
## Version 0.9.2: September 22, 2016
* Bug fixes.
## Version 0.9.1: September 7, 2016
* Bug fixes.
## Version 0.9.0: August 29, 2016
* [August update](https://blogs.msdn.microsoft.com/vcblog/2016/08/29/august-update-for-the-visual-studio-code-cc-extension/) for C/C++ extension.
* Debugging for Visual C++ applications on Windows (Program Database files) is now available.
* `clang-format` is now automatically installed as a part of the extension and formats code as you type.
* `clang-format` options have been moved from c_cpp_properties.json file to settings.json (File->Preferences->User settings).
* `clang-format` fallback style is now set to 'Visual Studio'.
* Attach now requires a request type of `attach` instead of `launch`.
* Support for additional console logging using the keyword `logging` inside `launch.json`.
* Bug fixes.
## Version 0.8.1: July 27, 2016
* Bug fixes.
## Version 0.8.0: July 21, 2016
* [July update](https://blogs.msdn.microsoft.com/vcblog/2016/07/26/july-update-for-the-visual-studio-code-cc-extension/) for C/C++ extension.
* Support for debugging on OS X with LLDB 3.8.0. LLDB is now the default debugging option on OS X.
* Attach to process displays a list of available processes.
* Set variable values through Visual Studio Code's locals window.
* Bug fixes.
## Version 0.7.1: June 27, 2016
* Bug fixes.
## Version 0.7.0: June 20, 2016
* [June Update](https://blogs.msdn.microsoft.com/vcblog/2016/06/01/may-update-for-the-cc-extension-in-visual-studio-code/) for C/C++ extension.
* Bug fixes.
* Switch between header and source.
* Control which files are processed under include path.
## Version 0.6.1: June 03, 2016
* Bug fixes.
## Version 0.6.0: May 24, 2016
* [May update](https://blogs.msdn.microsoft.com/vcblog/2016/07/26/july-update-for-the-visual-studio-code-cc-extension/) for C/C++ extension.
* Support for debugging on OS X with GDB.
* Support for debugging with GDB on MinGW.
* Support for debugging with GDB on Cygwin.
* Debugging on 32-bit Linux now enabled.
* Format code using clang-format.
* Experimental fuzzy auto-completion.
* Bug fixes.
## Version 0.5.0: April 14, 2016
* Usability and correctness bug fixes.
* Simplify installation experience.
* Usability and correctness bug fixes.
+78
View File
@@ -0,0 +1,78 @@
# License
**MICROSOFT PRE-RELEASE SOFTWARE LICENSE TERMS**
**MICROSOFT C/C++ EXTENSION FOR VISUAL STUDIO CODE**
---
These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. They apply to the pre-release software named above. The terms also apply to any Microsoft services or updates for the software, except to the extent those have additional terms.
---
**IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.**
1. **INSTALLATION AND USE RIGHTS.**
You may only use the C/C++ Extension for Visual Studio Code with Visual Studio Code, Visual Studio or Xamarin Studio software to help you develop and test your applications.
2. **TERMS FOR SPECIFIC COMPONENTS.**
**a. Third Party components.** The software may include third party components with separate legal notices or governed by other agreements, as described in the ThirdPartyNotices file accompanying the software. Even if such components are governed by other agreements, the disclaimers and the limitations on and exclusions of damages below also apply.
**b. Package Managers.** The software may include package managers, like Nuget, that give you the option to download other Microsoft and third party software packages to use with your application. Those packages are under their own licenses, and not this agreement. Microsoft does not distribute, license or provide any warranties for any of the third party packages.
3. **DATA**. The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation. There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at https://go.microsoft.com/fwlink/?LinkID=528096. Your use of the software operates as your consent to these practices.
4. **PRE-RELEASE SOFTWARE**. This software is a pre-release version. It may not work the way a final version of the software will. We may change it for the final, commercial version. We also may not release a commercial version.
5. **FEEDBACK**. If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the right to use, share and commercialize your feedback in any way and for any purpose. You will not give feedback that is subject to a license that requires Microsoft to license its software or documentation to third parties because we include your feedback in them. These rights survive this agreement.
6. **SCOPE OF LICENSE**. The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. For more information, see http://www.microsoftvolumelicensing.com/. You may not
* work around any technical limitations in the software;
* reverse engineer, decompile or disassemble the software, or attempt to do so, except and only to the extent required by third party licensing terms governing use of certain open-source components that may be included with the software;
* remove, minimize, block or modify any notices of Microsoft or its suppliers in the software;
* use the software in any way that is against the law; or
* share, publish, rent, or lease the software, or provide the software as a stand-alone hosted as solution for others to use.
7. **EXPORT RESTRICTIONS.** You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users and end use. For further information on export restrictions, visit https://aka.ms/exporting.
8. **SUPPORT SERVICES.** Because this software is “as is,” we may not provide support services for it.
9. **ENTIRE AGREEMENT.** This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.
10. **APPLICABLE LAW.** If you acquired the software in the United States, Washington law applies to interpretation of and claims for breach of this agreement, and the laws of the state where you live apply to all other claims. If you acquired the software in any other country, its laws apply.
11. **CONSUMER RIGHTS; REGIONAL VARIATIONS.** This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you:
**a. Australia.** You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights.
**b. Canada.** If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software.
**c. Germany and Austria.**
**(i)** **Warranty**. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software.
**(ii)** **Limitation of Liability**. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law.
Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence.
12. **DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS-IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.**
13. **LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.**
This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.
It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.
**Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.**
**Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français.**
**EXONÉRATION DE GARANTIE.** Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft naccorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, dadéquation à un usage particulier et dabsence de contrefaçon sont exclues.
**LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES.** Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
Cette limitation concerne:
* tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et
* les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou dune autre faute dans la limite autorisée par la loi en vigueur.
Elle sapplique également, même si Microsoft connaissait ou devrait connaître l’éventualité dun tel dommage. Si votre pays nautorise pas lexclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou lexclusion ci-dessus ne sappliquera pas à votre égard.
**EFFET JURIDIQUE.** Le présent contrat décrit certains droits juridiques. Vous pourriez avoir dautres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas.
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

+27
View File
@@ -0,0 +1,27 @@
# C/C++ for Visual Studio Code
This preview release of the extension adds language support for C/C++ to Visual Studio Code including:
* Language service
* Code Formatting (clang-format)
* Auto-Completion (experimental)
* Symbol Searching
* Go to Definition/Declaration
* Peek Definition/Declaration
* Class/Method Navigation
* Signature Help
* Quick Info (Hover)
* Error Squiggles
* Debugging
* Support for debugging Windows (PDB, Mingw/Cygwin), Linux and OS X applications
* Line by line code stepping
* Breakpoints (including conditional and function breakpoints)
* Variable inspection
* Multi-threaded debugging support
* Core dump debugging support
* Executing GDB or MI commands directly when using 'C++ (GDB/LLDB)' debugging environment
* For help configuring the debugger see [Configuring launch.json for C/C++ debugging](https://github.com/Microsoft/vscode-cpptools/blob/master/launch.md)
on our [GitHub page](https://github.com/Microsoft/vscode-cpptools).
You can find more detailed information about C/C++ support for Visual Studio Code at our [GitHub page](https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation) and our [VS Code documentation page](https://code.visualstudio.com/docs/languages/cpp).
## Contact Us
If you run into any issues or have suggestions for us, please file [issues and suggestions on GitHub](https://github.com/Microsoft/vscode-cpptools/issues). If you havent already provided us feedback, please take this [quick survey](https://www.research.net/r/VBVV6C6) to help shape this extension for your needs.
+258
View File
@@ -0,0 +1,258 @@
<!DOCTYPE html>
<html>
<head>
<STYLE type="text/css">
body {
padding: 10px 20px;
line-height: 22px
}
img {
max-width: 100%;
max-height: 100%
}
a {
text-decoration: none
}
a:focus,
input:focus,
select:focus,
textarea:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px
}
hr {
border: 0;
height: 2px;
border-bottom: 2px solid
}
h1 {
padding-bottom: .3em;
line-height: 1.2;
border-bottom-width: 1px;
border-bottom-style: solid
}
h1,
h2,
h3 {
font-weight: 400
}
a:hover {
text-decoration: underline
}
table {
border-collapse: collapse
}
table > thead > tr > th {
text-align: left
}
table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
padding: 5px 10px
}
blockquote {
margin: 0 7px 0 5px;
padding: 0 16px 0 10px;
border-left: 5px solid
}
code {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-size: 14px;
line-height: 19px
}
.mac code {
font-size: 12px;
line-height: 18px
}
code > div {
padding: 16px;
border-radius: 3px;
overflow: auto
}
.monaco-tokenized-source {
white-space: pre
}
/** Theming */
.vscode-light {
color: #1e1e1e
}
.vscode-dark {
color: #ddd
}
.vscode-high-contrast {
color: #fff
}
.vscode-light code {
color: #a31515
}
.vscode-dark code {
color: #d7ba7d
}
.vscode-light code > div {
background-color: rgba(220, 220, 220, .4)
}
.vscode-dark code > div {
background-color: rgba(10, 10, 10, .4)
}
.vscode-high-contrast code > div {
background-color: #000
}
.vscode-high-contrast h1 {
border-color: #000
}
.vscode-light table > thead > tr > th {
border-color: rgba(0, 0, 0, .69)
}
.vscode-dark table > thead > tr > th {
border-color: rgba(255, 255, 255, .69)
}
.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
border-color: rgba(0, 0, 0, .18)
}
.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
border-color: rgba(255, 255, 255, 0.18)
}
.vscode-light blockquote,
.vscode-dark blockquote {
background: rgba(127, 127, 127, .1);
border-color: rgba(0, 122, 204, .5)
}
.vscode-high-contrast blockquote {
background: transparent;
border-color: #fff
}
.main-content {
width: 65%;
vertical-align: top
}
.sidebar {
vertical-align: top
}
.footer {
padding: 25px;
text-align: center
}
.vscode-light table > tbody > tr > td.sidebar {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 10px
}
.vscode-dark table > tbody > tr > td.sidebar {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px
}
.vscode-light a {
color: #4080D0
}
.vscode-dark a {
color: #a2c1e8
}
</STYLE>
</head>
<body>
<div>
<div>
<h1>Microsoft C/C++ Extension for VS Code</h1>
</div>
<table>
<tr>
<td class="main-content">
<table>
<tr>
<td>
<div>
<h2 class="caption">March 2018 Update</h2>
<div>Thank you for installing the C/C++ extension. In the March update, we finished our implementation of autocomplete for the default IntelliSense engine. We also added additional configuration settings for forced include files, specifying your compiler path and language standard to improve IntelliSense accuracy.<br />
<br />
Additional features and bug fixes are detailed in the <a href="https://github.com/Microsoft/vscode-cpptools/releases">full release notes</a>.</div>
</div>
</td>
</tr>
</table>
</td>
<td class="sidebar">
<table>
<tr>
<td>
<div>
<h3 class="caption">Getting Started</h3>
<div><a href="https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/Getting%20started%20with%20IntelliSense%20configuration.md">Configuring IntelliSense</a></div>
<div><a href="https://github.com/Microsoft/vscode-cpptools/blob/master/launch.md">Configuring Debugging</a></div>
<div><a href="https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/MinGW.md">IntelliSense for MinGW projects</a></div>
<div><a href="https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/Windows%20Subsystem%20for%20Linux.md">IntelliSense for Windows Subsystem for Linux projects</a></div>
</div>
</td>
</tr>
<tr>
<td>
<div>
<h3 class="caption">Blog Posts</h3>
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/02/20/visual-studio-code-cc-extension-feb-2018-update/">February 2018 Update</a></div>
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2018/01/17/visual-studio-code-cc-extension-jan-2018-update/">January 2018 Update</a></div>
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2017/12/11/visual-studio-code-cc-extension-dec-2017-update-support-for-more-linux-distros/">December 2017 Update</a></div>
<div><a href="https://blogs.msdn.microsoft.com/vcblog/2016/03/31/cc-extension-for-visual-studio-code/">C/C++ Extension anouncement</a></div>
</div>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="2" class="footer">
<div>
Having trouble with the extension? -
<a href="https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation">Browse the documentation</a> -
<a href="https://www.github.com/Microsoft/vscode-cpptools/issues">Report an issue</a>
</div>
</td>
</tr>
</table>
</div>
</body>
</html>
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
{
"defaults": [
"-D_MSC_EXTENSIONS",
"--microsoft",
"--microsoft_bugs",
"--microsoft_version",
"1900",
"--pack_alignment",
"8",
"-D_MSC_VER=1900",
"-D_MSC_FULL_VER=190024210",
"-D_MSC_BUILD=0",
"-D_M_IX86=600",
"-D_M_IX86_FP=2"
],
"defaults_op" : "merge"
}
+8
View File
@@ -0,0 +1,8 @@
{
"defaults": [
"--clang",
"--pack_alignment",
"8"
],
"defaults_op" : "merge"
}
+18
View File
@@ -0,0 +1,18 @@
{
"defaults": [
"-D_MSC_EXTENSIONS",
"--microsoft",
"--microsoft_bugs",
"--microsoft_version",
"1900",
"--pack_alignment",
"8",
"-D_CPPUNWIND=1",
"-D_MSC_VER=1900",
"-D_MSC_FULL_VER=190024210",
"-D_MSC_BUILD=0",
"-D_M_X64=100",
"-D_AMD64=100"
],
"defaults_op" : "merge"
}
+8
View File
@@ -0,0 +1,8 @@
{
"defaults": [
"--clang",
"--pack_alignment",
"8"
],
"defaults_op" : "merge"
}
+18
View File
@@ -0,0 +1,18 @@
{
"defaults": [
"-D_MSC_EXTENSIONS",
"--microsoft",
"--microsoft_bugs",
"--microsoft_version",
"1900",
"--pack_alignment",
"8",
"-D_CPPUNWIND=1",
"-D_MSC_VER=1900",
"-D_MSC_FULL_VER=190024210",
"-D_MSC_BUILD=0",
"-D_M_X64=100",
"-D_AMD64=100"
],
"defaults_op" : "merge"
}
+8
View File
@@ -0,0 +1,8 @@
{
"defaults": [
"--clang",
"--pack_alignment",
"8"
],
"defaults_op" : "merge"
}
+18
View File
@@ -0,0 +1,18 @@
{
"defaults": [
"-D_MSC_EXTENSIONS",
"--microsoft",
"--microsoft_bugs",
"--microsoft_version",
"1900",
"--pack_alignment",
"8",
"-D_CPPUNWIND=1",
"-D_MSC_VER=1900",
"-D_MSC_FULL_VER=190024210",
"-D_MSC_BUILD=0",
"-D_M_X64=100",
"-D_AMD64=100"
],
"defaults_op" : "merge"
}
+33
View File
@@ -0,0 +1,33 @@
{
"defaults": [
"cpfe",
"--wchar_t_keyword",
"--no_warnings",
"--rtti",
"--edge",
"--exceptions",
"--error_limit",
"25000",
"-D_EDG_COMPILER",
"-D_USE_DECLSPECS_FOR_SAL=1"
],
"source_file_format": "-f %s",
"expressions": [
{
"match": "^/I(.*)",
"replace": "-I\n$1"
},
{
"match": "^/D(.*)",
"replace": "-D$1"
},
{
"match": "^/AI(.*)",
"replace": "--using_directory\n$1"
},
{
"match": "^/dE--header_only_fallback",
"replace": "--header_only_fallback"
}
]
}
+121
View File
@@ -0,0 +1,121 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"definitions": {
"configurations": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"description": "Configuration identifier. Mac, Linux, or Win32 are special identifiers for configurations that will be auto-selected on those platforms, but the identifier can be anything.",
"type": "string"
},
"compilerPath": {
"description": "Full path of the compiler being used, e.g. /usr/bin/gcc, to enable more accurate IntelliSense. Args can be added to modify the includes/defines used, e.g. -nostdinc++, -m32, etc., but paths with spaces must be surrounded with \\\" if args are used.",
"type": "string"
},
"cStandard": {
"description": "Version of the C language standard to use for IntelliSense.",
"type": "string",
"enum": [
"c89",
"c99",
"c11"
]
},
"cppStandard": {
"description": "Version of the C++ language standard to use for IntelliSense.",
"type": "string",
"enum": [
"c++98",
"c++03",
"c++11",
"c++14",
"c++17"
]
},
"compileCommands": {
"description": "Full path to compile_commands.json file for the workspace.",
"type": "string"
},
"includePath": {
"description": "A list of paths for the IntelliSense engine to use while searching for included headers. Searching on these paths is not recursive.",
"type": "array",
"items": {
"type": "string"
}
},
"macFrameworkPath": {
"description": "A list of paths for the Intellisense engine to use while searching for included headers from Mac frameworks. Only supported on Mac configuration.",
"type": "array",
"items": {
"type": "string"
}
},
"defines": {
"description": "A list of preprocessor definitions for the IntelliSense engine to use while parsing files. Optionally, use = to set a value, e.g. VERSION=1.",
"type": "array",
"items": {
"type": "string"
}
},
"intelliSenseMode": {
"type": "string",
"enum": [
"msvc-x64",
"clang-x64"
],
"description": "If set, it overrides the default mode used by the IntelliSense engine. Windows defaults to msvc-x64 and Linux/Mac default to clang-x64."
},
"forcedInclude": {
"description": "A list of files that should be included before any include file in a translation unit.",
"type": "array",
"items": {
"type": "string"
}
},
"browse": {
"type": "object",
"properties": {
"limitSymbolsToIncludedHeaders": {
"description": "true to process only those files directly or indirectly included as headers, false to process all files under the specified include paths.",
"type": "boolean"
},
"databaseFilename": {
"description": "Path to the generated symbol database. If a relative path is specified, it will be made relative to the workspace's default storage location.",
"type": "string"
},
"path": {
"description": "A list of paths for the tag parser to use while searching for included headers. Searching on these paths is recursive by default. Specify '*' to indicate non-recursive search. For example: '/usr/include' will search through all subdirectories while '/usr/include/*' will not.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"version": {
"type": "integer",
"description": "Version of the configuration file. This property is managed by the extension. Please do not change it."
}
},
"properties": {
"configurations": {
"$ref": "#/definitions/configurations"
},
"version": {
"$ref": "#/definitions/version"
}
},
"required": [
"configurations",
"version"
]
}
+2574
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
{
"engineAssemblyName": "Microsoft.MIDebugEngine",
"engineClassName": "Microsoft.MIDebugEngine.AD7Engine",
"conditionalBP": true,
"functionBP": true
}
+3
View File
@@ -0,0 +1,3 @@
{
"intelliSenseEngine_default_percentage": 100
}
+76
View File
@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
const gulp = require('gulp');
const env = require('gulp-env')
const tslint = require('gulp-tslint');
const mocha = require('gulp-mocha');
gulp.task('allTests', () => {
gulp.start('unitTests');
gulp.start('integrationTests');
});
gulp.task('unitTests', () => {
gulp.src('./out/test/unitTests', {read: false}).pipe(
mocha({
ui: "tdd"
})
).once('error', err => {
process.exit(1);
})
.once('end', () => {
process.exit();
})
});
gulp.task('integrationTests', () => {
env.set({
CODE_TESTS_PATH: "./out/test/integrationTests",
CODE_TESTS_WORKSPACE: "./test/integrationTests/testAssets/SimpleCppProject"
}
);
gulp.src('./test/runVsCodeTestsWithAbsolutePaths.js', {read: false}).pipe(
mocha({
ui: "tdd",
delay: true
})
).once('error', err => {
process.exit(1);
})
.once('end', () => {
process.exit();
})
});
/// Misc Tasks
const allTypeScript = [
'src/**/*.ts',
'!**/*.d.ts',
'!**/typings**'
];
const lintReporter = (output, file, options) => {
//emits: src/helloWorld.c:5:3: warning: implicit declaration of function prinft
var relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/');
output.forEach(e => {
var message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure;
console.log('[tslint] ' + message);
});
};
gulp.task('tslint', () => {
gulp.src(allTypeScript)
.pipe(tslint({
program: require('tslint').Linter.createProgram("./tsconfig.json"),
configuration: "./tslint.json"
}))
.pipe(tslint.report(lintReporter, {
summarizeFailureOutput: false,
emitError: false
}))
});
@@ -0,0 +1,216 @@
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize
This package is for the Microsoft C/C++ Extension for Visual Studio Code. This package includes components from the projects listed below. Microsoft licenses these components under the Microsoft C/C++ Extension for Visual Studio Code license terms. The original copyright notices and the licenses under which Microsoft received such components are set forth below for informational purposes. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise.
1. Clang (http://clang.llvm.org/)
2. LLDB (http://lldb.llvm.org/)
3. LLVM (http://llvm.org/)
%% Clang NOTICES AND INFORMATION BEGIN HERE
=========================================
LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2007-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
This project may include:
/*
* Copyright 2001-2004 Unicode, Inc.
*
* Disclaimer
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
=========================================
END OF Clang NOTICES AND INFORMATION
%% LLDB NOTICES AND INFORMATION BEGIN HERE
=========================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2010 Apple Inc.
All rights reserved.
Developed by:
LLDB Team
http://lldb.llvm.org/
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLDB Team, copyright holders, nor the names of
its contributors may be used to endorse or promote products derived from
this Software without specific prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
=========================================
END OF LLDB NOTICES AND INFORMATION
%% LLVM NOTICES AND INFORMATION BEGIN HERE
=========================================
LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
Copyrights and Licenses for Third Party Software Distributed with LLVM:
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Directory
------- ---------
Autoconf llvm/autoconf
llvm/projects/ModuleMaker/autoconf
Google Test llvm/utils/unittest/googletest
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
=========================================
END OF LLVM NOTICES AND INFORMATION
@@ -0,0 +1,170 @@
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize
This package is for the Microsoft C/C++ Extension for Visual Studio Code. This package includes components from the projects listed below. Microsoft licenses these components under the Microsoft C/C++ Extension for Visual Studio Code license terms. The original copyright notices and the licenses under which Microsoft received such components are set forth below for informational purposes. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise.
1. Mono (https://github.com/mono/mono)
%% Mono NOTICES AND INFORMATION BEGIN HERE
=========================================
The MIT License (MIT)
Copyright (c) .NET Foundation and its contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
The following code is linked with the final Mono runtime, the libmono
embeddable runtime:
* support/minizip: BSD license (modified).
* Copyright (C) 1998-2005 Gilles Vollant
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
* mono/utils/freebsd-dwarf.h.
* Copyright (c) 2007 John Birrell ([email protected])
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*notice, this list of conditions and the following disclaimer in the
*documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* mono/utils/freebsd-elf_common.h, freebsd-elf64.h freebsd-elf32.h: BSD license.
* Copyright (c) 1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* mono/utils/bsearch.c: BSD license.
* Taken from NetBSD with some minor modifications.
*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* mono/io-layer/wapi_glob.h, wapi_glob.c: BSD license
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
=========================================
END OF Mono NOTICES AND INFORMATION
+5223
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+149
View File
@@ -0,0 +1,149 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import { execChildProcess } from '../common';
import { PsProcessParser } from './nativeAttach';
import * as util from '../common';
export interface AttachItem extends vscode.QuickPickItem {
id: string;
}
export interface AttachItemsProvider {
getAttachItems(): Promise<AttachItem[]>;
}
export class AttachPicker {
constructor(private attachItemsProvider: AttachItemsProvider) { }
public ShowAttachEntries(): Promise<string> {
return util.isExtensionReady().then(ready => {
if (!ready) {
util.displayExtensionNotReadyPrompt();
} else {
return this.attachItemsProvider.getAttachItems()
.then(processEntries => {
let attachPickOptions: vscode.QuickPickOptions = {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: "Select the process to attach to"
};
return vscode.window.showQuickPick(processEntries, attachPickOptions)
.then(chosenProcess => {
return chosenProcess ? chosenProcess.id : Promise.reject<string>(new Error("Process not selected."));
});
});
}
});
}
}
export class RemoteAttachPicker {
constructor() {
this._channel = vscode.window.createOutputChannel('remote-attach');
}
private _channel: vscode.OutputChannel = null;
public ShowAttachEntries(args: any): Promise<string> {
return util.isExtensionReady().then(ready => {
if (!ready) {
util.displayExtensionNotReadyPrompt();
} else {
this._channel.clear();
let pipeTransport: any = args ? args.pipeTransport : null;
if (pipeTransport === null) {
return Promise.reject<string>(new Error("Chosen debug configuration does not contain pipeTransport"));
}
let pipeProgram: string = pipeTransport.pipeProgram;
let pipeArgs: string[] = pipeTransport.pipeArgs;
let argList: string = RemoteAttachPicker.createArgumentList(pipeArgs);
let pipeCmd: string = `"${pipeProgram}" ${argList}`;
return this.getRemoteOSAndProcesses(pipeCmd)
.then(processes => {
let attachPickOptions: vscode.QuickPickOptions = {
matchOnDetail: true,
matchOnDescription: true,
placeHolder: "Select the process to attach to"
};
return vscode.window.showQuickPick(processes, attachPickOptions)
.then(item => {
return item ? item.id : Promise.reject<string>(new Error("Process not selected."));
});
});
}
});
}
private getRemoteOSAndProcesses(pipeCmd: string): Promise<AttachItem[]> {
// Commands to get OS and processes
const command: string = `bash -c 'uname && if [ $(uname) == "Linux" ] ; then ${PsProcessParser.psLinuxCommand} ; elif [ $(uname) == "Darwin" ] ; ` +
`then ${PsProcessParser.psDarwinCommand}; fi'`;
return execChildProcess(`${pipeCmd} "${command}"`, null, this._channel).then(output => {
// OS will be on first line
// Processess will follow if listed
let lines: string[] = output.split(/\r?\n/);
if (lines.length === 0) {
return Promise.reject<AttachItem[]>(new Error("Pipe transport failed to get OS and processes."));
} else {
let remoteOS: string = lines[0].replace(/[\r\n]+/g, '');
if (remoteOS !== "Linux" && remoteOS !== "Darwin") {
return Promise.reject<AttachItem[]>(new Error(`Operating system "${remoteOS}" not supported.`));
}
// Only got OS from uname
if (lines.length === 1) {
return Promise.reject<AttachItem[]>(new Error("Transport attach could not obtain processes list."));
} else {
let processes: string[] = lines.slice(1);
return PsProcessParser.ParseProcessFromPsArray(processes)
.sort((a, b) => {
if (a.name === undefined) {
if (b.name === undefined) {
return 0;
}
return 1;
}
if (b.name === undefined) {
return -1;
}
let aLower: string = a.name.toLowerCase();
let bLower: string = b.name.toLowerCase();
if (aLower === bLower) {
return 0;
}
return aLower < bLower ? -1 : 1;
})
.map(p => p.toAttachItem());
}
}
});
}
private static createArgumentList(args: string[]): string {
let argsString: string = "";
for (let arg of args) {
if (argsString) {
argsString += " ";
}
argsString += `"${arg}"`;
}
return argsString;
}
}
@@ -0,0 +1,202 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as os from 'os';
import * as vscode from 'vscode';
import { IConfiguration, IConfigurationSnippet, DebuggerType, MIConfigurations, WindowsConfigurations, WSLConfigurations, PipeTransportConfigurations } from './configurations';
import { parse } from 'jsonc-parser';
abstract class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
private type: DebuggerType;
private provider: IConfigurationAssetProvider;
public constructor(provider: IConfigurationAssetProvider, type: DebuggerType) {
this.provider = provider;
this.type = type;
}
/**
* Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder.
*/
provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration[]> {
return this.provider.getInitialConfigurations(this.type);
}
/**
* Try to add all missing attributes to the debug configuration being launched.
*/
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
// Fail if cppvsdbg type is running on non-Windows
if (config.type === 'cppvsdbg' && os.platform() !== 'win32') {
vscode.window.showErrorMessage("Debugger of type: 'cppvsdbg' is only available on Windows. Use type: 'cppdbg' on the current OS platform.");
return undefined;
}
return config;
}
}
export class CppVsDbgConfigurationProvider extends CppConfigurationProvider {
public constructor(provider: IConfigurationAssetProvider) {
super(provider, DebuggerType.cppvsdbg);
}
}
export class CppDbgConfigurationProvider extends CppConfigurationProvider {
public constructor(provider: IConfigurationAssetProvider) {
super(provider, DebuggerType.cppdbg);
}
}
export interface IConfigurationAssetProvider {
getInitialConfigurations(debuggerType: DebuggerType): any;
getConfigurationSnippets(): vscode.CompletionItem[];
}
export class ConfigurationAssetProviderFactory {
public static getConfigurationProvider(): IConfigurationAssetProvider {
switch (os.platform()) {
case 'win32':
return new WindowsConfigurationProvider();
case 'darwin':
return new OSXConfigurationProvider();
case 'linux':
return new LinuxConfigurationProvider();
default:
throw new Error("Unexpected OS type");
}
}
}
abstract class DefaultConfigurationProvider implements IConfigurationAssetProvider {
configurations: IConfiguration[];
public getInitialConfigurations(debuggerType: DebuggerType): any {
let configurationSnippet: IConfigurationSnippet[] = [];
// Only launch configurations are initial configurations
this.configurations.forEach(configuration => {
configurationSnippet.push(configuration.GetLaunchConfiguration());
});
let initialConfigurations: any = configurationSnippet.filter(snippet => snippet.debuggerType === debuggerType && snippet.isInitialConfiguration)
.map(snippet => JSON.parse(snippet.bodyText));
// If configurations is empty, then it will only have an empty configurations array in launch.json. Users can still add snippets.
return initialConfigurations;
}
public getConfigurationSnippets(): vscode.CompletionItem[] {
let completionItems: vscode.CompletionItem[] = [];
this.configurations.forEach(configuration => {
completionItems.push(convertConfigurationSnippetToCompetionItem(configuration.GetLaunchConfiguration()));
completionItems.push(convertConfigurationSnippetToCompetionItem(configuration.GetAttachConfiguration()));
});
return completionItems;
}
}
class WindowsConfigurationProvider extends DefaultConfigurationProvider {
private executable: string = "a.exe";
private pipeProgram: string = "<full path to pipe program such as plink.exe>";
private MIMode: string = 'gdb';
private setupCommandsBlock: string = `"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]`;
constructor() {
super();
this.configurations = [
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
new PipeTransportConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
new WindowsConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
new WSLConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
];
}
}
class OSXConfigurationProvider extends DefaultConfigurationProvider {
private MIMode: string = 'lldb';
private executable: string = "a.out";
private pipeProgram: string = "/usr/bin/ssh";
constructor() {
super();
this.configurations = [
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram),
];
}
}
class LinuxConfigurationProvider extends DefaultConfigurationProvider {
private MIMode: string = 'gdb';
private setupCommandsBlock: string = `"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]`;
private executable: string = "a.out";
private pipeProgram: string = "/usr/bin/ssh";
constructor() {
super();
this.configurations = [
new MIConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock),
new PipeTransportConfigurations(this.MIMode, this.executable, this.pipeProgram, this.setupCommandsBlock)
];
}
}
function convertConfigurationSnippetToCompetionItem(snippet: IConfigurationSnippet): vscode.CompletionItem {
let item: vscode.CompletionItem = new vscode.CompletionItem(snippet.label, vscode.CompletionItemKind.Snippet);
item.insertText = snippet.bodyText;
return item;
}
export class ConfigurationSnippetProvider implements vscode.CompletionItemProvider {
private provider: IConfigurationAssetProvider;
private snippets: vscode.CompletionItem[];
constructor(provider: IConfigurationAssetProvider) {
this.provider = provider;
this.snippets = this.provider.getConfigurationSnippets();
}
public resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken): Thenable<vscode.CompletionItem> {
return Promise.resolve(item);
}
// This function will only provide completion items via the Add Configuration Button
// There are two cases where the configuration array has nothing or has some items.
// 1. If it has nothing, insert a snippet the user selected.
// 2. If there are items, the Add Configuration button will append it to the start of the configuration array. This function inserts a comma at the end of the snippet.
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Thenable<vscode.CompletionList> {
let items: vscode.CompletionItem[] = this.snippets;
const launch: any = parse(document.getText());
// Check to see if the array is empty, so any additional inserted snippets will need commas.
if (launch.configurations.length !== 0) {
items = [];
// Make a copy of each snippet since we are adding a comma to the end of the insertText.
this.snippets.forEach((item) => items.push(Object.assign({}, item)));
items.map((item) => {
item.insertText = item.insertText + ','; // Add comma
});
}
return Promise.resolve(new vscode.CompletionList(items, true));
}
}
+256
View File
@@ -0,0 +1,256 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as os from 'os';
export enum DebuggerType {
cppvsdbg,
cppdbg
}
export interface IConfigurationSnippet {
label: string;
description: string;
bodyText: string;
// Internal
isInitialConfiguration?: boolean;
debuggerType: DebuggerType;
}
export function indentJsonString(json: string, numTabs: number = 1): string {
return json.split('\n').map(line => '\t'.repeat(numTabs) + line).join('\n').trim();
}
function formatString(format: string, args: string[]): string {
for (let arg in args) {
format = format.replace("{" + arg + "}", args[arg]);
}
return format;
}
function CreateLaunchString(name: string, type: string, executable: string): string {
return `"name": "${name}",
"type": "${type}",
"request": "launch",
"program": "${"enter program name, for example " + "$\{workspaceFolder\}" + "/" + executable}",
"args": [],
"stopAtEntry": false,
"cwd": "$\{workspaceFolder\}",
"environment": [],
"externalConsole": true
`;
}
function CreateAttachString(name: string, type: string, executable: string): string {
return formatString(`
"name": "${name}",
"type": "${type}",
"request": "attach",{0}
"processId": "$\{command:pickProcess\}"
`, [type === "cppdbg" ? `${os.EOL}"program": "${"enter program name, for example $\{workspaceFolder\}/" + executable}",` : ""]);
}
function CreateRemoteAttachString(name: string, type: string, executable: string): string {
return `
"name": "${name}",
"type": "${type}",
"request": "attach",
"program": "${"enter program name, for example $\{workspaceFolder\}/" + executable}",
"processId": "$\{command:pickRemoteProcess\}"
`;
}
function CreatePipeTransportString(pipeProgram: string, debuggerProgram: string, pipeArgs: string[] = []): string {
return `
"pipeTransport": {
\t"debuggerPath": "/usr/bin/${debuggerProgram}",
\t"pipeProgram": "${pipeProgram}",
\t"pipeArgs": ${JSON.stringify(pipeArgs)},
\t"pipeCwd": ""
}`;
}
export interface IConfiguration {
GetLaunchConfiguration(): IConfigurationSnippet;
GetAttachConfiguration(): IConfigurationSnippet;
}
abstract class Configuration implements IConfiguration {
public snippetPrefix = "C/C++: ";
public executable: string;
public pipeProgram: string;
public MIMode: string;
public additionalProperties: string;
public miDebugger = "cppdbg";
public windowsDebugger = "cppvsdbg";
constructor(MIMode: string, executable: string, pipeProgram: string, additionalProperties: string = "") {
this.MIMode = MIMode;
this.executable = executable;
this.pipeProgram = pipeProgram;
this.additionalProperties = additionalProperties;
}
abstract GetLaunchConfiguration(): IConfigurationSnippet;
abstract GetAttachConfiguration(): IConfigurationSnippet;
}
export class MIConfigurations extends Configuration {
public GetLaunchConfiguration(): IConfigurationSnippet {
let name: string = `(${this.MIMode}) Launch`;
let body: string = formatString(`{
\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)}` : ""]);
return {
"label": this.snippetPrefix + name,
"description": `Launch with ${this.MIMode}.`,
"bodyText": body.trim(),
"isInitialConfiguration": true,
"debuggerType": DebuggerType.cppdbg
};
}
public GetAttachConfiguration(): IConfigurationSnippet {
let name: string = `(${this.MIMode}) Attach`;
let body: string = formatString(`{
\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)}` : ""]);
return {
"label": this.snippetPrefix + name,
"description": `Attach with ${this.MIMode}.`,
"bodyText": body.trim(),
"debuggerType": DebuggerType.cppdbg
};
}
}
export class PipeTransportConfigurations extends Configuration {
public GetLaunchConfiguration(): IConfigurationSnippet {
let name: string = `(${this.MIMode}) Pipe Launch`;
let body: string = formatString(`
{
\t${indentJsonString(CreateLaunchString(name, this.miDebugger, this.executable))},
\t${indentJsonString(CreatePipeTransportString(this.pipeProgram, this.MIMode))},
\t"MIMode": "${this.MIMode}"{0}
}`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
return {
"label": this.snippetPrefix + name,
"description": `Pipe Launch with ${this.MIMode}.`,
"bodyText": body.trim(),
"debuggerType": DebuggerType.cppdbg
};
}
public GetAttachConfiguration(): IConfigurationSnippet {
let name: string = `(${this.MIMode}) Pipe Attach`;
let body: string = formatString(`
{
\t${indentJsonString(CreateRemoteAttachString(name, this.miDebugger, this.executable))},
\t${indentJsonString(CreatePipeTransportString(this.pipeProgram, this.MIMode))},
\t"MIMode": "${this.MIMode}"{0}
}`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
return {
"label": this.snippetPrefix + name,
"description": `Pipe Attach with ${this.MIMode}.`,
"bodyText": body.trim(),
"debuggerType": DebuggerType.cppdbg
};
}
}
export class WindowsConfigurations extends Configuration {
public GetLaunchConfiguration(): IConfigurationSnippet {
let name: string = "(Windows) Launch";
let body: string = `
{
\t${indentJsonString(CreateLaunchString(name, this.windowsDebugger, this.executable))}
}`;
return {
"label": this.snippetPrefix + name,
"description": "Launch with the Visual Studio C/C++ debugger.",
"bodyText": body.trim(),
"isInitialConfiguration": true,
"debuggerType": DebuggerType.cppvsdbg
};
}
public GetAttachConfiguration(): IConfigurationSnippet {
let name: string = "(Windows) Attach";
let body: string = `
{
\t${indentJsonString(CreateAttachString(name, this.windowsDebugger, this.executable))}
}`;
return {
"label": this.snippetPrefix + name,
"description": "Attach to a process with the Visual Studio C/C++ debugger.",
"bodyText": body.trim(),
"debuggerType": DebuggerType.cppvsdbg
};
}
}
export class WSLConfigurations extends Configuration {
public bashPipeProgram = "C:\\\\Windows\\\\sysnative\\\\bash.exe";
public GetLaunchConfiguration(): IConfigurationSnippet {
let name: string = `(${this.MIMode}) Bash on Windows Launch`;
let body: string = formatString(`
{
\t${indentJsonString(CreateLaunchString(name, this.miDebugger, this.executable))},
\t${indentJsonString(CreatePipeTransportString(this.bashPipeProgram, this.MIMode, ["-c"]))}{0}
}`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
return {
"label": this.snippetPrefix + name,
"description": `Launch in Bash on Windows using ${this.MIMode}.`,
"bodyText": body.trim(),
"debuggerType": DebuggerType.cppdbg
};
}
public GetAttachConfiguration(): IConfigurationSnippet {
let name: string = `(${this.MIMode}) Bash on Windows Attach`;
let body: string = formatString(`
{
\t${indentJsonString(CreateRemoteAttachString(name, this.miDebugger, this.executable))},
\t${indentJsonString(CreatePipeTransportString(this.bashPipeProgram, this.MIMode, ["-c"]))}{0}
}`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]);
return {
"label": this.snippetPrefix + name,
"description": `Attach to a remote process running in Bash on Windows using ${this.MIMode}.`,
"bodyText": body.trim(),
"debuggerType": DebuggerType.cppdbg
};
}
}
+93
View File
@@ -0,0 +1,93 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
import * as os from 'os';
import { AttachPicker, RemoteAttachPicker, AttachItemsProvider } from './attachToProcess';
import { NativeAttachItemsProviderFactory } from './nativeAttach';
import { ConfigurationAssetProviderFactory, CppVsDbgConfigurationProvider, CppDbgConfigurationProvider, ConfigurationSnippetProvider, IConfigurationAssetProvider } from './configurationProvider';
import * as util from '../common';
import * as path from 'path';
// The extension deactivate method is asynchronous, so we handle the disposables ourselves instead of using extensonContext.subscriptions.
let disposables: vscode.Disposable[] = [];
export function initialize(): void {
// Activate Process Picker Commands
let attachItemsProvider: AttachItemsProvider = NativeAttachItemsProviderFactory.Get();
let attacher: AttachPicker = new AttachPicker(attachItemsProvider);
disposables.push(vscode.commands.registerCommand('extension.pickNativeProcess', () => attacher.ShowAttachEntries()));
let remoteAttacher: RemoteAttachPicker = new RemoteAttachPicker();
disposables.push(vscode.commands.registerCommand('extension.pickRemoteNativeProcess', (any) => remoteAttacher.ShowAttachEntries(any)));
// Activate ConfigurationProvider
let configurationProvider: IConfigurationAssetProvider = ConfigurationAssetProviderFactory.getConfigurationProvider();
// On non-windows platforms, the cppvsdbg debugger will not be registered for initial configurations.
// This will cause it to not show up on the dropdown list.
if (os.platform() === 'win32') {
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppvsdbg', new CppVsDbgConfigurationProvider(configurationProvider)));
}
disposables.push(vscode.debug.registerDebugConfigurationProvider('cppdbg', new CppDbgConfigurationProvider(configurationProvider)));
configurationProvider.getConfigurationSnippets();
const launchJsonDocumentSelector: vscode.DocumentSelector = [{
language: 'jsonc',
pattern: '**/launch.json'
}];
// ConfigurationSnippetProvider needs to be initiallized after configurationProvider calls getConfigurationSnippets.
disposables.push(vscode.languages.registerCompletionItemProvider(launchJsonDocumentSelector, new ConfigurationSnippetProvider(configurationProvider)));
// Activate Adapter Commands
registerAdapterExecutableCommands();
vscode.Disposable.from(...disposables);
}
export function dispose(): void {
disposables.forEach(d => d.dispose());
}
// Registers adapterExecutableCommands for cppdbg and cppvsdbg. If it is not ready, it will prompt waiting for the download.
//
// Note: util.extensionContext.extensionPath is needed for the commands because VsCode does not support relative paths for adapterExecutableComand
function registerAdapterExecutableCommands(): void {
disposables.push(vscode.commands.registerCommand('extension.cppdbgAdapterExecutableCommand', () => {
return util.isExtensionReady().then(ready => {
if (ready) {
let command: string = path.join(util.extensionContext.extensionPath, './debugAdapters/OpenDebugAD7');
// Windows has the exe in debugAdapters/bin.
if (os.platform() === 'win32') {
command = path.join(util.extensionContext.extensionPath, "./debugAdapters/bin/OpenDebugAD7.exe");
}
return {
command: command
};
} else {
throw new Error(util.extensionNotReadyString);
}
});
}));
disposables.push(vscode.commands.registerCommand('extension.cppvsdbgAdapterExecutableCommand', () => {
if (os.platform() !== 'win32') {
vscode.window.showErrorMessage("Debugger type 'cppvsdbg' is not avaliable for non-Windows machines.");
return null;
} else {
return util.isExtensionReady().then(ready => {
if (ready) {
return {
command: path.join(util.extensionContext.extensionPath, './debugAdapters/vsdbg/bin/vsdbg.exe'),
args: ['--interpreter=vscode']
};
} else {
throw new Error(util.extensionNotReadyString);
}
});
}
}));
}
+247
View File
@@ -0,0 +1,247 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as child_process from 'child_process';
import * as os from 'os';
import { AttachItem, AttachItemsProvider } from './attachToProcess';
class Process {
constructor(public name: string, public pid: string, public commandLine: string) { }
public toAttachItem(): AttachItem {
return {
label: this.name,
description: this.pid,
detail: this.commandLine,
id: this.pid
};
}
}
export class NativeAttachItemsProviderFactory {
static Get(): AttachItemsProvider {
if (os.platform() === 'win32') {
return new WmicAttachItemsProvider();
} else {
return new PsAttachItemsProvider();
}
}
}
abstract class NativeAttachItemsProvider implements AttachItemsProvider {
protected abstract getInternalProcessEntries(): Promise<Process[]>;
getAttachItems(): Promise<AttachItem[]> {
return this.getInternalProcessEntries().then(processEntries => {
// localeCompare is significantly slower than < and > (2000 ms vs 80 ms for 10,000 elements)
// We can change to localeCompare if this becomes an issue
processEntries.sort((a, b) => {
if (a.name === undefined) {
if (b.name === undefined) {
return 0;
}
return 1;
}
if (b.name === undefined) {
return -1;
}
let aLower: string = a.name.toLowerCase();
let bLower: string = b.name.toLowerCase();
if (aLower === bLower) {
return 0;
}
return aLower < bLower ? -1 : 1;
});
let attachItems: AttachItem[] = processEntries.map(p => p.toAttachItem());
return attachItems;
});
}
}
export class PsAttachItemsProvider extends NativeAttachItemsProvider {
// Perf numbers:
// OS X 10.10
// | # of processes | Time (ms) |
// |----------------+-----------|
// | 272 | 52 |
// | 296 | 49 |
// | 384 | 53 |
// | 784 | 116 |
//
// Ubuntu 16.04
// | # of processes | Time (ms) |
// |----------------+-----------|
// | 232 | 26 |
// | 336 | 34 |
// | 736 | 62 |
// | 1039 | 115 |
// | 1239 | 182 |
// ps outputs as a table. With the option "ww", ps will use as much width as necessary.
// However, that only applies to the right-most column. Here we use a hack of setting
// the column header to 50 a's so that the second column will have at least that many
// characters. 50 was chosen because that's the maximum length of a "label" in the
// QuickPick UI in VSCode.
protected getInternalProcessEntries(): Promise<Process[]> {
let processCmd: string = '';
switch (os.platform()) {
case 'darwin':
processCmd = PsProcessParser.psDarwinCommand;
break;
case 'linux':
processCmd = PsProcessParser.psLinuxCommand;
break;
default:
return Promise.reject<Process[]>(new Error(`Operating system "${os.platform()}" not support.`));
}
return execChildProcess(processCmd, null).then(processes => {
return PsProcessParser.ParseProcessFromPs(processes);
});
}
}
export class PsProcessParser {
private static get secondColumnCharacters(): number { return 50; }
private static get commColumnTitle(): string { return Array(PsProcessParser.secondColumnCharacters).join("a"); }
// the BSD version of ps uses '-c' to have 'comm' only output the executable name and not
// the full path. The Linux version of ps has 'comm' to only display the name of the executable
// Note that comm on Linux systems is truncated to 16 characters:
// https://bugzilla.redhat.com/show_bug.cgi?id=429565
// Since 'args' contains the full path to the executable, even if truncated, searching will work as desired.
public static get psLinuxCommand(): string { return `ps -axww -o pid=,comm=${PsProcessParser.commColumnTitle},args=`; }
public static get psDarwinCommand(): string { return `ps -axww -o pid=,comm=${PsProcessParser.commColumnTitle},args= -c`; }
// Only public for tests.
public static ParseProcessFromPs(processes: string): Process[] {
let lines: string[] = processes.split(os.EOL);
return PsProcessParser.ParseProcessFromPsArray(lines);
}
public static ParseProcessFromPsArray(processArray: string[]): Process[] {
let processEntries: Process[] = [];
// lines[0] is the header of the table
for (let i: number = 1; i < processArray.length; i++) {
let line: string = processArray[i];
if (!line) {
continue;
}
let processEntry: Process = PsProcessParser.parseLineFromPs(line);
processEntries.push(processEntry);
}
return processEntries;
}
private static parseLineFromPs(line: string): Process {
// Explanation of the regex:
// - any leading whitespace
// - PID
// - whitespace
// - executable name --> this is PsAttachItemsProvider.secondColumnCharacters - 1 because ps reserves one character
// for the whitespace separator
// - whitespace
// - args (might be empty)
const psEntry: RegExp = new RegExp(`^\\s*([0-9]+)\\s+(.{${PsProcessParser.secondColumnCharacters - 1}})\\s+(.*)$`);
const matches: RegExpExecArray = psEntry.exec(line);
if (matches && matches.length === 4) {
const pid: string = matches[1].trim();
const executable: string = matches[2].trim();
const cmdline: string = matches[3].trim();
return new Process(executable, pid, cmdline);
}
}
}
/**
* Originally from common.ts. Due to test code not having vscode, it was refactored to not have vscode.OutputChannel.
*/
function execChildProcess(process: string, workingDirectory: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
child_process.exec(process, { cwd: workingDirectory, maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => {
if (error) {
reject(error);
return;
}
if (stderr && stderr.length > 0) {
reject(new Error(stderr));
return;
}
resolve(stdout);
});
});
}
export class WmicAttachItemsProvider extends NativeAttachItemsProvider {
// Perf numbers on Win10:
// | # of processes | Time (ms) |
// |----------------+-----------|
// | 309 | 413 |
// | 407 | 463 |
// | 887 | 746 |
// | 1308 | 1132 |
protected getInternalProcessEntries(): Promise<Process[]> {
const wmicCommand: string = 'wmic process get Name,ProcessId,CommandLine /FORMAT:list';
return execChildProcess(wmicCommand, null).then(processes => {
return WmicProcessParser.ParseProcessFromWmic(processes);
});
}
}
export class WmicProcessParser {
private static get wmicNameTitle(): string { return 'Name'; }
private static get wmicCommandLineTitle(): string { return 'CommandLine'; }
private static get wmicPidTitle(): string { return 'ProcessId'; }
// Only public for tests.
public static ParseProcessFromWmic(processes: string): Process[] {
let lines: string[] = processes.split(os.EOL);
let currentProcess: Process = new Process(null, null, null);
let processEntries: Process[] = [];
for (let i: number = 0; i < lines.length; i++) {
let line: string = lines[i];
if (!line) {
continue;
}
WmicProcessParser.parseLineFromWmic(line, currentProcess);
// Each entry of processes has ProcessId as the last line
if (line.lastIndexOf(WmicProcessParser.wmicPidTitle, 0) === 0) {
processEntries.push(currentProcess);
currentProcess = new Process(null, null, null);
}
}
return processEntries;
}
private static parseLineFromWmic(line: string, process: Process): void {
let splitter: number = line.indexOf('=');
if (splitter >= 0) {
let key: string = line.slice(0, line.indexOf('=')).trim();
let value: string = line.slice(line.indexOf('=') + 1).trim();
if (key === WmicProcessParser.wmicNameTitle) {
process.name = value;
} else if (key === WmicProcessParser.wmicPidTitle) {
process.pid = value;
} else if (key === WmicProcessParser.wmicCommandLineTitle) {
const extendedLengthPath: string = '\\??\\';
if (value.lastIndexOf(extendedLengthPath, 0) === 0) {
value = value.slice(extendedLengthPath.length);
}
process.commandLine = value;
}
}
}
}
+952
View File
@@ -0,0 +1,952 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as path from 'path';
import * as vscode from 'vscode';
import {
LanguageClient, LanguageClientOptions, ServerOptions, NotificationType, TextDocumentIdentifier,
RequestType, ErrorAction, CloseAction, DidOpenTextDocumentParams
} from 'vscode-languageclient';
import * as util from '../common';
import * as configs from './configurations';
import { CppSettings, OtherSettings } from './settings';
import * as telemetry from '../telemetry';
import { PersistentState } from './persistentState';
import { UI, getUI } from './ui';
import { ClientCollection } from './clientCollection';
import { createProtocolFilter } from './protocolFilter';
import { DataBinding } from './dataBinding';
import minimatch = require("minimatch");
import * as logger from '../logger';
import { updateLanguageConfigurations } from './extension';
let ui: UI;
interface NavigationPayload {
navigation: string;
}
interface TelemetryPayload {
event: string;
properties?: { [key: string]: string };
metrics?: { [key: string]: number };
}
interface OutputNotificationBody {
category: string;
output: string;
}
interface ReportStatusNotificationBody {
status: string;
}
interface QueryCompilerDefaultsParams {
}
interface FolderSettingsParams {
currentConfiguration: number;
configurations: any[];
}
interface FolderSelectedSettingParams {
currentConfiguration: number;
}
interface SwitchHeaderSourceParams {
rootPath: string;
switchHeaderSourceFileName: string;
}
interface FileChangedParams {
uri: string;
}
interface OutputNotificationBody {
category: string;
output: string;
}
interface InactiveRegionParams {
uri: string;
regions: InputRegion[];
}
interface InputRegion {
startLine: number;
endLine: number;
}
interface DecorationRangesPair {
decoration: vscode.TextEditorDecorationType;
ranges: vscode.Range[];
}
// Requests
const NavigationListRequest: RequestType<TextDocumentIdentifier, string, void, void> = new RequestType<TextDocumentIdentifier, string, void, void>('cpptools/requestNavigationList');
const GoToDeclarationRequest: RequestType<void, void, void, void> = new RequestType<void, void, void, void>('cpptools/goToDeclaration');
const QueryCompilerDefaultsRequest: RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void> = new RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void>('cpptools/queryCompilerDefaults');
const SwitchHeaderSourceRequest: RequestType<SwitchHeaderSourceParams, string, void, void> = new RequestType<SwitchHeaderSourceParams, string, void, void>('cpptools/didSwitchHeaderSource');
// Notifications to the server
const DidOpenNotification: NotificationType<DidOpenTextDocumentParams, void> = new NotificationType<DidOpenTextDocumentParams, void>('textDocument/didOpen');
const FileCreatedNotification: NotificationType<FileChangedParams, void> = new NotificationType<FileChangedParams, void>('cpptools/fileCreated');
const FileDeletedNotification: NotificationType<FileChangedParams, void> = new NotificationType<FileChangedParams, void>('cpptools/fileDeleted');
const ResetDatabaseNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/resetDatabase');
const PauseParsingNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/pauseParsing');
const ResumeParsingNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/resumeParsing');
const ActiveDocumentChangeNotification: NotificationType<TextDocumentIdentifier, void> = new NotificationType<TextDocumentIdentifier, void>('cpptools/activeDocumentChange');
const TextEditorSelectionChangeNotification: NotificationType<vscode.Position, void> = new NotificationType<vscode.Position, void>('cpptools/textEditorSelectionChange');
const ChangeFolderSettingsNotification: NotificationType<FolderSettingsParams, void> = new NotificationType<FolderSettingsParams, void>('cpptools/didChangeFolderSettings');
const ChangeCompileCommandsNotification: NotificationType<FileChangedParams, void> = new NotificationType<FileChangedParams, void>('cpptools/didChangeCompileCommands');
const ChangeSelectedSettingNotification: NotificationType<FolderSelectedSettingParams, void> = new NotificationType<FolderSelectedSettingParams, void>('cpptools/didChangeSelectedSetting');
const IntervalTimerNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/onIntervalTimer');
// Notifications from the server
const ReloadWindowNotification: NotificationType<void, void> = new NotificationType<void, void>('cpptools/reloadWindow');
const LogTelemetryNotification: NotificationType<TelemetryPayload, void> = new NotificationType<TelemetryPayload, void>('cpptools/logTelemetry');
const ReportNavigationNotification: NotificationType<NavigationPayload, void> = new NotificationType<NavigationPayload, void>('cpptools/reportNavigation');
const ReportTagParseStatusNotification: NotificationType<ReportStatusNotificationBody, void> = new NotificationType<ReportStatusNotificationBody, void>('cpptools/reportTagParseStatus');
const ReportStatusNotification: NotificationType<ReportStatusNotificationBody, void> = new NotificationType<ReportStatusNotificationBody, void>('cpptools/reportStatus');
const DebugProtocolNotification: NotificationType<OutputNotificationBody, void> = new NotificationType<OutputNotificationBody, void>('cpptools/debugProtocol');
const DebugLogNotification: NotificationType<OutputNotificationBody, void> = new NotificationType<OutputNotificationBody, void>('cpptools/debugLog');
const InactiveRegionNotification: NotificationType<InactiveRegionParams, void> = new NotificationType<InactiveRegionParams, void>('cpptools/inactiveRegions');
const maxSettingLengthForTelemetry: number = 50;
let previousCppSettings: { [key: string]: any } = {};
/**
* track settings changes for telemetry
*/
function collectSettingsForTelemetry(filter: (key: string, val: string, settings: vscode.WorkspaceConfiguration) => boolean, resource: vscode.Uri): { [key: string]: string } {
let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", resource);
let result: { [key: string]: string } = {};
for (let key in settings) {
if (settings.inspect(key).defaultValue === undefined) {
continue; // ignore methods and settings that don't exist
}
let val: any = settings.get(key);
if (val instanceof Object) {
val = JSON.stringify(val, null, 2);
}
// Skip values that don't match the setting's enum.
let curSetting: any = util.packageJson.contributes.configuration.properties["C_Cpp." + key];
if (curSetting) {
let curEnum: any[] = curSetting["enum"];
if (curEnum && curEnum.indexOf(val) === -1) {
continue;
}
}
if (filter(key, val, settings)) {
previousCppSettings[key] = val;
switch (String(key).toLowerCase()) {
case "clang_format_path": {
continue;
}
case "clang_format_style":
case "clang_format_fallbackstyle": {
let newKey: string = String(key) + "2";
if (val) {
switch (String(val).toLowerCase()) {
case "visual studio":
case "llvm":
case "google":
case "chromium":
case "mozilla":
case "webkit":
case "file":
case "none": {
result[newKey] = String(previousCppSettings[key]);
break;
}
default: {
result[newKey] = "...";
break;
}
}
} else {
result[newKey] = "null";
}
key = newKey;
break;
}
default: {
result[key] = String(previousCppSettings[key]);
break;
}
}
if (result[key].length > maxSettingLengthForTelemetry) {
result[key] = result[key].substr(0, maxSettingLengthForTelemetry) + "...";
}
}
}
return result;
}
function initializeSettingsCache(resource: vscode.Uri): void {
collectSettingsForTelemetry(() => true, resource);
}
function getNonDefaultSettings(resource: vscode.Uri): { [key: string]: string } {
let filter: (key: string, val: string, settings: vscode.WorkspaceConfiguration) => boolean = (key: string, val: string, settings: vscode.WorkspaceConfiguration) => {
return val !== settings.inspect(key).defaultValue;
};
initializeSettingsCache(resource);
return collectSettingsForTelemetry(filter, resource);
}
interface ClientModel {
isTagParsing: DataBinding<boolean>;
isUpdatingIntelliSense: DataBinding<boolean>;
navigationLocation: DataBinding<string>;
tagParserStatus: DataBinding<string>;
activeConfigName: DataBinding<string>;
}
export interface Client {
TagParsingChanged: vscode.Event<boolean>;
IntelliSenseParsingChanged: vscode.Event<boolean>;
NavigationLocationChanged: vscode.Event<string>;
TagParserStatusChanged: vscode.Event<string>;
ActiveConfigChanged: vscode.Event<string>;
RootPath: string;
RootUri: vscode.Uri;
Name: string;
TrackedDocuments: Set<vscode.TextDocument>;
onDidChangeSettings(): void;
onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void;
takeOwnership(document: vscode.TextDocument): void;
requestGoToDeclaration(): Thenable<void>;
requestSwitchHeaderSource(rootPath: string, fileName: string): Thenable<string>;
requestNavigationList(document: vscode.TextDocument): Thenable<string>;
activeDocumentChanged(document: vscode.TextDocument): void;
activate(): void;
selectionChanged(selection: vscode.Position): void;
resetDatabase(): void;
deactivate(): void;
pauseParsing(): void;
resumeParsing(): void;
handleConfigurationSelectCommand(): void;
handleShowParsingCommands(): void;
handleConfigurationEditCommand(): void;
handleAddToIncludePathCommand(path: string): void;
onInterval(): void;
dispose(): Thenable<void>;
}
export function createClient(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder): Client {
return new DefaultClient(allClients, workspaceFolder);
}
export function createNullClient(): Client {
return new NullClient();
}
class DefaultClient implements Client {
private languageClient: LanguageClient; // The "client" that launches and communicates with our language "server" process.
private disposables: vscode.Disposable[] = [];
private configuration: configs.CppProperties;
private rootPathFileWatcher: vscode.FileSystemWatcher;
private rootFolder: vscode.WorkspaceFolder | undefined;
private trackedDocuments = new Set<vscode.TextDocument>();
private outputChannel: vscode.OutputChannel;
private debugChannel: vscode.OutputChannel;
private crashTimes: number[] = [];
private failureMessageShown = new PersistentState<boolean>("DefaultClient.failureMessageShown", false);
private isSupported: boolean = true;
private inactiveRegionsDecorations = new Map<string, DecorationRangesPair>();
// The "model" that is displayed via the UI (status bar).
private model: ClientModel = {
isTagParsing: new DataBinding<boolean>(false),
isUpdatingIntelliSense: new DataBinding<boolean>(false),
navigationLocation: new DataBinding<string>(""),
tagParserStatus: new DataBinding<string>(""),
activeConfigName: new DataBinding<string>("")
};
public get TagParsingChanged(): vscode.Event<boolean> { return this.model.isTagParsing.ValueChanged; }
public get IntelliSenseParsingChanged(): vscode.Event<boolean> { return this.model.isUpdatingIntelliSense.ValueChanged; }
public get NavigationLocationChanged(): vscode.Event<string> { return this.model.navigationLocation.ValueChanged; }
public get TagParserStatusChanged(): vscode.Event<string> { return this.model.tagParserStatus.ValueChanged; }
public get ActiveConfigChanged(): vscode.Event<string> { return this.model.activeConfigName.ValueChanged; }
/**
* don't use this.rootFolder directly since it can be undefined
*/
public get RootPath(): string {
return (this.rootFolder) ? this.rootFolder.uri.fsPath : "";
}
public get RootUri(): vscode.Uri {
return (this.rootFolder) ? this.rootFolder.uri : null;
}
public get Name(): string {
return this.getName(this.rootFolder);
}
public get TrackedDocuments(): Set<vscode.TextDocument> {
return this.trackedDocuments;
}
private getName(workspaceFolder?: vscode.WorkspaceFolder): string {
return workspaceFolder ? workspaceFolder.name : "untitled";
}
/**
* All public methods on this class must be guarded by the "onReady" promise. Requests and notifications received before the client is
* ready are executed after this promise is resolved.
* @see requestWhenReady<T>(request)
* @see notifyWhenReady(notify)
*/
private onReadyPromise: Thenable<void>;
constructor(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder) {
try {
let languageClient: LanguageClient = this.createLanguageClient(allClients, workspaceFolder);
languageClient.registerProposedFeatures();
languageClient.start(); // This returns Disposable, but doesn't need to be tracked because we call .stop() explicitly in our dispose()
util.setProgress(util.getProgressExecutableStarted());
this.rootFolder = workspaceFolder;
ui = getUI();
ui.bind(this);
this.onReadyPromise = languageClient.onReady().then(() => {
this.configuration = new configs.CppProperties(this.RootPath);
this.configuration.ConfigurationsChanged((e) => this.onConfigurationsChanged(e));
this.configuration.SelectionChanged((e) => this.onSelectedConfigurationChanged(e));
this.configuration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
this.disposables.push(this.configuration);
// The configurations will not be sent to the language server until the default include paths and frameworks have been set.
// The event handlers must be set before this happens.
languageClient.sendRequest(QueryCompilerDefaultsRequest, {}).then((compilerDefaults: configs.CompilerDefaults) => {
this.configuration.CompilerDefaults = compilerDefaults;
});
// Once this is set, we don't defer any more callbacks.
this.languageClient = languageClient;
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", getNonDefaultSettings(this.RootUri));
this.failureMessageShown.Value = false;
// Listen for messages from the language server.
this.registerNotifications();
this.registerFileWatcher();
}, () => {
this.isSupported = false; // Running on an OS we don't support yet.
if (!this.failureMessageShown.Value) {
this.failureMessageShown.Value = true;
vscode.window.showErrorMessage("Unable to start the C/C++ language server. IntelliSense features will be disabled.");
}
});
} catch {
this.isSupported = false; // Running on an OS we don't support yet.
if (!this.failureMessageShown.Value) {
this.failureMessageShown.Value = true;
vscode.window.showErrorMessage("Unable to start the C/C++ language server. IntelliSense features will be disabled.");
}
}
}
private createLanguageClient(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder): LanguageClient {
let serverModule: string = getLanguageServerFileName();
let serverName: string = this.getName(workspaceFolder);
let serverOptions: ServerOptions = {
run: { command: serverModule },
debug: { command: serverModule, args: [ serverName ] }
};
let settings: CppSettings = new CppSettings(workspaceFolder ? workspaceFolder.uri : null);
let other: OtherSettings = new OtherSettings(workspaceFolder ? workspaceFolder.uri : null);
let storagePath: string = util.extensionContext.storagePath;
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
storagePath = path.join(storagePath, serverName);
}
let clientOptions: LanguageClientOptions = {
documentSelector: [
{ scheme: 'file', language: 'cpp' },
{ scheme: 'file', language: 'c' }
],
synchronize: {
// Synchronize the setting section to the server
configurationSection: ['C_Cpp', 'files', 'search']
},
workspaceFolder: workspaceFolder,
initializationOptions: {
clang_format_path: settings.clangFormatPath,
clang_format_style: settings.clangFormatStyle,
clang_format_fallbackStyle: settings.clangFormatFallbackStyle,
clang_format_sortIncludes: settings.clangFormatSortIncludes,
formatting: settings.formatting,
extension_path: util.extensionContext.extensionPath,
exclude_files: other.filesExclude,
exclude_search: other.searchExclude,
storage_path: storagePath,
tab_size: other.editorTabSize,
intelliSenseEngine: settings.intelliSenseEngine,
intelliSenseEngineFallback: settings.intelliSenseEngineFallback,
autocomplete: settings.autoComplete,
errorSquiggles: settings.errorSquiggles,
dimInactiveRegions: settings.dimInactiveRegions,
loggingLevel: settings.loggingLevel,
workspaceParsingPriority: settings.workspaceParsingPriority,
exclusionPolicy: settings.exclusionPolicy
},
middleware: createProtocolFilter(this, allClients), // Only send messages directed at this client.
errorHandler: {
error: () => ErrorAction.Continue,
closed: () => {
this.crashTimes.push(Date.now());
if (this.crashTimes.length < 5) {
let newClient: DefaultClient = <DefaultClient>allClients.replace(this, true);
newClient.crashTimes = this.crashTimes;
} else {
let elapsed: number = this.crashTimes[this.crashTimes.length - 1] - this.crashTimes[0];
if (elapsed <= 3 * 60 * 1000) {
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
vscode.window.showErrorMessage(`The language server for '${serverName}' crashed 5 times in the last 3 minutes. It will not be restarted.`);
} else {
vscode.window.showErrorMessage(`The language server crashed 5 times in the last 3 minutes. It will not be restarted.`);
}
allClients.replace(this, false);
} else {
this.crashTimes.shift();
let newClient: DefaultClient = <DefaultClient>allClients.replace(this, true);
newClient.crashTimes = this.crashTimes;
}
}
return CloseAction.DoNotRestart;
}
}
// TODO: should I set the output channel? Does this sort output between servers?
};
// Create the language client
return new LanguageClient(`cpptools: ${serverName}`, serverOptions, clientOptions);
}
public onDidChangeSettings(): void {
// This relies on getNonDefaultSettings being called first.
console.assert(Object.keys(previousCppSettings).length > 0);
let filter: (key: string, val: string) => boolean = (key: string, val: string) => {
return !(key in previousCppSettings) || val !== previousCppSettings[key];
};
let changedSettings: { [key: string] : string} = collectSettingsForTelemetry(filter, this.RootUri);
if (Object.keys(changedSettings).length > 0) {
if (changedSettings["commentContinuationPatterns"]) {
updateLanguageConfigurations();
}
telemetry.logLanguageServerEvent("CppSettingsChange", changedSettings, null);
}
}
public onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
let settings: CppSettings = new CppSettings(this.RootUri);
if (settings.dimInactiveRegions) {
//Apply text decorations to inactive regions
for (let e of editors) {
let valuePair: DecorationRangesPair = this.inactiveRegionsDecorations.get(e.document.uri.toString());
if (valuePair) {
e.setDecorations(valuePair.decoration, valuePair.ranges); // VSCode clears the decorations when the text editor becomes invisible
}
}
}
}
/**
* Take ownership of a document that was previously serviced by another client.
* This process involves sending a textDocument/didOpen message to the server so
* that it knows about the file, as well as adding it to this client's set of
* tracked documents.
*/
public takeOwnership(document: vscode.TextDocument): void {
let params: DidOpenTextDocumentParams = {
textDocument: {
uri: document.uri.toString(),
languageId: document.languageId,
version: document.version,
text: document.getText()
}
};
this.notifyWhenReady(() => this.languageClient.sendNotification(DidOpenNotification, params));
this.trackedDocuments.add(document);
}
/*************************************************************************************
* wait until the language client is ready for use before attempting to send messages
*************************************************************************************/
private requestWhenReady<T>(request: () => Thenable<T>): Thenable<T> {
if (this.languageClient) {
return request();
} else if (this.isSupported && this.onReadyPromise) {
return this.onReadyPromise.then(() => request());
} else {
return Promise.reject<T>("Unsupported client");
}
}
private notifyWhenReady(notify: () => void): void {
if (this.languageClient) {
notify();
} else if (this.isSupported && this.onReadyPromise) {
this.onReadyPromise.then(() => notify());
}
}
/**
* listen for notifications from the language server.
*/
private registerNotifications(): void {
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
this.languageClient.onNotification(ReloadWindowNotification, () => this.reloadWindow());
this.languageClient.onNotification(LogTelemetryNotification, (e) => this.logTelemetry(e));
this.languageClient.onNotification(ReportNavigationNotification, (e) => this.navigate(e));
this.languageClient.onNotification(ReportStatusNotification, (e) => this.updateStatus(e));
this.languageClient.onNotification(ReportTagParseStatusNotification, (e) => this.updateTagParseStatus(e));
this.languageClient.onNotification(InactiveRegionNotification, (e) => this.updateInactiveRegions(e));
this.setupOutputHandlers();
}
/**
* listen for file created/deleted events under the ${workspaceFolder} folder
*/
private registerFileWatcher(): void {
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
if (this.rootFolder) {
// WARNING: The default limit on Linux is 8k, so for big directories, this can cause file watching to fail.
this.rootPathFileWatcher = vscode.workspace.createFileSystemWatcher(
path.join(this.RootPath, "*"),
false /*ignoreCreateEvents*/,
true /*ignoreChangeEvents*/,
false /*ignoreDeleteEvents*/);
this.rootPathFileWatcher.onDidCreate((uri) => {
this.languageClient.sendNotification(FileCreatedNotification, { uri: uri.toString() });
});
this.rootPathFileWatcher.onDidDelete((uri) => {
this.languageClient.sendNotification(FileDeletedNotification, { uri: uri.toString() });
});
this.disposables.push(this.rootPathFileWatcher);
} else {
this.rootPathFileWatcher = undefined;
}
}
/**
* listen for logging messages from the language server and print them to the Output window
*/
private setupOutputHandlers(): void {
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
this.languageClient.onNotification(DebugProtocolNotification, (output) => {
if (!this.debugChannel) {
this.debugChannel = vscode.window.createOutputChannel(`C/C++ Debug Protocol: ${this.Name}`);
this.disposables.push(this.debugChannel);
}
this.debugChannel.appendLine("");
this.debugChannel.appendLine("************************************************************************************************************************");
this.debugChannel.append(`${output}`);
});
this.languageClient.onNotification(DebugLogNotification, (output) => {
if (!this.outputChannel) {
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
this.outputChannel = vscode.window.createOutputChannel(`C/C++: ${this.Name}`);
} else {
this.outputChannel = logger.getOutputChannel();
}
this.disposables.push(this.outputChannel);
}
this.outputChannel.appendLine(`${output}`);
});
}
/*******************************************************
* handle notifications coming from the language server
*******************************************************/
private reloadWindow(): void {
let reload: string = "Reload";
vscode.window.showInformationMessage("Reload the workspace for the settings change to take effect.", reload).then((value: string) => {
if (value === reload) {
vscode.commands.executeCommand("workbench.action.reloadWindow");
}
});
}
private logTelemetry(notificationBody: TelemetryPayload): void {
telemetry.logLanguageServerEvent(notificationBody.event, notificationBody.properties, notificationBody.metrics);
}
private navigate(payload: NavigationPayload): void {
let cppSettings: CppSettings = new CppSettings(this.RootUri);
// TODO: Move this code to a different place?
if (cppSettings.autoAddFileAssociations && payload.navigation.startsWith("<def")) {
this.addFileAssociations(payload.navigation.substr(4));
return;
}
// If it's too big, it doesn't appear.
// The space available depends on the user's resolution and space taken up by other UI.
let currentNavigation: string = payload.navigation;
let maxLength: number = cppSettings.navigationLength;
if (currentNavigation.length > maxLength) {
currentNavigation = currentNavigation.substring(0, maxLength - 3).concat("...");
}
this.model.navigationLocation.Value = currentNavigation;
}
private addFileAssociations(fileAssociations: string): void {
let settings: OtherSettings = new OtherSettings(this.RootUri);
let assocs: any = settings.filesAssociations;
let is_c: boolean = fileAssociations.startsWith("c");
// Skip over rest of header: c>; or >;
fileAssociations = fileAssociations.substr(is_c ? 3 : 2);
let filesAndPaths: string[] = fileAssociations.split(";");
let foundNewAssociation: boolean = false;
for (let i: number = 0; i < filesAndPaths.length - 1; ++i) {
let fileAndPath: string[] = filesAndPaths[i].split("@");
let file: string = fileAndPath[0];
let filePath: string = fileAndPath[1];
if ((file in assocs) || (("**/" + file) in assocs)) {
continue; // File already has an association.
}
let j: number = file.lastIndexOf('.');
if (j !== -1) {
let ext: string = file.substr(j);
if ((("*" + ext) in assocs) || (("**/*" + ext) in assocs)) {
continue; // Extension already has an association.
}
}
let foundGlobMatch: boolean = false;
for (let assoc in assocs) {
if (minimatch(filePath, assoc)) {
foundGlobMatch = true;
break; // Assoc matched a glob pattern.
}
}
if (foundGlobMatch) {
continue;
}
assocs[file] = is_c ? "c" : "cpp";
foundNewAssociation = true;
}
if (foundNewAssociation) {
settings.filesAssociations = assocs;
}
}
private updateStatus(notificationBody: ReportStatusNotificationBody): void {
let message: string = notificationBody.status;
util.setProgress(util.getProgressExecutableSuccess());
if (message.endsWith("Indexing...")) {
this.model.isTagParsing.Value = true;
} else if (message.endsWith("Updating IntelliSense...")) {
this.model.isUpdatingIntelliSense.Value = true;
} else if (message.endsWith("IntelliSense Ready")) {
this.model.isUpdatingIntelliSense.Value = false;
} else if (message.endsWith("Ready")) { // Tag Parser Ready
this.model.isTagParsing.Value = false;
util.setProgress(util.getProgressParseRootSuccess());
} else if (message.endsWith("No Squiggles")) {
util.setIntelliSenseProgress(util.getProgressIntelliSenseNoSquiggles());
} else if (message.endsWith("IntelliSense Fallback")) {
let showIntelliSenseFallbackMessage: PersistentState<boolean> = new PersistentState<boolean>("CPP.showIntelliSenseFallbackMessage", true);
if (showIntelliSenseFallbackMessage.Value) {
let learnMorePanel: string = "Learn More";
let dontShowAgain: string = "Don't Show Again";
vscode.window.showInformationMessage("Configure includePath for better IntelliSense results.", learnMorePanel, dontShowAgain).then((value) => {
switch (value) {
case learnMorePanel:
let uri: vscode.Uri = vscode.Uri.parse(`https://go.microsoft.com/fwlink/?linkid=864631`);
vscode.commands.executeCommand('vscode.open', uri);
vscode.commands.getCommands(true).then((commands: string[]) => {
if (commands.indexOf("workbench.action.problems.focus") >= 0) {
vscode.commands.executeCommand("workbench.action.problems.focus");
}
});
break;
case dontShowAgain:
showIntelliSenseFallbackMessage.Value = false;
break;
}
});
}
}
}
private updateTagParseStatus(notificationBody: ReportStatusNotificationBody): void {
this.model.tagParserStatus.Value = notificationBody.status;
}
private updateInactiveRegions(params: InactiveRegionParams): void {
let renderOptions: vscode.DecorationRenderOptions = {
light: { color: "rgba(175,175,175,1.0)" },
dark: { color: "rgba(155,155,155,1.0)" },
rangeBehavior: vscode.DecorationRangeBehavior.ClosedOpen
};
let decoration: vscode.TextEditorDecorationType = vscode.window.createTextEditorDecorationType(renderOptions);
// We must convert to vscode.Ranges in order to make use of the API's
let ranges: vscode.Range[] = [];
params.regions.forEach(element => {
let newRange : vscode.Range = new vscode.Range(element.startLine, 0, element.endLine, 0);
ranges.push(newRange);
});
// Find entry for cached file and act accordingly
let valuePair: DecorationRangesPair = this.inactiveRegionsDecorations.get(params.uri);
if (valuePair) {
// Disposing of and resetting the decoration will undo previously applied text decorations
valuePair.decoration.dispose();
valuePair.decoration = decoration;
// As vscode.TextEditor.setDecorations only applies to visible editors, we must cache the range for when another editor becomes visible
valuePair.ranges = ranges;
} else { // The entry does not exist. Make a new one
let toInsert: DecorationRangesPair = {
decoration: decoration,
ranges: ranges
};
this.inactiveRegionsDecorations.set(params.uri, toInsert);
}
let settings: CppSettings = new CppSettings(this.RootUri);
if (settings.dimInactiveRegions) {
// Apply the decorations to all *visible* text editors
let editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri.toString() === params.uri);
for (let e of editors) {
e.setDecorations(decoration, ranges);
}
}
}
/*********************************************
* requests to the language server
*********************************************/
public requestGoToDeclaration(): Thenable<void> {
return this.requestWhenReady(() => this.languageClient.sendRequest(GoToDeclarationRequest, null));
}
public requestSwitchHeaderSource(rootPath: string, fileName: string): Thenable<string> {
let params: SwitchHeaderSourceParams = {
rootPath: rootPath,
switchHeaderSourceFileName: fileName
};
return this.requestWhenReady(() => this.languageClient.sendRequest(SwitchHeaderSourceRequest, params));
}
public requestNavigationList(document: vscode.TextDocument): Thenable<string> {
return this.requestWhenReady(() => {
return this.languageClient.sendRequest(NavigationListRequest, this.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document));
});
}
/*********************************************
* notifications to the language server
*********************************************/
public activeDocumentChanged(document: vscode.TextDocument): void {
this.notifyWhenReady(() => {
this.languageClient.sendNotification(ActiveDocumentChangeNotification, this.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document));
});
}
/**
* enable UI updates from this client and resume tag parsing on the server.
*/
public activate(): void {
for (let key in this.model) {
if (this.model.hasOwnProperty(key)) {
this.model[key].activate();
}
}
this.resumeParsing();
}
public selectionChanged(selection: vscode.Position): void {
this.notifyWhenReady(() => this.languageClient.sendNotification(TextEditorSelectionChangeNotification, selection));
}
public resetDatabase(): void {
this.notifyWhenReady(() => this.languageClient.sendNotification(ResetDatabaseNotification));
}
/**
* disable UI updates from this client and pause tag parsing on the server.
*/
public deactivate(): void {
for (let key in this.model) {
if (this.model.hasOwnProperty(key)) {
this.model[key].deactivate();
}
}
this.pauseParsing();
}
public pauseParsing(): void {
this.notifyWhenReady(() => this.languageClient.sendNotification(PauseParsingNotification));
}
public resumeParsing(): void {
this.notifyWhenReady(() => this.languageClient.sendNotification(ResumeParsingNotification));
}
private onConfigurationsChanged(configurations: configs.Configuration[]): void {
let params: FolderSettingsParams = {
configurations: configurations,
currentConfiguration: this.configuration.CurrentConfiguration
};
this.notifyWhenReady(() => {
this.languageClient.sendNotification(ChangeFolderSettingsNotification, params);
this.model.activeConfigName.Value = configurations[params.currentConfiguration].name;
});
}
private onSelectedConfigurationChanged(index: number): void {
let params: FolderSelectedSettingParams = {
currentConfiguration: index
};
this.notifyWhenReady(() => {
this.languageClient.sendNotification(ChangeSelectedSettingNotification, params);
this.model.activeConfigName.Value = this.configuration.ConfigurationNames[index];
});
}
private onCompileCommandsChanged(path: string): void {
let params: FileChangedParams = {
uri: path
};
this.notifyWhenReady(() => this.languageClient.sendNotification(ChangeCompileCommandsNotification, params));
}
/*********************************************
* command handlers
*********************************************/
public handleConfigurationSelectCommand(): void {
this.notifyWhenReady(() => {
ui.showConfigurations(this.configuration.ConfigurationNames)
.then((index: number) => {
if (index < 0) {
return;
}
this.configuration.select(index);
});
});
}
public handleShowParsingCommands(): void {
this.notifyWhenReady(() => {
ui.showParsingCommands()
.then((index: number) => {
if (index === 0) {
this.pauseParsing();
} else if (index === 1) {
this.resumeParsing();
}
});
});
}
public handleConfigurationEditCommand(): void {
this.notifyWhenReady(() => this.configuration.handleConfigurationEditCommand(vscode.window.showTextDocument));
}
public handleAddToIncludePathCommand(path: string): void {
this.notifyWhenReady(() => this.configuration.addToIncludePathCommand(path));
}
public onInterval(): void {
// These events can be discarded until the language client is ready.
// Don't queue them up with this.notifyWhenReady calls.
if (this.languageClient !== undefined && this.configuration !== undefined) {
this.languageClient.sendNotification(IntervalTimerNotification);
this.configuration.checkCppProperties();
}
}
public dispose(): Thenable<void> {
let promise: Thenable<void> = (this.languageClient) ? this.languageClient.stop() : Promise.resolve();
return promise.then(() => {
this.disposables.forEach((d) => d.dispose());
this.disposables = [];
for (let key in this.model) {
if (this.model.hasOwnProperty(key)) {
this.model[key].dispose();
}
}
});
}
}
function getLanguageServerFileName(): string {
let extensionProcessName: string = 'Microsoft.VSCode.CPP.Extension';
let plat: NodeJS.Platform = process.platform;
if (plat === 'linux') {
extensionProcessName += '.linux';
} else if (plat === 'darwin') {
extensionProcessName += '.darwin';
} else if (plat === 'win32') {
extensionProcessName += '.exe';
} else {
throw "Invalid Platform";
}
return path.resolve(util.getExtensionFilePath("bin"), extensionProcessName);
}
class NullClient implements Client {
private booleanEvent = new vscode.EventEmitter<boolean>();
private stringEvent = new vscode.EventEmitter<string>();
public get TagParsingChanged(): vscode.Event<boolean> { return this.booleanEvent.event; }
public get IntelliSenseParsingChanged(): vscode.Event<boolean> { return this.booleanEvent.event; }
public get NavigationLocationChanged(): vscode.Event<string> { return this.stringEvent.event; }
public get TagParserStatusChanged(): vscode.Event<string> { return this.stringEvent.event; }
public get ActiveConfigChanged(): vscode.Event<string> { return this.stringEvent.event; }
RootPath: string = "/";
RootUri: vscode.Uri = vscode.Uri.file("/");
Name: string = "(empty)";
TrackedDocuments = new Set<vscode.TextDocument>();
onDidChangeSettings(): void {}
onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {}
takeOwnership(document: vscode.TextDocument): void {}
requestGoToDeclaration(): Thenable<void> { return Promise.resolve(); }
requestSwitchHeaderSource(rootPath: string, fileName: string): Thenable<string> { return Promise.resolve(""); }
requestNavigationList(document: vscode.TextDocument): Thenable<string> { return Promise.resolve(""); }
activeDocumentChanged(document: vscode.TextDocument): void {}
activate(): void {}
selectionChanged(selection: vscode.Position): void {}
resetDatabase(): void {}
deactivate(): void {}
pauseParsing(): void {}
resumeParsing(): void {}
handleConfigurationSelectCommand(): void {}
handleShowParsingCommands(): void {}
handleConfigurationEditCommand(): void {}
handleAddToIncludePathCommand(path: string): void {}
onInterval(): void {}
dispose(): Thenable<void> {
this.booleanEvent.dispose();
this.stringEvent.dispose();
return Promise.resolve();
}
}
@@ -0,0 +1,209 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import * as util from '../common';
import * as telemetry from '../telemetry';
import * as cpptools from './client';
const defaultClientKey: string = "@@default@@";
export interface ClientKey {
name: string;
key: string;
}
export class ClientCollection {
private disposables: vscode.Disposable[] = [];
private languageClients = new Map<string, cpptools.Client>();
private defaultClient: cpptools.Client;
private activeClient: cpptools.Client;
private activeDocument: vscode.TextDocument;
public get ActiveClient(): cpptools.Client { return this.activeClient; }
public get Names(): ClientKey[] {
let result: ClientKey[] = [];
this.languageClients.forEach((client, key) => {
result.push({ name: client.Name, key: key });
});
return result;
}
public get Count(): number { return this.languageClients.size; }
constructor() {
let key: string = defaultClientKey;
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
let folder: vscode.WorkspaceFolder = vscode.workspace.workspaceFolders[0];
key = util.asFolder(folder.uri);
this.activeClient = cpptools.createClient(this, folder);
} else {
this.activeClient = cpptools.createClient(this);
}
this.defaultClient = this.activeClient;
this.languageClients.set(key, this.activeClient);
this.disposables.push(vscode.workspace.onDidChangeWorkspaceFolders(e => this.onDidChangeWorkspaceFolders(e)));
this.disposables.push(vscode.workspace.onDidOpenTextDocument(d => this.onDidOpenTextDocument(d)));
this.disposables.push(vscode.workspace.onDidCloseTextDocument(d => this.onDidCloseTextDocument(d)));
}
public activeDocumentChanged(document: vscode.TextDocument): void {
this.activeDocument = document;
let activeClient: cpptools.Client = this.getClientFor(document.uri);
// Notify the active client that the document has changed.
activeClient.activeDocumentChanged(document);
// If the active client changed, resume the new client and tell the currently active client to deactivate.
if (activeClient !== this.activeClient) {
activeClient.activate();
this.activeClient.deactivate();
this.activeClient = activeClient;
}
}
/**
* get a handle to a language client. returns null if the client was not found.
*/
public get(key: string): cpptools.Client | null {
if (this.languageClients.has(key)) {
return this.languageClients.get(key);
}
console.assert("key not found");
return null;
}
public forEach(callback: (client: cpptools.Client) => void): void {
this.languageClients.forEach(callback);
}
public checkOwnership(client: cpptools.Client, document: vscode.TextDocument): boolean {
let owners: cpptools.Client[] = [];
this.languageClients.forEach(languageClient => {
if (document.uri.fsPath.startsWith(languageClient.RootPath)) {
owners.push(languageClient);
}
});
if (owners.length === 0) {
owners.push(this.activeClient);
}
return (owners[0] === client); // TODO: we may want to pick the owner with the longest path?
}
/**
* creates a new client to replace one that crashed.
*/
public replace(client: cpptools.Client, transferFileOwnership: boolean): cpptools.Client {
let key: string = undefined;
for (let pair of this.languageClients) {
if (pair[1] === client) {
key = pair[0];
break;
}
}
if (key) {
this.languageClients.delete(key);
if (transferFileOwnership) {
// This will create a new Client for the workspace since we removed the old one from this.languageClients.
client.TrackedDocuments.forEach(document => this.transferOwnership(document, client));
client.TrackedDocuments.clear();
} else {
// Create an empty client that will continue to "own" files matching this workspace, but ignore all messages from VS Code.
this.languageClients.set(key, cpptools.createNullClient());
}
if (this.activeClient === client) {
this.activeClient = this.getClientFor(this.activeDocument.uri);
this.activeClient.activeDocumentChanged(this.activeDocument);
}
client.dispose();
return this.languageClients.get(key);
} else {
console.assert(key, "unable to locate language client");
return null;
}
}
/**
* Remove folders that were closed. We don't check the e.added property because we will
* add new clients on-demand as files are opened.
*/
private onDidChangeWorkspaceFolders(e?: vscode.WorkspaceFoldersChangeEvent): void {
let folderCount: number = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders.length : 0;
if (folderCount > 1) {
telemetry.logLanguageServerEvent("workspaceFoldersChange", { "count": folderCount.toString() });
}
if (e !== undefined) {
e.removed.forEach(folder => {
let path: string = util.asFolder(folder.uri);
let client: cpptools.Client = this.languageClients.get(path);
if (client) {
this.languageClients.delete(path); // Do this first so that we don't iterate on it during the ownership transfer process.
// Transfer ownership of the client's documents to another client.
// (this includes calling textDocument/didOpen on the new client so that the server knows it's open too)
client.TrackedDocuments.forEach(document => this.transferOwnership(document, client));
client.TrackedDocuments.clear();
if (this.activeClient === client) {
// Need to make a different client the active client.
this.activeClient = this.getClientFor(this.activeDocument.uri);
this.activeClient.activeDocumentChanged(this.activeDocument);
// may not need this, the navigation UI should not have changed.
// this.activeClient.selectionChanged(vscode.window.activeTextEditor.selection.start);
}
client.dispose();
}
});
}
}
private transferOwnership(document: vscode.TextDocument, oldOwner: cpptools.Client): void {
let newOwner: cpptools.Client = this.getClientFor(document.uri);
console.assert(newOwner !== oldOwner, "'oldOwner' should not be in the list of clients to consider");
newOwner.takeOwnership(document);
}
private onDidOpenTextDocument(document: vscode.TextDocument): void {
if (document.languageId === "c" || document.languageId === "cpp") {
// Make sure a client exists for this document's workspace.
this.getClientFor(document.uri);
}
}
private getClientFor(uri: vscode.Uri): cpptools.Client {
let folder: vscode.WorkspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
if (!folder) {
return this.defaultClient;
} else {
let key: string = util.asFolder(folder.uri);
if (!this.languageClients.has(key)) {
this.languageClients.set(key, cpptools.createClient(this, folder));
}
return this.languageClients.get(key);
}
}
private onDidCloseTextDocument(document: vscode.TextDocument): void {
// Don't seem to need to do anything here since we clean up when the workspace is closed instead.
}
public dispose(): Thenable<void> {
let promises: Thenable<void>[] = [];
// this.defaultClient is already in this.languageClients, so do not call dispose() on it.
this.defaultClient = undefined;
this.languageClients.forEach(client => promises.push(client.dispose()));
this.languageClients.clear();
return Promise.all(promises).then(() => undefined);
}
}
@@ -0,0 +1,560 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as path from 'path';
import * as fs from "fs";
import * as vscode from 'vscode';
import * as util from '../common';
import { PersistentFolderState } from './persistentState';
const configVersion: number = 3;
let defaultSettings: string = `{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"$\{workspaceFolder\}"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"$\{workspaceFolder\}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include",
"/usr/local/include",
"$\{workspaceFolder\}"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"$\{workspaceFolder\}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
"$\{workspaceFolder\}"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
"$\{workspaceFolder\}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": ${configVersion}
}
`;
export interface Browse {
path?: string[];
limitSymbolsToIncludedHeaders?: boolean;
databaseFilename?: string;
}
export interface Configuration {
name: string;
compilerPath?: string;
cStandard?: string;
cppStandard?: string;
includePath?: string[];
macFrameworkPath?: string[];
defines?: string[];
intelliSenseMode?: string;
compileCommands?: string;
forcedInclude?: string[];
browse?: Browse;
}
export interface CompilerDefaults {
compilerPath: string;
cStandard: string;
cppStandard: string;
includes: string[];
frameworks: string[];
}
interface ConfigurationJson {
configurations: Configuration[];
version: number;
}
export class CppProperties {
private propertiesFile: vscode.Uri = null;
private readonly configFolder: string;
private configurationJson: ConfigurationJson = null;
private currentConfigurationIndex: PersistentFolderState<number>;
private configFileWatcher: vscode.FileSystemWatcher = null;
private configFileWatcherFallbackTime: Date = new Date(); // Used when file watching fails.
private compileCommandFileWatchers: fs.FSWatcher[] = [];
private defaultCompilerPath: string = null;
private defaultCStandard: string = null;
private defaultCppStandard: string = null;
private defaultIncludes: string[] = null;
private defaultFrameworks: string[] = null;
private readonly configurationGlobPattern: string = "**/c_cpp_properties.json"; // TODO: probably should be a single file, not all files...
private disposables: vscode.Disposable[] = [];
private configurationsChanged = new vscode.EventEmitter<Configuration[]>();
private selectionChanged = new vscode.EventEmitter<number>();
private compileCommandsChanged = new vscode.EventEmitter<string>();
// Any time the `defaultSettings` are parsed and assigned to `this.configurationJson`,
// we want to track when the default includes have been added to it.
private configurationIncomplete: boolean = true;
constructor(rootPath: string) {
console.assert(rootPath !== undefined);
this.currentConfigurationIndex = new PersistentFolderState<number>("CppProperties.currentConfigurationIndex", -1, rootPath);
this.configFolder = path.join(rootPath, ".vscode");
this.resetToDefaultSettings(this.currentConfigurationIndex.Value === -1);
let configFilePath: string = path.join(this.configFolder, "c_cpp_properties.json");
if (fs.existsSync(configFilePath)) {
this.propertiesFile = vscode.Uri.file(configFilePath);
}
this.configFileWatcher = vscode.workspace.createFileSystemWatcher(path.join(this.configFolder, this.configurationGlobPattern));
this.disposables.push(this.configFileWatcher);
this.configFileWatcher.onDidCreate((uri) => {
this.propertiesFile = uri;
this.handleConfigurationChange();
});
this.configFileWatcher.onDidDelete(() => {
this.propertiesFile = null;
this.resetToDefaultSettings(true);
this.handleConfigurationChange();
});
this.configFileWatcher.onDidChange(() => {
this.handleConfigurationChange();
});
this.disposables.push(vscode.Disposable.from(this.configurationsChanged, this.selectionChanged, this.compileCommandsChanged));
}
public get ConfigurationsChanged(): vscode.Event<Configuration[]> { return this.configurationsChanged.event; }
public get SelectionChanged(): vscode.Event<number> { return this.selectionChanged.event; }
public get CompileCommandsChanged(): vscode.Event<string> { return this.compileCommandsChanged.event; }
public get Configurations(): Configuration[] { return this.configurationJson.configurations; }
public get CurrentConfiguration(): number { return this.currentConfigurationIndex.Value; }
public get ConfigurationNames(): string[] {
let result: string[] = [];
this.configurationJson.configurations.forEach((config: Configuration) => result.push(config.name));
return result;
}
public set CompilerDefaults(compilerDefaults: CompilerDefaults) {
this.defaultCompilerPath = compilerDefaults.compilerPath;
this.defaultCStandard = compilerDefaults.cStandard;
this.defaultCppStandard = compilerDefaults.cppStandard;
this.defaultIncludes = compilerDefaults.includes;
this.defaultFrameworks = compilerDefaults.frameworks;
// defaultPaths is only used when there isn't a c_cpp_properties.json, but we don't send the configuration changed event
// to the language server until the default include paths and frameworks have been sent.
this.handleConfigurationChange();
}
private onConfigurationsChanged(): void {
this.configurationsChanged.fire(this.Configurations);
}
private onSelectionChanged(): void {
this.selectionChanged.fire(this.CurrentConfiguration);
}
private onCompileCommandsChanged(path: string): void {
this.compileCommandsChanged.fire(path);
}
private resetToDefaultSettings(resetIndex: boolean): void {
this.configurationJson = JSON.parse(defaultSettings);
if (resetIndex || this.CurrentConfiguration < 0 ||
this.CurrentConfiguration >= this.configurationJson.configurations.length) {
this.currentConfigurationIndex.Value = this.getConfigIndexForPlatform(this.configurationJson);
}
this.configurationIncomplete = true;
}
private applyDefaultIncludePathsAndFrameworks(): void {
if (this.configurationIncomplete && this.defaultIncludes && this.defaultFrameworks) {
this.configurationJson.configurations[this.CurrentConfiguration].includePath = this.defaultIncludes;
this.configurationJson.configurations[this.CurrentConfiguration].browse.path = this.defaultIncludes;
if (process.platform === 'darwin') {
this.configurationJson.configurations[this.CurrentConfiguration].macFrameworkPath = this.defaultFrameworks;
}
if (this.defaultCompilerPath) {
this.configurationJson.configurations[this.CurrentConfiguration].compilerPath = this.defaultCompilerPath;
}
if (this.defaultCStandard) {
this.configurationJson.configurations[this.CurrentConfiguration].cStandard = this.defaultCStandard;
}
if (this.defaultCppStandard) {
this.configurationJson.configurations[this.CurrentConfiguration].cppStandard = this.defaultCppStandard;
}
this.configurationIncomplete = false;
}
}
private getConfigIndexForPlatform(config: any): number {
if (this.configurationJson.configurations.length > 3) {
return this.configurationJson.configurations.length - 1; // Default to the last custom configuration.
}
let nodePlatform: NodeJS.Platform = process.platform;
let plat: string;
if (nodePlatform === 'linux') {
plat = "Linux";
} else if (nodePlatform === 'darwin') {
plat = "Mac";
} else if (nodePlatform === 'win32') {
plat = "Win32";
}
for (let i: number = 0; i < this.configurationJson.configurations.length; i++) {
if (config.configurations[i].name === plat) {
return i;
}
}
return this.configurationJson.configurations.length - 1;
}
private getIntelliSenseModeForPlatform(name: string): string {
// Do the built-in configs first.
if (name === "Linux" || name === "Mac") {
return "clang-x64";
} else if (name === "Win32") {
return "msvc-x64";
} else {
// Custom configs default to the OS's preference.
let nodePlatform: NodeJS.Platform = process.platform;
if (nodePlatform === 'linux' || nodePlatform === 'darwin') {
return "clang-x64";
}
}
return "msvc-x64";
}
private includePathConverted(): boolean {
for (let i: number = 0; i < this.configurationJson.configurations.length; i++) {
if (this.configurationJson.configurations[i].browse === undefined || this.configurationJson.configurations[i].browse.path === undefined) {
return false;
}
}
return true;
}
public addToIncludePathCommand(path: string): void {
this.handleConfigurationEditCommand((document: vscode.TextDocument) => {
let config: Configuration = this.configurationJson.configurations[this.CurrentConfiguration];
config.includePath.splice(config.includePath.length, 0, path);
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
this.updateServerOnFolderSettingsChange();
});
}
public select(index: number): Configuration {
if (index === this.configurationJson.configurations.length) {
this.handleConfigurationEditCommand(vscode.window.showTextDocument);
return;
}
this.currentConfigurationIndex.Value = index;
this.onSelectionChanged();
}
private resolveAndSplit(paths: string[] | undefined): string[] {
let result: string[] = [];
if (paths) {
paths.forEach(entry => {
let entries: string[] = util.resolveVariables(entry).split(";").filter(e => e);
result = result.concat(entries);
});
}
return result;
}
private updateServerOnFolderSettingsChange(): void {
for (let i: number = 0; i < this.configurationJson.configurations.length; i++) {
let configuration: Configuration = this.configurationJson.configurations[i];
if (configuration.includePath) {
configuration.includePath = this.resolveAndSplit(configuration.includePath);
}
if (configuration.browse && configuration.browse.path) {
configuration.browse.path = this.resolveAndSplit(configuration.browse.path);
}
if (configuration.macFrameworkPath) {
configuration.macFrameworkPath = this.resolveAndSplit(configuration.macFrameworkPath);
}
if (configuration.forcedInclude) {
configuration.forcedInclude = this.resolveAndSplit(configuration.forcedInclude);
}
if (configuration.compileCommands) {
configuration.compileCommands = util.resolveVariables(configuration.compileCommands);
}
if (configuration.compilerPath) {
configuration.compilerPath = util.resolveVariables(configuration.compilerPath);
}
}
this.updateCompileCommandsFileWatchers();
if (!this.configurationIncomplete) {
this.onConfigurationsChanged();
}
}
// Dispose existing and loop through cpp and populate with each file (exists or not) as you go.
// paths are expected to have variables resolved already
public updateCompileCommandsFileWatchers(): void {
this.compileCommandFileWatchers.forEach((watcher: fs.FSWatcher) => watcher.close());
this.compileCommandFileWatchers = []; //reset it
let filePaths: Set<string> = new Set<string>();
this.configurationJson.configurations.forEach(c => {
if (c.compileCommands !== undefined && fs.existsSync(c.compileCommands)) {
filePaths.add(c.compileCommands);
}
});
try {
filePaths.forEach((path: string) => {
this.compileCommandFileWatchers.push(fs.watch(path, (event: string, filename: string) => {
if (event !== "rename") {
this.onCompileCommandsChanged(path);
}
}));
});
} catch (e) {
// The file watcher limit is hit.
// TODO: Check if the compile commands file has a higher timestamp during the interval timer.
}
}
public handleConfigurationEditCommand(onSuccess: (document: vscode.TextDocument) => void): void {
if (this.propertiesFile && fs.existsSync(this.propertiesFile.fsPath)) {
vscode.workspace.openTextDocument(this.propertiesFile).then((document: vscode.TextDocument) => {
onSuccess(document);
});
} else {
fs.mkdir(this.configFolder, (e: NodeJS.ErrnoException) => {
if (!e || e.code === 'EEXIST') {
let dirPathEscaped: string = this.configFolder.replace("#", "%23");
let fullPathToFile: string = path.join(dirPathEscaped, "c_cpp_properties.json");
let filePath: vscode.Uri = vscode.Uri.parse("untitled:" + fullPathToFile);
vscode.workspace.openTextDocument(filePath).then((document: vscode.TextDocument) => {
let edit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
if (this.configurationJson === undefined) {
this.resetToDefaultSettings(true);
}
this.applyDefaultIncludePathsAndFrameworks();
edit.insert(document.uri, new vscode.Position(0, 0), JSON.stringify(this.configurationJson, null, 4));
vscode.workspace.applyEdit(edit).then((status) => {
// Fix for issue 163
// https://github.com/Microsoft/vscppsamples/issues/163
// Save the file to disk so that when the user tries to re-open the file it exists.
// Before this fix the file existed but was unsaved, so we went through the same
// code path and reapplied the edit.
document.save().then(() => {
this.propertiesFile = vscode.Uri.file(path.join(this.configFolder, "c_cpp_properties.json"));
vscode.workspace.openTextDocument(this.propertiesFile).then((document: vscode.TextDocument) => {
onSuccess(document);
});
});
});
});
}
});
}
}
private handleConfigurationChange(): void {
this.configFileWatcherFallbackTime = new Date();
if (this.propertiesFile) {
this.parsePropertiesFile();
// parsePropertiesFile can fail, but it won't overwrite an existing configurationJson in the event of failure.
// this.configurationJson should only be undefined here if we have never successfully parsed the propertiesFile.
if (this.configurationJson !== undefined) {
if (this.CurrentConfiguration < 0 ||
this.CurrentConfiguration >= this.configurationJson.configurations.length) {
// If the index is out of bounds (during initialization or due to removal of configs), fix it.
this.currentConfigurationIndex.Value = this.getConfigIndexForPlatform(this.configurationJson);
}
}
}
if (this.configurationJson === undefined) {
this.resetToDefaultSettings(true); // I don't think there's a case where this will be hit anymore.
}
this.applyDefaultIncludePathsAndFrameworks();
this.updateServerOnFolderSettingsChange();
}
private parsePropertiesFile(): void {
try {
let readResults: string = fs.readFileSync(this.propertiesFile.fsPath, 'utf8');
if (readResults === "") {
return; // Repros randomly when the file is initially created. The parse will get called again after the file is written.
}
// Try to use the same configuration as before the change.
let newJson: ConfigurationJson = JSON.parse(readResults);
if (!newJson || !newJson.configurations || newJson.configurations.length === 0) {
throw { message: "Invalid configuration file. There must be at least one configuration present in the array." };
}
if (!this.configurationIncomplete && this.configurationJson && this.configurationJson.configurations &&
this.CurrentConfiguration < this.configurationJson.configurations.length) {
for (let i: number = 0; i < newJson.configurations.length; i++) {
if (newJson.configurations[i].name === this.configurationJson.configurations[this.CurrentConfiguration].name) {
this.currentConfigurationIndex.Value = i;
break;
}
}
}
this.configurationJson = newJson;
if (this.CurrentConfiguration >= newJson.configurations.length) {
this.currentConfigurationIndex.Value = this.getConfigIndexForPlatform(newJson);
}
// Warning: There is a chance that this is incorrect in the event that the c_cpp_properties.json file was created before
// the system includes were available.
this.configurationIncomplete = false;
let dirty: boolean = false;
for (let i: number = 0; i < this.configurationJson.configurations.length; i++) {
let config: Configuration = this.configurationJson.configurations[i];
if (config.intelliSenseMode === undefined) {
dirty = true;
config.intelliSenseMode = this.getIntelliSenseModeForPlatform(config.name);
}
}
if (this.configurationJson.version !== configVersion) {
dirty = true;
if (this.configurationJson.version === undefined) {
this.updateToVersion2();
}
if (this.configurationJson.version === 2) {
this.updateToVersion3();
} else {
this.configurationJson.version = configVersion;
vscode.window.showErrorMessage('Unknown version number found in c_cpp_properties.json. Some features may not work as expected.');
}
}
// Update the compilerPath, cStandard, and cppStandard with the default if they're missing.
let config: Configuration = this.configurationJson.configurations[this.CurrentConfiguration];
// Don't set the default if compileCommands exist, until it is fixed to have the correct value.
if (config.compilerPath === undefined && this.defaultCompilerPath && !config.compileCommands) {
config.compilerPath = this.defaultCompilerPath;
dirty = true;
}
if (!config.cStandard && this.defaultCStandard) {
config.cStandard = this.defaultCStandard;
dirty = true;
}
if (!config.cppStandard && this.defaultCppStandard) {
config.cppStandard = this.defaultCppStandard;
dirty = true;
}
if (dirty) {
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
}
} catch (err) {
vscode.window.showErrorMessage('Failed to parse "' + this.propertiesFile.fsPath + '": ' + err.message);
throw err;
}
}
private updateToVersion2(): void {
this.configurationJson.version = 2;
if (!this.includePathConverted()) {
for (let i: number = 0; i < this.configurationJson.configurations.length; i++) {
let config: Configuration = this.configurationJson.configurations[i];
if (config.browse === undefined) {
config.browse = {};
}
if (config.browse.path === undefined && (this.defaultIncludes !== undefined || config.includePath !== undefined)) {
config.browse.path = (config.includePath === undefined) ? this.defaultIncludes.slice(0) : config.includePath.slice(0);
}
}
}
}
private updateToVersion3(): void {
this.configurationJson.version = 3;
for (let i: number = 0; i < this.configurationJson.configurations.length; i++) {
let config: Configuration = this.configurationJson.configurations[i];
// Look for Mac configs and extra configs on Mac systems
if (config.name === "Mac" || (process.platform === "darwin" && config.name !== "Win32" && config.name !== "Linux")) {
if (config.macFrameworkPath === undefined) {
config.macFrameworkPath = [
"/System/Library/Frameworks",
"/Library/Frameworks"
];
}
}
}
}
public checkCppProperties(): void {
// Check for change properties in case of file watcher failure.
let propertiesFile: string = path.join(this.configFolder, "c_cpp_properties.json");
fs.stat(propertiesFile, (err, stats) => {
if (err) {
if (this.propertiesFile !== null) {
this.propertiesFile = null; // File deleted.
this.resetToDefaultSettings(true);
this.handleConfigurationChange();
}
} else if (stats.mtime > this.configFileWatcherFallbackTime) {
if (this.propertiesFile === null) {
this.propertiesFile = vscode.Uri.file(propertiesFile); // File created.
}
this.handleConfigurationChange();
}
});
}
dispose(): void {
this.disposables.forEach((d) => d.dispose());
this.disposables = [];
this.compileCommandFileWatchers.forEach((watcher: fs.FSWatcher) => watcher.close());
this.compileCommandFileWatchers = []; //reset it
}
}
@@ -0,0 +1,47 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as vscode from 'vscode';
export class DataBinding<T> {
private value: T;
private valueChanged = new vscode.EventEmitter<T>();
private isActive: boolean = true;
constructor(value: T) {
this.value = value;
this.isActive = true;
}
public get Value(): T {
return this.value;
}
public set Value(value: T) {
if (value !== this.value) {
this.value = value;
if (this.isActive) {
this.valueChanged.fire(this.value);
}
}
}
public get ValueChanged(): vscode.Event<T> {
return this.valueChanged.event;
}
public activate(): void {
this.isActive = true;
this.valueChanged.fire(this.value);
}
public deactivate(): void {
this.isActive = false;
}
public dispose(): void {
this.deactivate();
this.valueChanged.dispose();
}
}
+453
View File
@@ -0,0 +1,453 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as path from 'path';
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as util from '../common';
import * as telemetry from '../telemetry';
import { UI, getUI } from './ui';
import { Client } from './client';
import { ClientCollection } from './clientCollection';
import { CppSettings } from './settings';
import { PersistentWorkspaceState } from './persistentState';
import { getLanguageConfig } from './languageConfig';
import * as os from 'os';
let prevCrashFile: string;
let clients: ClientCollection;
let activeDocument: string;
let ui: UI;
let disposables: vscode.Disposable[] = [];
let languageConfigurations: vscode.Disposable[] = [];
let intervalTimer: NodeJS.Timer;
let realActivationOccurred: boolean = false;
let tempCommands: vscode.Disposable[] = [];
let activatedPreviously: PersistentWorkspaceState<boolean>;
/**
* activate: set up the extension for language services
*/
export function activate(activationEventOccurred: boolean): void {
console.log("activating extension");
// Activate immediately if an activation event occurred in the previous workspace session.
// If onActivationEvent doesn't occur, it won't auto-activate next time.
activatedPreviously = new PersistentWorkspaceState("activatedPreviously", false);
if (activatedPreviously.Value) {
activatedPreviously.Value = false;
realActivation();
}
registerCommands();
tempCommands.push(vscode.workspace.onDidOpenTextDocument(d => onDidOpenTextDocument(d)));
// Check if an activation event has already occurred.
if (activationEventOccurred) {
return onActivationEvent();
}
if (vscode.workspace.textDocuments !== undefined && vscode.workspace.textDocuments.length > 0) {
for (let i: number = 0; i < vscode.workspace.textDocuments.length; ++i) {
let document: vscode.TextDocument = vscode.workspace.textDocuments[i];
if (document.languageId === "cpp" || document.languageId === "c") {
return onActivationEvent();
}
}
}
}
function onDidOpenTextDocument(document: vscode.TextDocument): void {
if (document.languageId === "c" || document.languageId === "cpp") {
onActivationEvent();
}
}
function onActivationEvent(): void {
if (tempCommands.length === 0) {
return;
}
// Cancel all the temp commands that just look for activations.
tempCommands.forEach((command) => {
command.dispose();
});
tempCommands = [];
if (!realActivationOccurred) {
realActivation();
}
activatedPreviously.Value = true;
}
function realActivation(): void {
realActivationOccurred = true;
console.log("starting language server");
clients = new ClientCollection();
ui = getUI();
// Check for files left open from the previous session. We won't get events for these until they gain focus,
// so we manually activate the visible file.
if (vscode.workspace.textDocuments !== undefined && vscode.workspace.textDocuments.length > 0) {
onDidChangeActiveTextEditor(vscode.window.activeTextEditor);
}
disposables.push(vscode.workspace.onDidChangeConfiguration(onDidChangeSettings));
disposables.push(vscode.workspace.onDidSaveTextDocument(onDidSaveTextDocument));
disposables.push(vscode.window.onDidChangeActiveTextEditor(onDidChangeActiveTextEditor));
disposables.push(vscode.window.onDidChangeTextEditorSelection(onDidChangeTextEditorSelection));
disposables.push(vscode.window.onDidChangeVisibleTextEditors(onDidChangeVisibleTextEditors));
updateLanguageConfigurations();
reportMacCrashes();
intervalTimer = setInterval(onInterval, 2500);
}
export function updateLanguageConfigurations(): void {
languageConfigurations.forEach(d => d.dispose());
languageConfigurations = [];
languageConfigurations.push(vscode.languages.setLanguageConfiguration('c', getLanguageConfig('c', clients.ActiveClient.RootUri)));
languageConfigurations.push(vscode.languages.setLanguageConfiguration('cpp', getLanguageConfig('cpp', clients.ActiveClient.RootUri)));
}
/*********************************************
* workspace events
*********************************************/
function onDidChangeSettings(): void {
clients.forEach(client => client.onDidChangeSettings());
}
let saveMessageShown: boolean = false;
function onDidSaveTextDocument(doc: vscode.TextDocument): void {
if (!vscode.window.activeTextEditor || doc !== vscode.window.activeTextEditor.document || (doc.languageId !== "cpp" && doc.languageId !== "c")) {
return;
}
if (!saveMessageShown && new CppSettings(doc.uri).clangFormatOnSave) {
saveMessageShown = true;
vscode.window.showInformationMessage("\"C_Cpp.clang_format_formatOnSave\" has been removed. Please use \"editor.formatOnSave\" instead.");
}
}
function onDidChangeActiveTextEditor(editor: vscode.TextEditor): void {
/* need to notify the affected client(s) */
console.assert(clients !== undefined, "client should be available before active editor is changed");
if (clients === undefined) {
return;
}
let activeEditor: vscode.TextEditor = vscode.window.activeTextEditor;
if (!activeEditor || (activeEditor.document.languageId !== "cpp" && activeEditor.document.languageId !== "c")) {
activeDocument = "";
} else {
activeDocument = editor.document.uri.toString();
clients.activeDocumentChanged(editor.document);
clients.ActiveClient.selectionChanged(editor.selection.start);
}
ui.activeDocumentChanged();
}
function onDidChangeTextEditorSelection(event: vscode.TextEditorSelectionChangeEvent): void {
/* need to notify the affected client(s) */
if (!event.textEditor || !vscode.window.activeTextEditor || event.textEditor.document.uri !== vscode.window.activeTextEditor.document.uri ||
(event.textEditor.document.languageId !== "cpp" && event.textEditor.document.languageId !== "c")) {
return;
}
if (activeDocument !== event.textEditor.document.uri.toString()) {
// For some strange (buggy?) reason we don't reliably get onDidChangeActiveTextEditor callbacks.
activeDocument = event.textEditor.document.uri.toString();
clients.activeDocumentChanged(event.textEditor.document);
ui.activeDocumentChanged();
}
clients.ActiveClient.selectionChanged(event.selections[0].start);
}
function onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {
clients.forEach(client => client.onDidChangeVisibleTextEditors(editors));
}
function onInterval(): void {
// TODO: do we need to pump messages to all clients? depends on what we do with the icons, I suppose.
clients.ActiveClient.onInterval();
}
/*********************************************
* registered commands
*********************************************/
function registerCommands(): void {
disposables.push(vscode.commands.registerCommand('C_Cpp.Navigate', onNavigate));
disposables.push(vscode.commands.registerCommand('C_Cpp.GoToDeclaration', onGoToDeclaration));
disposables.push(vscode.commands.registerCommand('C_Cpp.PeekDeclaration', onPeekDeclaration));
disposables.push(vscode.commands.registerCommand('C_Cpp.SwitchHeaderSource', onSwitchHeaderSource));
disposables.push(vscode.commands.registerCommand('C_Cpp.ResetDatabase', onResetDatabase));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationSelect', onSelectConfiguration));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEdit', onEditConfiguration));
disposables.push(vscode.commands.registerCommand('C_Cpp.AddToIncludePath', onAddToIncludePath));
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleErrorSquiggles', onToggleSquiggles));
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleIncludeFallback', onToggleIncludeFallback));
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleDimInactiveRegions', onToggleDimInactiveRegions));
disposables.push(vscode.commands.registerCommand('C_Cpp.ShowReleaseNotes', onShowReleaseNotes));
disposables.push(vscode.commands.registerCommand('C_Cpp.PauseParsing', onPauseParsing));
disposables.push(vscode.commands.registerCommand('C_Cpp.ResumeParsing', onResumeParsing));
disposables.push(vscode.commands.registerCommand('C_Cpp.ShowParsingCommands', onShowParsingCommands));
disposables.push(vscode.commands.registerCommand('C_Cpp.TakeSurvey', onTakeSurvey));
}
function onNavigate(): void {
onActivationEvent();
let activeEditor: vscode.TextEditor = vscode.window.activeTextEditor;
if (!activeEditor) {
return;
}
clients.ActiveClient.requestNavigationList(activeEditor.document).then((navigationList: string) => {
ui.showNavigationOptions(navigationList);
});
}
function onGoToDeclaration(): void {
onActivationEvent();
clients.ActiveClient.requestGoToDeclaration().then(() => vscode.commands.executeCommand("editor.action.goToDeclaration"));
}
function onPeekDeclaration(): void {
onActivationEvent();
clients.ActiveClient.requestGoToDeclaration().then(() => vscode.commands.executeCommand("editor.action.previewDeclaration"));
}
function onSwitchHeaderSource(): void {
onActivationEvent();
let activeEditor: vscode.TextEditor = vscode.window.activeTextEditor;
if (!activeEditor || !activeEditor.document) {
return;
}
if (activeEditor.document.languageId !== "cpp" && activeEditor.document.languageId !== "c") {
return;
}
let rootPath: string = clients.ActiveClient.RootPath;
let fileName: string = activeEditor.document.fileName;
if (!rootPath) {
rootPath = path.dirname(fileName); // When switching without a folder open.
}
clients.ActiveClient.requestSwitchHeaderSource(rootPath, fileName).then((targetFileName: string) => {
vscode.workspace.openTextDocument(targetFileName).then((document: vscode.TextDocument) => {
let foundEditor: boolean = false;
// If the document is already visible in another column, open it there.
vscode.window.visibleTextEditors.forEach((editor, index, array) => {
if (editor.document === document && !foundEditor) {
foundEditor = true;
vscode.window.showTextDocument(document, editor.viewColumn);
}
});
// TODO: Handle non-visibleTextEditor...not sure how yet.
if (!foundEditor) {
if (vscode.window.activeTextEditor !== undefined) {
// TODO: Change to show it in a different column?
vscode.window.showTextDocument(document, vscode.window.activeTextEditor.viewColumn);
} else {
vscode.window.showTextDocument(document);
}
}
});
});
}
/**
* Allow the user to select a workspace when multiple workspaces exist and get the corresponding Client back.
* The resulting client is used to handle some command that was previously invoked.
*/
function selectClient(): Thenable<Client> {
if (clients.Count === 1) {
return Promise.resolve(clients.ActiveClient);
} else {
return ui.showWorkspaces(clients.Names).then(key => {
if (key !== "") {
let client: Client = clients.get(key);
if (client) {
return client;
} else {
console.assert("client not found");
}
}
return Promise.reject<Client>("client not found");
});
}
}
function onResetDatabase(): void {
onActivationEvent();
/* need to notify the affected client(s) */
selectClient().then(client => client.resetDatabase(), rejected => {});
}
function onSelectConfiguration(): void {
onActivationEvent();
if (!isFolderOpen()) {
vscode.window.showInformationMessage('Open a folder first to select a configuration');
} else {
// This only applies to the active client. You cannot change the configuration for
// a client that is not active since that client's UI will not be visible.
clients.ActiveClient.handleConfigurationSelectCommand();
}
}
function onEditConfiguration(): void {
onActivationEvent();
if (!isFolderOpen()) {
vscode.window.showInformationMessage('Open a folder first to edit configurations');
} else {
selectClient().then(client => client.handleConfigurationEditCommand(), rejected => {});
}
}
function onAddToIncludePath(path: string): void {
if (!isFolderOpen()) {
vscode.window.showInformationMessage('Open a folder first to add to includePath');
} else {
// This only applies to the active client. It would not make sense to add the include path
// suggestion to a different workspace.
clients.ActiveClient.handleAddToIncludePathCommand(path);
}
}
function onToggleSquiggles(): void {
onActivationEvent();
// This only applies to the active client.
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
settings.toggleSetting("errorSquiggles", "Enabled", "Disabled");
}
function onToggleIncludeFallback(): void {
onActivationEvent();
// This only applies to the active client.
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
settings.toggleSetting("intelliSenseEngineFallback", "Enabled", "Disabled");
}
function onToggleDimInactiveRegions(): void {
onActivationEvent();
// This only applies to the active client.
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
settings.update<boolean>("dimInactiveRegions", !settings.dimInactiveRegions);
}
function onShowReleaseNotes(): void {
onActivationEvent();
util.showReleaseNotes();
}
function onPauseParsing(): void {
onActivationEvent();
selectClient().then(client => client.pauseParsing(), rejected => {});
}
function onResumeParsing(): void {
onActivationEvent();
selectClient().then(client => client.resumeParsing(), rejected => {});
}
function onShowParsingCommands(): void {
onActivationEvent();
selectClient().then(client => client.handleShowParsingCommands(), rejected => {});
}
function onTakeSurvey(): void {
onActivationEvent();
telemetry.logLanguageServerEvent("onTakeSurvey");
let uri: vscode.Uri = vscode.Uri.parse(`https://www.research.net/r/VBVV6C6?o=${os.platform()}&m=${vscode.env.machineId}`);
vscode.commands.executeCommand('vscode.open', uri);
}
function reportMacCrashes(): void {
if (process.platform === "darwin") {
prevCrashFile = "";
let crashFolder: string = path.resolve(process.env.HOME, "Library/Logs/DiagnosticReports");
fs.stat(crashFolder, (err, stats) => {
let crashObject: { [key: string]: string } = {};
if (err) {
// If the directory isn't there, we have a problem...
crashObject["fs.stat: err.code"] = err.code;
telemetry.logLanguageServerEvent("MacCrash", crashObject, null);
return;
}
// vscode.workspace.createFileSystemWatcher only works in workspace folders.
try {
fs.watch(crashFolder, (event, filename) => {
if (event !== "rename") {
return;
}
if (filename === prevCrashFile) {
return;
}
prevCrashFile = filename;
if (!filename.startsWith("Microsoft.VSCode.CPP.")) {
return;
}
// Wait 5 seconds to allow time for the crash log to finish being written.
setTimeout(() => {
fs.readFile(path.resolve(crashFolder, filename), 'utf8', (err, data) => {
if (err) {
// Try again?
fs.readFile(path.resolve(crashFolder, filename), 'utf8', handleCrashFileRead);
return;
}
handleCrashFileRead(err, data);
});
}, 5000);
});
} catch (e) {
// The file watcher limit is hit (may not be possible on Mac, but just in case).
}
});
}
}
function handleCrashFileRead(err: NodeJS.ErrnoException, data: string): void {
let crashObject: { [key: string]: string } = {};
if (err) {
crashObject["readFile: err.code"] = err.code;
telemetry.logLanguageServerEvent("MacCrash", crashObject, null);
return;
}
let startCrash: number = data.indexOf(" Crashed:");
if (startCrash < 0) {
startCrash = 0;
}
let endCrash: number = data.indexOf("Thread ", startCrash);
if (endCrash < startCrash) {
endCrash = data.length - 1;
}
data = data.substr(startCrash, endCrash - startCrash);
if (data.length > 16384) {
data = data.substr(0, 16384) + "...";
}
crashObject["CrashingThreadCallStack"] = data;
telemetry.logLanguageServerEvent("MacCrash", crashObject, null);
}
export function deactivate(): Thenable<void> {
console.log("deactivating extension");
telemetry.logLanguageServerEvent("LanguageServerShutdown");
clearInterval(intervalTimer);
disposables.forEach(d => d.dispose());
languageConfigurations.forEach(d => d.dispose());
ui.dispose();
return clients.dispose();
}
export function isFolderOpen(): boolean {
return vscode.workspace.workspaceFolders !== undefined && vscode.workspace.workspaceFolders.length > 0;
}
@@ -0,0 +1,321 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import { CppSettings } from './settings';
import { getOutputChannel } from '../logger';
export interface CommentPattern {
begin: string;
continue: string;
}
const escapeChars: RegExp = /[\\\^\$\*\+\?\{\}\(\)\.\!\=\|\[\]\ \/]/; // characters that should be escaped.
// Insert '\\' in front of regexp escape chars.
function escape(chars: string): string {
let result: string = "";
for (let char of chars) {
if (char.match(escapeChars)) {
result += `\\${char}`;
} else {
result += char;
}
}
return result;
}
// BEWARE: below are string representations of regular expressions, so the backslashes must all be escaped.
function getMLBeginPattern(insert: string): string | undefined {
if (insert && insert.startsWith("/*")) {
let match: string = escape(insert.substr(2)); // trim the leading '/*' and escape any troublesome characters.
return `^\\s*\\/\\*${match}(?!\\/)([^\\*]|\\*(?!\\/))*$`;
}
return undefined;
}
function getMLSplitAfterPattern(): string {
return "^\\s*\\*\\/$";
}
function getMLContinuePattern(insert: string): string | undefined {
if (insert) {
let match: string = escape(insert.trimRight());
if (match) {
let right: string = escape(insert.substr(insert.trimRight().length));
return `^\\s*${match}(${right}([^\\*]|\\*(?!\\/))*)?$`;
}
// else: if the continuation is just whitespace, vscode already does indentation preservation.
}
return undefined;
}
function getMLEndPattern(insert: string): string | undefined {
if (insert) {
let match: string = escape(insert.trimRight().trimLeft());
if (match) {
return `^\\s*${match}[^/]*\\*\\/\\s*$`;
}
// else: if the continuation is just whitespace, don't mess with indentation
// since we don't know if this is a continuation line or not.
}
return undefined;
}
function getMLEmptyEndPattern(insert: string): string | undefined {
if (insert) {
insert = insert.trimRight();
if (insert) {
if (insert.endsWith('*')) {
insert = insert.substr(0, insert.length - 1);
}
let match: string = escape(insert.trimRight());
return `^\\s*${match}\\*\\/\\s*$`;
}
// else: if the continuation is just whitespace, don't mess with indentation
// since we don't know if this is a continuation line or not.
}
return undefined;
}
function getSLBeginPattern(insert: string): string | undefined {
if (insert) {
let match: string = escape(insert.trimRight());
return `^\\s*${match}.*$`;
}
return undefined;
}
function getSLContinuePattern(insert: string): string | undefined {
if (insert) {
let match: string = escape(insert.trimRight());
return `^\\s*${match}.+$`;
}
return undefined;
}
function getSLEndPattern(insert: string): string | undefined {
if (insert) {
let match: string = escape(insert);
let trimmed: string = escape(insert.trimRight());
if (match !== trimmed) {
match = `(${match}|${trimmed})`;
}
return `^\\s*${match}$`;
}
return undefined;
}
// When Enter is pressed while the cursor is between '/**' and '*/' on the same line.
function getMLSplitRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let beforePattern: string | undefined = getMLBeginPattern(comment.begin);
if (beforePattern) {
return {
beforeText: new RegExp(beforePattern),
afterText: new RegExp(getMLSplitAfterPattern()),
action: {
indentAction: vscode.IndentAction.IndentOutdent,
appendText: comment.continue ? comment.continue : ''
}
};
}
}
return undefined;
}
// When Enter is pressed while the cursor is after '/**' and there is no '*/' on the same line after the cursor
function getMLFirstLineRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let beforePattern: string | undefined = getMLBeginPattern(comment.begin);
if (beforePattern) {
return {
beforeText: new RegExp(beforePattern),
action: {
indentAction: vscode.IndentAction.None,
appendText: comment.continue ? comment.continue : ''
}
};
}
}
return undefined;
}
// When Enter is pressed while the cursor is after the continuation pattern
function getMLContinuationRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let continuePattern: string = getMLContinuePattern(comment.continue);
if (continuePattern) {
return {
beforeText: new RegExp(continuePattern),
action: {
indentAction: vscode.IndentAction.None,
appendText: comment.continue.trimLeft()
}
};
}
}
return undefined;
}
// When Enter is pressed while the cursor is after '*/' (and '*/' plus leading whitespace is all that is on the line)
function getMLEndRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let endPattern: string = getMLEndPattern(comment.continue);
if (endPattern) {
return {
beforeText: new RegExp(endPattern),
action: {
indentAction: vscode.IndentAction.None,
removeText: comment.continue.length - comment.continue.trimLeft().length
}
};
}
}
return undefined;
}
// When Enter is pressed while the cursor is after the continuation pattern and '*/'
function getMLEmptyEndRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let endPattern: string = getMLEmptyEndPattern(comment.continue);
if (endPattern) {
return {
beforeText: new RegExp(endPattern),
action: {
indentAction: vscode.IndentAction.None,
removeText: comment.continue.length - comment.continue.trimLeft().length
}
};
}
}
return undefined;
}
// When the continue rule is different than the begin rule for single line comments
function getSLFirstLineRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let continuePattern: string = getSLBeginPattern(comment.begin);
if (continuePattern) {
return {
beforeText: new RegExp(continuePattern),
action: {
indentAction: vscode.IndentAction.None,
appendText: comment.continue.trimLeft()
}
};
}
}
return undefined;
}
// When Enter is pressed while the cursor is after the continuation pattern plus at least one other character.
function getSLContinuationRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let continuePattern: string = getSLContinuePattern(comment.continue);
if (continuePattern) {
return {
beforeText: new RegExp(continuePattern),
action: {
indentAction: vscode.IndentAction.None,
appendText: comment.continue.trimLeft()
}
};
}
}
return undefined;
}
// When Enter is pressed while the cursor is immediately after the continuation pattern
function getSLEndRule(comment: CommentPattern): vscode.OnEnterRule | undefined {
if (comment) {
let endPattern: string = getSLEndPattern(comment.continue);
if (endPattern) {
return {
beforeText: new RegExp(endPattern),
action: {
indentAction: vscode.IndentAction.None,
removeText: comment.continue.length - comment.continue.trimLeft().length
}
};
}
}
return undefined;
}
interface Rules {
begin: vscode.OnEnterRule[];
continue: vscode.OnEnterRule[];
end: vscode.OnEnterRule[];
}
export function getLanguageConfig(languageId: string, resource?: vscode.Uri): vscode.LanguageConfiguration {
let settings: CppSettings = new CppSettings(resource);
let patterns: (string | CommentPattern)[] = settings.commentContinuationPatterns;
return getLanguageConfigFromPatterns(languageId, patterns);
}
export function getLanguageConfigFromPatterns(languageId: string, patterns: (string | CommentPattern)[]): vscode.LanguageConfiguration {
let beginPatterns: string[] = []; // avoid duplicate rules
let continuePatterns: string[] = []; // avoid duplicate rules
let duplicates: boolean = false;
let beginRules: vscode.OnEnterRule[] = [];
let continueRules: vscode.OnEnterRule[] = [];
let endRules: vscode.OnEnterRule[] = [];
patterns.forEach(pattern => {
let c: CommentPattern = (typeof pattern === "string") ? { begin: pattern, continue: pattern.startsWith('/*') ? " * " : pattern } : <CommentPattern>pattern;
let r: Rules = constructCommentRules(c, languageId);
if (beginPatterns.indexOf(c.begin) < 0) {
if (r.begin && r.begin.length > 0) {
beginRules = beginRules.concat(r.begin);
}
beginPatterns.push(c.begin);
} else {
duplicates = true;
}
if (continuePatterns.indexOf(c.continue) < 0) {
if (r.continue && r.continue.length > 0) {
continueRules = continueRules.concat(r.continue);
}
if (r.end && r.end.length > 0) {
endRules = endRules.concat(r.end);
}
continuePatterns.push(c.continue);
}
});
if (duplicates) {
getOutputChannel().appendLine("Duplicate multiline comment patterns detected.");
}
return { onEnterRules: beginRules.concat(continueRules).concat(endRules).filter(e => (e)) }; // Remove any 'undefined' entries
}
function constructCommentRules(comment: CommentPattern, languageId: string): Rules {
if (comment && comment.begin && comment.begin.startsWith('/*') && (languageId === 'c' || languageId === 'cpp')) {
return {
begin: [
getMLSplitRule(comment),
getMLFirstLineRule(comment)
],
continue: [ getMLContinuationRule(comment) ],
end: [
getMLEmptyEndRule(comment),
getMLEndRule(comment)
]
};
} else if (comment && comment.begin && comment.begin.startsWith('//') && languageId === 'cpp') {
return {
begin: (comment.begin === comment.continue) ? [] : [ getSLFirstLineRule(comment) ],
continue: [ getSLContinuationRule(comment) ],
end: [ getSLEndRule(comment) ]
};
}
return {
begin: [],
continue: [],
end: []
};
}
@@ -0,0 +1,49 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as util from '../common';
import * as vscode from 'vscode';
import * as path from 'path';
class PersistentStateBase<T> {
private key: string;
private defaultvalue: T;
private state: vscode.Memento;
constructor(key: string, defaultValue: T, state: vscode.Memento) {
this.key = key;
this.defaultvalue = defaultValue;
this.state = state;
}
public get Value(): T {
return this.state.get<T>(this.key, this.defaultvalue);
}
public set Value(newValue: T) {
this.state.update(this.key, newValue);
}
}
// Abstraction for global state that persists across activations but is not present in a settings file
export class PersistentState<T> extends PersistentStateBase<T> {
constructor(key: string, defaultValue: T) {
super(key, defaultValue, util.extensionContext.globalState);
}
}
export class PersistentWorkspaceState<T> extends PersistentStateBase<T> {
constructor(key: string, defaultValue: T) {
super(key, defaultValue, util.extensionContext.workspaceState);
}
}
export class PersistentFolderState<T> extends PersistentWorkspaceState<T> {
constructor(key: string, defaultValue: T, folder: string) {
let newKey: string = key + (folder ? `-${path.basename(folder)}` : "-untitled");
super(newKey, defaultValue);
}
}
@@ -0,0 +1,70 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import { Middleware } from 'vscode-languageclient';
import { ClientCollection } from './clientCollection';
import { Client } from './client';
export function createProtocolFilter(me: Client, clients: ClientCollection): Middleware {
// Disabling lint for invoke handlers
/* tslint:disable */
let defaultHandler: (data: any, callback: (data: any) => void) => void = (data, callback: (data) => void) => { if (clients.ActiveClient === me) { callback(data); } };
let invoke1 = (a, callback: (a) => any) => { if (clients.ActiveClient === me) { return callback(a); } return null; };
let invoke2 = (a, b, callback: (a, b) => any) => { if (clients.ActiveClient === me) { return callback(a, b); } return null; };
let invoke3 = (a, b, c, callback: (a, b, c) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c); } return null; };
let invoke4 = (a, b, c, d, callback: (a, b, c, d) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c, d); } return null; };
let invoke5 = (a, b, c, d, e, callback: (a, b, c, d, e) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c, d, e); } return null; };
/* tslint:enable */
return {
didOpen: (document, sendMessage) => {
if (clients.checkOwnership(me, document)) {
me.TrackedDocuments.add(document);
sendMessage(document);
}
},
didChange: defaultHandler,
willSave: defaultHandler,
willSaveWaitUntil: (event, sendMessage) => {
if (clients.ActiveClient === me) {
return sendMessage(event);
}
return Promise.resolve([]);
},
didSave: defaultHandler,
didClose: (document, sendMessage) => {
if (clients.ActiveClient === me) {
console.assert(me.TrackedDocuments.has(document));
me.TrackedDocuments.delete(document);
sendMessage(document);
}
},
provideCompletionItem: invoke3,
resolveCompletionItem: invoke2,
provideHover: invoke3,
provideSignatureHelp: invoke3,
provideDefinition: invoke3,
provideReferences: invoke4,
provideDocumentHighlights: invoke3,
provideDocumentSymbols: invoke2,
provideWorkspaceSymbols: invoke2,
provideCodeActions: invoke4,
provideCodeLenses: invoke2,
resolveCodeLens: invoke2,
provideDocumentFormattingEdits: invoke3,
provideDocumentRangeFormattingEdits: invoke4,
provideOnTypeFormattingEdits: invoke5,
provideRenameEdits: invoke4,
provideDocumentLinks: invoke2,
resolveDocumentLink: invoke2,
// I believe the default handler will do the same thing.
// workspace: {
// didChangeConfiguration: (sections, sendMessage) => sendMessage(sections)
// }
};
}
+78
View File
@@ -0,0 +1,78 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import { CommentPattern } from './languageConfig';
function getTarget(): vscode.ConfigurationTarget {
return (vscode.workspace.workspaceFolders) ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Global;
}
class Settings {
private readonly settings: vscode.WorkspaceConfiguration;
/**
* create the Settings object.
* @param resource The path to a resource to which the settings should apply, or undefined if global settings are desired
*/
constructor(section: string, resource?: vscode.Uri) {
this.settings = vscode.workspace.getConfiguration(section, resource ? resource : null);
}
protected get Section(): vscode.WorkspaceConfiguration { return this.settings; }
}
export class CppSettings extends Settings {
constructor(resource?: vscode.Uri) {
super("C_Cpp", resource);
}
public get clangFormatPath(): string { return super.Section.get<string>("clang_format_path"); }
public get clangFormatStyle(): string { return super.Section.get<string>("clang_format_style"); }
public get clangFormatFallbackStyle(): string { return super.Section.get<string>("clang_format_fallbackStyle"); }
public get clangFormatSortIncludes(): string { return super.Section.get<string>("clang_format_sortIncludes"); }
public get clangFormatOnSave(): string { return super.Section.get<string>("clang_format_formatOnSave"); }
public get formatting(): string { return super.Section.get<string>("formatting"); }
public get intelliSenseEngine(): string { return super.Section.get<string>("intelliSenseEngine"); }
public get intelliSenseEngineFallback(): string { return super.Section.get<string>("intelliSenseEngineFallback"); }
public get errorSquiggles(): string { return super.Section.get<string>("errorSquiggles"); }
public get dimInactiveRegions(): boolean { return super.Section.get<boolean>("dimInactiveRegions"); }
public get autoComplete(): string { return super.Section.get<string>("autocomplete"); }
public get loggingLevel(): string { return super.Section.get<string>("loggingLevel"); }
public get navigationLength(): number { return super.Section.get<number>("navigation.length", 60); }
public get autoAddFileAssociations(): boolean { return super.Section.get<boolean>("autoAddFileAssociations"); }
public get workspaceParsingPriority(): boolean { return super.Section.get<boolean>("workspaceParsingPriority"); }
public get exclusionPolicy(): boolean { return super.Section.get<boolean>("exclusionPolicy"); }
public get commentContinuationPatterns(): (string | CommentPattern)[] { return super.Section.get<(string | CommentPattern)[]>("commentContinuationPatterns"); }
public toggleSetting(name: string, value1: string, value2: string): void {
let value: string = super.Section.get<string>(name);
super.Section.update(name, value === value1 ? value2 : value1, getTarget());
}
public update<T>(name: string, value: T): void {
super.Section.update(name, value);
}
}
export class OtherSettings {
private resource: vscode.Uri;
constructor(resource?: vscode.Uri) {
if (!resource) {
resource = null;
}
this.resource = resource;
}
public get editorTabSize(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("editor", this.resource).get("tabSize"); }
public get filesAssociations(): any { return vscode.workspace.getConfiguration("files", null).get("associations"); }
public get filesExclude(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); }
public get searchExclude(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); }
public set filesAssociations(value: any) {
vscode.workspace.getConfiguration("files", null).update("associations", value, vscode.ConfigurationTarget.Workspace);
}
}
+218
View File
@@ -0,0 +1,218 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import { Client } from './client';
let ui: UI;
interface IndexableQuickPickItem extends vscode.QuickPickItem {
index: number;
}
interface KeyedQuickPickItem extends vscode.QuickPickItem {
key: string;
}
export class UI {
private navigationStatusBarItem: vscode.StatusBarItem;
private configStatusBarItem: vscode.StatusBarItem;
private browseEngineStatusBarItem: vscode.StatusBarItem;
private intelliSenseStatusBarItem: vscode.StatusBarItem;
constructor() {
// 1000 = priority, it needs to be high enough to be on the left of the Ln/Col.
this.navigationStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 1000);
this.navigationStatusBarItem.tooltip = "C/C++ Navigation";
this.navigationStatusBarItem.command = "C_Cpp.Navigate";
this.ShowNavigation = true;
this.configStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 2);
this.configStatusBarItem.command = "C_Cpp.ConfigurationSelect";
this.configStatusBarItem.tooltip = "C/C++ Configuration";
this.ShowConfiguration = true;
this.intelliSenseStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 1);
this.intelliSenseStatusBarItem.text = "";
this.intelliSenseStatusBarItem.tooltip = "Updating IntelliSense...";
this.intelliSenseStatusBarItem.color = "Red";
this.ShowFlameIcon = true;
this.browseEngineStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 0);
this.browseEngineStatusBarItem.text = "";
this.browseEngineStatusBarItem.tooltip = "Discovering files...";
this.browseEngineStatusBarItem.color = new vscode.ThemeColor("statusBar.foreground");
this.browseEngineStatusBarItem.command = "C_Cpp.ShowParsingCommands";
this.ShowDBIcon = true;
}
private set NavigationLocation(location: string) {
this.navigationStatusBarItem.text = location;
}
private set ActiveConfig(label: string) {
this.configStatusBarItem.text = label;
}
private set TagParseStatus(label: string) {
this.browseEngineStatusBarItem.tooltip = label;
}
private get IsTagParsing(): boolean {
return this.browseEngineStatusBarItem.text !== "";
}
private set IsTagParsing(val: boolean) {
this.browseEngineStatusBarItem.text = val ? "$(database)" : "";
this.ShowDBIcon = val;
}
private get IsUpdatingIntelliSense(): boolean {
return this.intelliSenseStatusBarItem.text !== "";
}
private set IsUpdatingIntelliSense(val: boolean) {
this.intelliSenseStatusBarItem.text = val ? "$(flame)" : "";
this.ShowFlameIcon = val;
}
private set ShowNavigation(show: boolean) {
if (show) {
this.navigationStatusBarItem.show();
} else {
this.navigationStatusBarItem.hide();
}
}
private set ShowDBIcon(show: boolean) {
if (show && this.IsTagParsing) {
this.browseEngineStatusBarItem.show();
} else {
this.browseEngineStatusBarItem.hide();
}
}
private set ShowFlameIcon(show: boolean) {
if (show && this.IsUpdatingIntelliSense) {
this.intelliSenseStatusBarItem.show();
} else {
this.intelliSenseStatusBarItem.hide();
}
}
private set ShowConfiguration(show: boolean) {
if (show) {
this.configStatusBarItem.show();
} else {
this.configStatusBarItem.hide();
}
}
public activeDocumentChanged(): void {
let activeEditor: vscode.TextEditor = vscode.window.activeTextEditor;
let show: boolean = (activeEditor && (activeEditor.document.languageId === "cpp" || activeEditor.document.languageId === "c"));
this.ShowConfiguration = show;
this.ShowDBIcon = show;
this.ShowFlameIcon = show;
this.ShowNavigation = show;
}
public bind(client: Client): void {
client.TagParsingChanged(value => { this.IsTagParsing = value; });
client.IntelliSenseParsingChanged(value => { this.IsUpdatingIntelliSense = value; });
client.NavigationLocationChanged(value => { this.NavigationLocation = value; });
client.TagParserStatusChanged(value => { this.TagParseStatus = value; });
client.ActiveConfigChanged(value => { this.ActiveConfig = value; });
}
public showNavigationOptions(navigationList: string): void {
let options: vscode.QuickPickOptions = {};
options.placeHolder = "Select where to navigate to";
let items: IndexableQuickPickItem[] = [];
let navlist: string[] = navigationList.split(";");
for (let i: number = 0; i < navlist.length - 1; i += 2) {
items.push({ label: navlist[i], description: "", index: Number(navlist[i + 1]) });
}
vscode.window.showQuickPick(items, options)
.then(selection => {
if (!selection) {
return;
}
vscode.window.activeTextEditor.revealRange(new vscode.Range(selection.index, 0, selection.index, 0), vscode.TextEditorRevealType.InCenter);
vscode.window.activeTextEditor.selection = new vscode.Selection(new vscode.Position(selection.index, 0), new vscode.Position(selection.index, 0));
});
}
public showConfigurations(configurationNames: string[]): Thenable<number> {
let options: vscode.QuickPickOptions = {};
options.placeHolder = "Select a Configuration...";
let items: IndexableQuickPickItem[] = [];
for (let i: number = 0; i < configurationNames.length; i++) {
items.push({ label: configurationNames[i], description: "", index: i });
}
items.push({ label: "Edit Configurations...", description: "", index: configurationNames.length });
return vscode.window.showQuickPick(items, options)
.then(selection => {
if (!selection) {
return -1;
}
return selection.index;
});
}
public showWorkspaces(workspaceNames: { name: string; key: string }[]): Thenable<string> {
let options: vscode.QuickPickOptions = {};
options.placeHolder = "Select a Workspace...";
let items: KeyedQuickPickItem[] = [];
workspaceNames.forEach(name => items.push({ label: name.name, description: "", key: name.key }));
return vscode.window.showQuickPick(items, options)
.then(selection => {
if (!selection) {
return "";
}
return selection.key;
});
}
public showParsingCommands(): Thenable<number> {
let options: vscode.QuickPickOptions = {};
options.placeHolder = "Select a parsing command...";
let items: IndexableQuickPickItem[];
items = [];
if (this.browseEngineStatusBarItem.tooltip === "Parsing paused") {
items.push({ label: "Resume Parsing", description: "", index: 1 });
} else {
items.push({ label: "Pause Parsing", description: "", index: 0 });
}
return vscode.window.showQuickPick(items, options)
.then(selection => {
if (!selection) {
return -1;
}
return selection.index;
});
}
public dispose(): void {
this.configStatusBarItem.dispose();
this.browseEngineStatusBarItem.dispose();
this.intelliSenseStatusBarItem.dispose();
this.navigationStatusBarItem.dispose();
}
}
export function getUI(): UI {
if (ui === undefined) {
ui = new UI();
}
return ui;
}
@@ -0,0 +1,216 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
/**
* This file is used for packaging the application and should not be referenced
* by any other source files
*/
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
//Change this to true to force a dev workflow.
const EnableDevWorkflow: boolean = false;
const DebugAdapterPath: string = "./debugAdapters";
const DebugAdapterBinPath: string = DebugAdapterPath + "/bin";
let CpptoolsExtensionRoot: string = null;
let SearchCompleted: boolean = false;
interface RootsHashtable {
"miEngineRoot": string;
"openDebugRoot": string;
"monoDeps": string;
}
const internalBinaryRoots: RootsHashtable = {
"miEngineRoot": process.env.CPPTOOLS_MIENGINE_ROOT,
"openDebugRoot": process.env.CPPTOOLS_OPENDEBUG_ROOT,
"monoDeps": process.env.CPPTOLS_MONODEPS_ROOT
};
const externalBinaryRoots: RootsHashtable = {
"miEngineRoot": DebugAdapterBinPath,
"openDebugRoot": DebugAdapterBinPath,
"monoDeps": DebugAdapterPath
};
function findCppToolsExtensionDebugAdapterFolder(): string {
const vscodeFolderRegExp: RegExp = new RegExp(/\.vscode-*[a-z]*$/);
const cpptoolsFolderRegExp: RegExp = new RegExp(/ms\-vscode\.cpptools\-.*$/);
let dirPath: string = os.homedir();
if (fs.existsSync(dirPath)) {
let files: string[] = fs.readdirSync(dirPath);
for (let i: number = 0; i < files.length; i++) {
// Check to see if it starts with '.vscode'
if (vscodeFolderRegExp.test(files[i])) {
let extPath: string = path.join(dirPath, files[i], "extensions");
if (fs.existsSync(extPath)) {
let extFiles: string[] = fs.readdirSync(extPath);
for (let j: number = 0; j < extFiles.length; j++) {
if (cpptoolsFolderRegExp.test(path.join(extFiles[j]))) {
dirPath = path.join(extPath, extFiles[j]);
break;
}
}
}
}
}
if (dirPath === os.homedir()) {
console.error("Could not find installed C/C++ extension.");
return null;
}
return dirPath;
} else {
console.error("Unable to determine C/C++ extension installation location.");
return null;
}
}
function enableDevWorkflow(): Boolean {
if (process.env.AGENT_ID) {
//Agent machines must not attempt any dev workflows
return false;
}
return (EnableDevWorkflow || (process.env.CPPTOOLS_DEV !== undefined));
}
function copySourceDependencies(): void {
copy("./", DebugAdapterBinPath, "cppdbg.ad7Engine.json");
}
function getRoot(rootKey: string): string {
const internal: string = internalBinaryRoots[rootKey];
if (internal) {
return internal;
}
// Only search for the extension root once.
if (!CpptoolsExtensionRoot && !SearchCompleted) {
CpptoolsExtensionRoot = findCppToolsExtensionDebugAdapterFolder();
SearchCompleted = true;
}
if (CpptoolsExtensionRoot) {
return path.join(CpptoolsExtensionRoot, externalBinaryRoots[rootKey]);
}
console.error("Unable to determine internal/external location to copy from for root %s.", rootKey);
return null;
}
function copyBinaryDependencies(): void {
const miEngineRoot: string = getRoot("miEngineRoot");
const openDebugRoot: string = getRoot("openDebugRoot");
copy(miEngineRoot, DebugAdapterBinPath, "Microsoft.MICore.dll");
copy(miEngineRoot, DebugAdapterBinPath, "Microsoft.MICore.dll.mdb");
copy(miEngineRoot, DebugAdapterBinPath, "Microsoft.MICore.XmlSerializers.dll");
copy(miEngineRoot, DebugAdapterBinPath, "Microsoft.MIDebugEngine.dll");
copy(miEngineRoot, DebugAdapterBinPath, "Microsoft.MIDebugEngine.dll.mdb");
copy(miEngineRoot, DebugAdapterBinPath, "osxlaunchhelper.scpt");
copy(openDebugRoot, DebugAdapterBinPath, "Microsoft.VisualStudio.Debugger.Interop.10.0.dll");
copy(openDebugRoot, DebugAdapterBinPath, "Microsoft.VisualStudio.Debugger.Interop.11.0.dll");
copy(openDebugRoot, DebugAdapterBinPath, "Microsoft.VisualStudio.Debugger.Interop.12.0.dll");
copy(openDebugRoot, DebugAdapterBinPath, "Microsoft.VisualStudio.Debugger.InteropA.dll");
copy(openDebugRoot, DebugAdapterBinPath, "Microsoft.DebugEngineHost.dll");
copy(openDebugRoot, DebugAdapterBinPath, "Microsoft.DebugEngineHost.dll.mdb");
copy(openDebugRoot, DebugAdapterBinPath, "OpenDebugAD7.exe");
copy(openDebugRoot, DebugAdapterBinPath, "OpenDebugAD7.exe.config");
copy(openDebugRoot, DebugAdapterBinPath, "OpenDebugAD7.exe.mdb");
copy(openDebugRoot, DebugAdapterBinPath, "Newtonsoft.Json.dll");
}
function copyMonoDependencies(): void {
const monoDeps: string = getRoot("monoDeps");
copy(monoDeps, DebugAdapterPath, "OpenDebugAD7");
}
function copy(root: string, target: string, file: string): void {
if (!root) {
console.error("Unknown root location. Copy Failed for %s.", file);
return;
}
const source: string = path.join(root, file);
const destination: string = path.join(target, file);
if (!fs.existsSync(target)) {
console.log('Creating directory %s', target);
makeDirectory(target);
}
console.log('copying %s to %s', source, destination);
if (fs.existsSync(source)) {
fs.writeFileSync(destination, fs.readFileSync(source));
} else {
console.error('ERR: could not find file %s', source);
}
}
function removeFolder(root: string): void {
if (!isDirectory(root)) {
console.warn('Skipping deletion of %s; directory does not exist', root);
return;
}
let files: string[] = fs.readdirSync(root);
for (let i: number = 0; i < files.length; i++) {
let fullPath: string = path.join(root, files[i]);
console.warn('Found entry %s', fullPath);
if (!isDirectory(fullPath)) {
console.warn('Deleting %s', fullPath);
fs.unlinkSync(fullPath);
} else {
removeFolder(fullPath);
}
}
console.warn('Deleting %s', root);
fs.rmdirSync(root);
}
function isDirectory(dir: string): Boolean {
try {
return fs.statSync(dir).isDirectory();
} catch (e) {
}
return false;
}
function makeDirectory(dir: string): void {
try {
//Note: mkdir is limited to creating folders with one level of nesting. Creating "a/b" if 'a' doesn't exist will throw a ENOENT.
fs.mkdirSync(dir);
} catch (e) {
if ((<NodeJS.ErrnoException>e).code !== "EEXIST") {
throw e;
}
}
}
if (enableDevWorkflow()) {
removeFolder("./debugAdapters");
}
makeDirectory("./debugAdapters");
copySourceDependencies();
if (enableDevWorkflow()) {
copyMonoDependencies();
copyBinaryDependencies();
} else {
console.warn('WARNING: Debugger dependencies are missing.');
console.log('If you are trying to build and run the extension from source and need the debugger dependencies, set the environment variable CPPTOOLS_DEV=1 and try again.');
}
+34
View File
@@ -0,0 +1,34 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
/**
* This file is used during local debugging of the extension and should not be referenced by any
* other source files.
*/
const fs = require("fs");
const cp = require("child_process");
const path = require("path");
if (!process.env.CPPTOOLS_DEV && fs.existsSync('./node_modules')) {
console.warn("WARNING: Skipping npm install since it appears to have been executed already.");
} else {
console.log(">> npm install");
cp.execSync("npm install", { stdio: [0, 1, 2] });
}
// Compile the TypeScript code
console.log(">> tsc -p ./");
cp.execSync("tsc -p ./", {stdio:[0, 1, 2]});
// If the required debugger file doesn't exist, make sure it is copied.
if (process.env.CPPTOOLS_DEV || !fs.existsSync('./debugAdapters/bin/cppdbg.ad7Engine.json')) {
const copyDebuggerDependenciesJSFile = './out/src/Support/copyDebuggerDependencies.js';
// Required for nightly builds. Nightly builds do not enable CPPTOOLS_DEV.
console.log(">> node " + copyDebuggerDependenciesJSFile);
cp.execSync("node " + copyDebuggerDependenciesJSFile, { stdio: [0, 1, 2] });
}
+95
View File
@@ -0,0 +1,95 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as url from 'url';
import * as https from 'https';
import { ClientRequest } from 'http';
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as util from './common';
import * as Telemetry from './telemetry';
const userBucketMax: number = 100;
const userBucketString: string = "CPP.UserBucket";
export function activate(context: vscode.ExtensionContext): void {
if (context.globalState.get<number>(userBucketString, -1) === -1) {
let bucket: number = Math.floor(Math.random() * userBucketMax) + 1; // Range is [1, userBucketMax].
context.globalState.update(userBucketString, bucket);
}
setInterval(() => {
// Redownload occasionally to prevent an extra reload during long sessions.
downloadCpptoolsJsonPkg();
}, 30 * 60 * 1000); // 30 minutes.
}
// NOTE: Code is copied from DownloadPackage in packageManager.ts, but with ~75% fewer lines.
function downloadCpptoolsJson(urlString): Promise<void> {
return new Promise<void>((resolve, reject) => {
let parsedUrl: url.Url = url.parse(urlString);
let request: ClientRequest = https.request({
host: parsedUrl.host,
path: parsedUrl.path,
agent: util.GetHttpsProxyAgent(),
rejectUnauthorized: vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true)
}, (response) => {
if (response.statusCode === 301 || response.statusCode === 302) {
let redirectUrl: string | string[];
if (typeof response.headers.location === "string") {
redirectUrl = response.headers.location;
} else {
redirectUrl = response.headers.location[0];
}
return resolve(downloadCpptoolsJson(redirectUrl)); // Redirect - download from new location
}
if (response.statusCode !== 200) {
return reject();
}
let downloadedBytes = 0; // tslint:disable-line
let cppToolsJsonFile: fs.WriteStream = fs.createWriteStream(util.getExtensionFilePath("cpptools.json"));
response.on('data', (data) => { downloadedBytes += data.length; });
response.on('end', () => { cppToolsJsonFile.close(); });
cppToolsJsonFile.on('close', () => { resolve(); });
response.on('error', (error) => { reject(); });
response.pipe(cppToolsJsonFile, { end: false });
});
request.on('error', (error) => { reject(); });
request.end();
});
}
export function downloadCpptoolsJsonPkg(): Promise<void> {
let hasError: boolean = false;
let telemetryProperties: { [key: string]: string } = {};
return downloadCpptoolsJson("https://go.microsoft.com/fwlink/?linkid=852750")
.catch((error) => {
// More specific error info is not likely to be helpful, and we get detailed download data from the initial install.
hasError = true;
})
.then(() => {
telemetryProperties['success'] = (!hasError).toString();
Telemetry.logDebuggerEvent("cpptoolsJsonDownload", telemetryProperties);
});
}
export function processCpptoolsJson(cpptoolsString: string): Promise<void> {
let cpptoolsObject: any = JSON.parse(cpptoolsString);
let intelliSenseEnginePercentage: number = cpptoolsObject.intelliSenseEngine_default_percentage;
if (!util.packageJson.extensionFolderPath.includes(".vscode-insiders")) {
let prevIntelliSenseEngineDefault: any = util.packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default;
if (util.extensionContext.globalState.get<number>(userBucketString, userBucketMax + 1) <= intelliSenseEnginePercentage) {
util.packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default = "Default";
} else {
util.packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default = "Tag Parser";
}
if (prevIntelliSenseEngineDefault !== util.packageJson.contributes.configuration.properties["C_Cpp.intelliSenseEngine"].default) {
return util.writeFileText(util.getPackageJsonPath(), util.getPackageJsonString());
}
}
}
+73
View File
@@ -0,0 +1,73 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import * as LanguageServer from './LanguageServer/extension';
class TemporaryCommandRegistrar {
// Used to save/re-execute commands used before the extension has activated (e.g. delayed by dependency downloading).
private delayedCommandsToExecute: Set<string>;
private tempCommands: vscode.Disposable[]; // Need to save this to unregister/dispose the temporary commands.
private commandsToRegister: string[] = [
"C_Cpp.ConfigurationEdit",
"C_Cpp.ConfigurationSelect",
"C_Cpp.SwitchHeaderSource",
"C_Cpp.Navigate",
"C_Cpp.GoToDeclaration",
"C_Cpp.PeekDeclaration",
"C_Cpp.ToggleErrorSquiggles",
"C_Cpp.ToggleIncludeFallback",
"C_Cpp.ToggleDimInactiveRegions",
"C_Cpp.ShowReleaseNotes",
"C_Cpp.ResetDatabase",
"C_Cpp.PauseParsing",
"C_Cpp.ResumeParsing",
"C_Cpp.ShowParsingCommands",
"C_Cpp.TakeSurvey"
];
constructor() {
this.tempCommands = [];
this.delayedCommandsToExecute = new Set<string>();
// Add temp commands that invoke the real commands after download/install is complete (preventing an error message)
this.commandsToRegister.forEach(command => {
this.registerTempCommand(command);
});
}
public registerTempCommand(command: string): void {
this.tempCommands.push(vscode.commands.registerCommand(command, () => {
this.delayedCommandsToExecute.add(command);
}));
}
public activateLanguageServer(): void {
// Main activation code.
this.tempCommands.forEach((command) => {
command.dispose();
});
this.tempCommands = [];
LanguageServer.activate(this.delayedCommandsToExecute.size > 0);
this.delayedCommandsToExecute.forEach((command) => {
vscode.commands.executeCommand(command);
});
this.delayedCommandsToExecute.clear();
}
}
let tempCommandRegistrar: TemporaryCommandRegistrar;
export function initializeTemporaryCommandRegistrar(): void {
tempCommandRegistrar = new TemporaryCommandRegistrar();
}
export function getTemporaryCommandRegistrarInstance(): TemporaryCommandRegistrar {
return tempCommandRegistrar;
}
+433
View File
@@ -0,0 +1,433 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as path from 'path';
import * as fs from 'fs';
import * as os from 'os';
import * as child_process from 'child_process';
import * as vscode from 'vscode';
import * as Telemetry from './telemetry';
import HttpsProxyAgent = require('https-proxy-agent');
import * as url from 'url';
import { PlatformInformation } from './platform';
import { getOutputChannelLogger, showOutputChannel } from './logger';
import * as assert from 'assert';
export let extensionContext: vscode.ExtensionContext;
export function setExtensionContext(context: vscode.ExtensionContext): void {
extensionContext = context;
}
export let packageJson: any = vscode.extensions.getExtension("ms-vscode.cpptools").packageJSON;
export function getExtensionFilePath(extensionfile: string): string {
return path.resolve(extensionContext.extensionPath, extensionfile);
}
export function getPackageJsonPath(): string {
return getExtensionFilePath("package.json");
}
export function getPackageJsonString(): string {
packageJson.main = "./out/src/main"; // Needs to be reset, because the relative path is removed by VS Code.
return JSON.stringify(packageJson, null, 2);
}
// Extension is ready if install.lock exists and debugAdapters folder exist.
export async function isExtensionReady(): Promise<boolean> {
const doesInstallLockFileExist: boolean = await checkInstallLockFile();
return doesInstallLockFileExist;
}
let isExtensionNotReadyPromptDisplayed: boolean = false;
export const extensionNotReadyString: string = 'The C/C++ extension is still installing. See the output window for more information.';
export function displayExtensionNotReadyPrompt(): void {
if (!isExtensionNotReadyPromptDisplayed) {
isExtensionNotReadyPromptDisplayed = true;
showOutputChannel();
getOutputChannelLogger().showInformationMessage(extensionNotReadyString).then(
() => { isExtensionNotReadyPromptDisplayed = false; },
() => { isExtensionNotReadyPromptDisplayed = false; }
);
}
}
// This Progress global state tracks how far users are able to get before getting blocked.
// Users start with a progress of 0 and it increases as they get further along in using the tool.
// This eliminates noise/problems due to re-installs, terminated installs that don't send errors,
// errors followed by workarounds that lead to success, etc.
const progressInstallSuccess: number = 100;
const progressExecutableStarted: number = 150;
const progressExecutableSuccess: number = 200;
const progressParseRootSuccess: number = 300;
const progressIntelliSenseNoSquiggles: number = 1000;
// Might add more IntelliSense progress measurements later.
// IntelliSense progress is separate from the install progress, because parse root can occur afterwards.
let installProgressStr: string = "CPP." + packageJson.version + ".Progress";
let intelliSenseProgressStr: string = "CPP." + packageJson.version + ".IntelliSenseProgress";
export function getProgress(): number {
return extensionContext.globalState.get<number>(installProgressStr, -1);
}
export function getIntelliSenseProgress(): number {
return extensionContext.globalState.get<number>(intelliSenseProgressStr, -1);
}
export function setProgress(progress: number): void {
if (getProgress() < progress) {
extensionContext.globalState.update(installProgressStr, progress);
let telemetryProperties: { [key: string]: string } = {};
let progressName: string;
switch (progress) {
case 0: progressName = "install started"; break;
case progressInstallSuccess: progressName = "install succeeded"; break;
case progressExecutableStarted: progressName = "executable started"; break;
case progressExecutableSuccess: progressName = "executable succeeded"; break;
case progressParseRootSuccess: progressName = "parse root succeeded"; break;
}
telemetryProperties['progress'] = progressName;
Telemetry.logDebuggerEvent("progress", telemetryProperties);
}
}
export function setIntelliSenseProgress(progress: number): void {
if (getIntelliSenseProgress() < progress) {
extensionContext.globalState.update(intelliSenseProgressStr, progress);
let telemetryProperties: { [key: string]: string } = {};
let progressName: string;
switch (progress) {
case progressIntelliSenseNoSquiggles: progressName = "IntelliSense no squiggles"; break;
}
telemetryProperties['progress'] = progressName;
Telemetry.logDebuggerEvent("progress", telemetryProperties);
}
}
export function getProgressInstallSuccess(): number { return progressInstallSuccess; } // Download/install was successful (i.e. not blocked by component acquisition).
export function getProgressExecutableStarted(): number { return progressExecutableStarted; } // The extension was activated and starting the executable was attempted.
export function getProgressExecutableSuccess(): number { return progressExecutableSuccess; } // Starting the exe was successful (i.e. not blocked by 32-bit or glibc < 2.18 on Linux)
export function getProgressParseRootSuccess(): number { return progressParseRootSuccess; } // Parse root was successful (i.e. not blocked by processing taking too long).
export function getProgressIntelliSenseNoSquiggles(): number { return progressIntelliSenseNoSquiggles; } // IntelliSense was successful and the user got no squiggles.
export function showReleaseNotes(): void {
vscode.commands.executeCommand('vscode.previewHtml', vscode.Uri.file(getExtensionFilePath("ReleaseNotes.html")), vscode.ViewColumn.One, "C/C++ Extension Release Notes");
}
export function resolveVariables(input: string): string {
if (!input) {
return "";
}
// Replace environment and configuration variables.
let regexp: RegExp = /\$\{((env|config)(.|:))?(.*?)\}/g;
let ret: string = input.replace(regexp, (match: string, ignored1: string, varType: string, ignored2: string, name: string) => {
// Historically, if the variable didn't have anything before the "." or ":"
// it was assumed to be an environment variable
if (varType === undefined) {
varType = "env";
}
let newValue: string = undefined;
switch (varType) {
case "env": { newValue = process.env[name]; break; }
case "config": {
let config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration();
let keys: string[] = name.split('.');
keys.forEach((key: string) => { config = (config) ? config.get(key) : config; });
newValue = (config) ? config.toString() : undefined;
break;
}
default: { assert.fail("unknown varType matched"); }
}
return (newValue) ? newValue : match;
});
// Resolve '~' at the start of the path.
regexp = /^\~/g;
ret = ret.replace(regexp, (match: string, name: string) => {
let newValue: string = process.env.HOME;
return (newValue) ? newValue : match;
});
return ret;
}
export function asFolder(uri: vscode.Uri): string {
let result: string = uri.toString();
if (result.charAt(result.length - 1) !== '/') {
result += '/';
}
return result;
}
/**
* get the default open command for the current platform
*/
export function getOpenCommand(): string {
if (os.platform() === 'win32') {
return 'explorer';
} else if (os.platform() === 'darwin') {
return '/usr/bin/open';
} else {
return '/usr/bin/xdg-open';
}
}
export function getDebugAdaptersPath(file: string): string {
return path.resolve(getExtensionFilePath("debugAdapters"), file);
}
export function GetHttpsProxyAgent(): HttpsProxyAgent {
let proxy: string = vscode.workspace.getConfiguration().get<string>('http.proxy');
if (!proxy) {
proxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy;
if (!proxy) {
return null; // No proxy
}
}
// Basic sanity checking on proxy url
let proxyUrl: any = url.parse(proxy);
if (proxyUrl.protocol !== "https:" && proxyUrl.protocol !== "http:") {
return null;
}
let strictProxy: any = vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true);
let proxyOptions: any = {
host: proxyUrl.hostname,
port: parseInt(proxyUrl.port, 10),
auth: proxyUrl.auth,
rejectUnauthorized: strictProxy
};
return new HttpsProxyAgent(proxyOptions);
}
/** Creates a file if it doesn't exist */
function touchFile(file: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
fs.writeFile(file, "", (err) => {
if (err) {
reject(err);
}
resolve();
});
});
}
export function touchInstallLockFile(): Promise<void> {
return touchFile(getInstallLockPath());
}
export function touchExtensionFolder(): Promise<void> {
return new Promise<void>((resolve, reject) => {
fs.utimes(path.resolve(extensionContext.extensionPath, ".."), new Date(Date.now()), new Date(Date.now()), (err) => {
if (err) {
reject(err);
}
resolve();
});
});
}
/** Test whether a file exists */
export function checkFileExists(filePath: string): Promise<boolean> {
return new Promise((resolve, reject) => {
fs.stat(filePath, (err, stats) => {
if (stats && stats.isFile()) {
resolve(true);
} else {
resolve(false);
}
});
});
}
/** Test whether the lock file exists.*/
export function checkInstallLockFile(): Promise<boolean> {
return checkFileExists(getInstallLockPath());
}
/** Reads the content of a text file */
export function readFileText(filePath: string, encoding: string = "utf8"): Promise<string> {
return new Promise<string>((resolve, reject) => {
fs.readFile(filePath, encoding, (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
/** Writes content to a text file */
export function writeFileText(filePath: string, content: string, encoding: string = "utf8"): Promise<void> {
return new Promise<void>((resolve, reject) => {
fs.writeFile(filePath, content, { encoding }, (err) => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
// Get the path of the lock file. This is used to indicate that the platform-specific dependencies have been downloaded.
export function getInstallLockPath(): string {
return getExtensionFilePath("install.lock");
}
export function getReadmeMessage(): string {
const readmePath: string = getExtensionFilePath("README.md");
const readmeMessage: string = `Please refer to ${readmePath} for troubleshooting information. Issues can be created at https://github.com/Microsoft/vscppsamples/issues`;
return readmeMessage;
}
/** Used for diagnostics only */
export function logToFile(message: string): void {
const logFolder: string = getExtensionFilePath("extension.log");
fs.writeFileSync(logFolder, `${message}${os.EOL}`, { flag: 'a' });
}
export function execChildProcess(process: string, workingDirectory: string, channel?: vscode.OutputChannel): Promise<string> {
return new Promise<string>((resolve, reject) => {
child_process.exec(process, { cwd: workingDirectory, maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => {
if (channel) {
let message: string = "";
let err: Boolean = false;
if (stdout && stdout.length > 0) {
message += stdout;
}
if (stderr && stderr.length > 0) {
message += stderr;
err = true;
}
if (error) {
message += error.message;
err = true;
}
if (err) {
channel.append(message);
channel.show();
}
}
if (error) {
reject(error);
return;
}
if (stderr && stderr.length > 0) {
reject(new Error(stderr));
return;
}
resolve(stdout);
});
});
}
export function spawnChildProcess(process: string, args: string[], workingDirectory: string,
dataCallback: (stdout: string) => void, errorCallback: (stderr: string) => void): Promise<void> {
return new Promise<void>(function (resolve, reject): void {
const child: child_process.ChildProcess = child_process.spawn(process, args, { cwd: workingDirectory });
child.stdout.on('data', (data) => {
dataCallback(`${data}`);
});
child.stderr.on('data', (data) => {
errorCallback(`${data}`);
});
child.on('exit', (code: number) => {
if (code !== 0) {
reject(new Error(`${process} exited with error code ${code}`));
} else {
resolve();
}
});
});
}
export function allowExecution(file: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (process.platform !== 'win32') {
checkFileExists(file).then((exists: boolean) => {
if (exists) {
fs.chmod(file, '755', (err: NodeJS.ErrnoException) => {
if (err) {
reject(err);
return;
}
resolve();
});
} else {
getOutputChannelLogger().appendLine("");
getOutputChannelLogger().appendLine(`Warning: Expected file ${file} is missing.`);
resolve();
}
});
} else {
resolve();
}
});
}
export function removePotentialPII(str: string): string {
let words: string[] = str.split(" ");
let result: string = "";
for (let word of words) {
if (word.indexOf(".") === -1 && word.indexOf("/") === -1 && word.indexOf("\\") === -1 && word.indexOf(":") === -1) {
result += word + " ";
} else {
result += "? ";
}
}
return result;
}
export function checkDistro(platformInfo: PlatformInformation): void {
if (platformInfo.platform !== 'win32' && platformInfo.platform !== 'linux' && platformInfo.platform !== 'darwin') {
// this should never happen because VSCode doesn't run on FreeBSD
// or SunOS (the other platforms supported by node)
getOutputChannelLogger().appendLine(`Warning: Debugging has not been tested for this platform. ${getReadmeMessage()}`);
}
}
export async function unlinkPromise(fileName: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
fs.unlink(fileName, err => {
if (err) {
return reject(err);
}
return resolve();
});
});
}
export async function renamePromise(oldName: string, newName: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
fs.rename(oldName, newName, err => {
if (err) {
return reject(err);
}
return resolve();
});
});
}
+32
View File
@@ -0,0 +1,32 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
export class InstallationInformation {
stage: string;
hasError: boolean;
telemetryProperties: { [key: string]: string };
constructor() {
this.hasError = false;
this.telemetryProperties = {};
}
}
let installBlob: InstallationInformation ;
export function initializeInstallationInformation(): void {
installBlob = new InstallationInformation ();
}
export function getInstallationInformationInstance(): InstallationInformation {
return installBlob;
}
export function setInstallationStage(stage: string): void {
if (!installBlob) {
initializeInstallationInformation();
}
installBlob.stage = stage;
}
+67
View File
@@ -0,0 +1,67 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as fs from 'fs';
import * as os from 'os';
export class LinuxDistribution {
constructor(public name, public version) { }
/**
* There is no standard way on Linux to find the distribution name and version.
* Recently, systemd has pushed to standardize the os-release file. This has
* seen adoption in "recent" versions of all major distributions.
* https://www.freedesktop.org/software/systemd/man/os-release.html
*/
public static GetDistroInformation(): Promise<LinuxDistribution> {
let linuxDistro: Promise<LinuxDistribution>;
// First check /etc/os-release and only fallback to /usr/lib/os-release
// as per the os-release documentation.
linuxDistro = LinuxDistribution.getDistroInformationFromFile('/etc/os-release')
.catch(() => {
return LinuxDistribution.getDistroInformationFromFile('/usr/lib/os-release');
}).catch(() => {
// couldn't get distro information
return Promise.resolve(new LinuxDistribution('unknown', 'unknown'));
});
return linuxDistro;
}
private static getDistroInformationFromFile(path: string): Promise<LinuxDistribution> {
return new Promise<LinuxDistribution>((resolve, reject) => {
fs.readFile(path, 'utf8', (error, data) => {
if (error) {
reject(error);
return;
}
resolve(LinuxDistribution.getDistroInformation(data));
});
});
}
// Only public for tests.
public static getDistroInformation(data: string): LinuxDistribution {
const idKey: string = 'ID';
const versionKey: string = 'VERSION_ID';
let distroName: string = 'unknown';
let distroVersion: string = 'unknown';
let keyValues: string[] = data.split(os.EOL);
for (let i: number = 0; i < keyValues.length; i++) {
let keyValue: string[] = keyValues[i].split('=');
if (keyValue.length === 2) {
if (keyValue[0] === idKey) {
distroName = keyValue[1];
} else if (keyValue[0] === versionKey) {
distroVersion = keyValue[1];
}
}
}
return new LinuxDistribution(distroName, distroVersion);
}
}
+76
View File
@@ -0,0 +1,76 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import * as os from 'os';
// This is used for testing purposes
let Subscriber: (message: string) => void;
export function subscribeToAllLoggers(subscriber: (message: string) => void): void {
Subscriber = subscriber;
}
export class Logger {
private writer: (message: string) => void;
constructor(writer: (message: string) => void) {
this.writer = writer;
}
public append(message: string): void {
this.writer(message);
if (Subscriber) {
Subscriber(message);
}
}
public appendLine(message: string): void {
this.writer(message + os.EOL);
if (Subscriber) {
Subscriber(message + os.EOL);
}
}
public showInformationMessage(message: string, items?: string[]): Thenable<string> {
this.appendLine(message);
return vscode.window.showInformationMessage(message, ...items);
}
public showWarningMessage(message: string, items?: string[]): Thenable<string> {
this.appendLine(message);
return vscode.window.showWarningMessage(message, ...items);
}
public showErrorMessage(message: string, items?: string[]): Thenable<string> {
this.appendLine(message);
return vscode.window.showErrorMessage(message, ...items);
}
}
let outputChannel: vscode.OutputChannel;
export function getOutputChannel(): vscode.OutputChannel {
if (outputChannel === undefined) {
outputChannel = vscode.window.createOutputChannel("C/C++");
}
return outputChannel;
}
export function showOutputChannel(): void {
getOutputChannel().show();
}
let outputChannelLogger: Logger;
export function getOutputChannelLogger(): Logger {
if (!outputChannelLogger) {
outputChannelLogger = new Logger(message => getOutputChannel().append(message));
}
return outputChannelLogger;
}
+314
View File
@@ -0,0 +1,314 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as cpptoolsJsonUtils from './abTesting';
import * as DebuggerExtension from './Debugger/extension';
import * as fs from 'fs';
import * as LanguageServer from './LanguageServer/extension';
import * as os from 'os';
import * as Telemetry from './telemetry';
import * as util from './common';
import * as vscode from 'vscode';
import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistrar } from './commands';
import { PlatformInformation } from './platform';
import { PackageManager, PackageManagerError, PackageManagerWebResponseError, IPackage } from './packageManager';
import { PersistentState } from './LanguageServer/persistentState';
import { initializeInstallationInformation, getInstallationInformationInstance, InstallationInformation, setInstallationStage } from './installationInformation';
import { Logger, getOutputChannelLogger, showOutputChannel } from './logger';
const releaseNotesVersion: number = 3;
export function activate(context: vscode.ExtensionContext): void | Promise<void> {
initializeTemporaryCommandRegistrar();
util.setExtensionContext(context);
Telemetry.activate();
util.setProgress(0);
cpptoolsJsonUtils.activate(context);
initializeInstallationInformation();
// Initialize the DebuggerExtension and register the related commands and providers.
DebuggerExtension.initialize();
return processRuntimeDependencies();
}
export function deactivate(): Thenable<void> {
DebuggerExtension.dispose();
Telemetry.deactivate();
return LanguageServer.deactivate();
}
async function processRuntimeDependencies(): Promise<void> {
const installLockExists: boolean = await util.checkInstallLockFile();
if (installLockExists) {
// Offline Scenario: Lock file exists but package.json has not had its activationEvents rewritten.
if (util.packageJson.activationEvents && util.packageJson.activationEvents.length === 1) {
try {
await offlineInstallation();
} catch (error) {
getOutputChannelLogger().showErrorMessage('The installation of the C/C++ extension failed. Please see the output window for more information.');
showOutputChannel();
}
// The extension have been installed and activated before.
} else {
await finalizeExtensionActivation();
}
// No lock file, need to download and install dependencies.
} else {
try {
await onlineInstallation();
} catch (error) {
handleError(error);
}
}
}
async function offlineInstallation(): Promise<void> {
setInstallationStage('getPlatformInfo');
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
setInstallationStage('makeBinariesExecutable');
await makeBinariesExecutable();
setInstallationStage('makeOfflineBinariesExecutable');
await makeOfflineBinariesExecutable(info);
setInstallationStage('removeUnnecessaryFile');
await removeUnnecessaryFile();
setInstallationStage('rewriteManifest');
await rewriteManifest();
setInstallationStage('postInstall');
await postInstall(info);
}
async function onlineInstallation(): Promise<void> {
setInstallationStage('getPlatformInfo');
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
await downloadAndInstallPackages(info);
setInstallationStage('makeBinariesExecutable');
await makeBinariesExecutable();
setInstallationStage('removeUnnecessaryFile');
await removeUnnecessaryFile();
setInstallationStage('rewriteManifest');
await rewriteManifest();
setInstallationStage('touchInstallLockFile');
await touchInstallLockFile();
setInstallationStage('postInstall');
await postInstall(info);
}
async function downloadAndInstallPackages(info: PlatformInformation): Promise<void> {
let outputChannelLogger: Logger = getOutputChannelLogger();
outputChannelLogger.appendLine("Updating C/C++ dependencies...");
let statusItem: vscode.StatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
let packageManager: PackageManager = new PackageManager(info, outputChannelLogger, statusItem);
outputChannelLogger.appendLine('');
setInstallationStage('downloadPackages');
await packageManager.DownloadPackages();
outputChannelLogger.appendLine('');
setInstallationStage('installPackages');
await packageManager.InstallPackages();
statusItem.dispose();
}
function makeBinariesExecutable(): Promise<void> {
return util.allowExecution(util.getDebugAdaptersPath("OpenDebugAD7"));
}
function makeOfflineBinariesExecutable(info: PlatformInformation): Promise<void> {
let promises: Thenable<void>[] = [];
let packages: IPackage[] = util.packageJson["runtimeDependencies"];
packages.forEach(p => {
if (p.binaries && p.binaries.length > 0 &&
p.platforms.findIndex(plat => plat === info.platform) !== -1 &&
(p.architectures === undefined || p.architectures.findIndex(arch => arch === info.architecture) !== - 1)) {
p.binaries.forEach(binary => promises.push(util.allowExecution(util.getExtensionFilePath(binary))));
}
});
return Promise.all(promises).then(() => { });
}
function removeUnnecessaryFile(): Promise<void> {
if (os.platform() !== 'win32') {
let sourcePath: string = util.getDebugAdaptersPath("bin/OpenDebugAD7.exe.config");
if (fs.existsSync(sourcePath)) {
fs.rename(sourcePath, util.getDebugAdaptersPath("bin/OpenDebugAD7.exe.config.unused"), (err: NodeJS.ErrnoException) => {
if (err) {
getOutputChannelLogger().appendLine(`ERROR: fs.rename failed with "${err.message}". Delete ${sourcePath} manually to enable debugging.`);
}
});
}
}
return Promise.resolve();
}
function touchInstallLockFile(): Promise<void> {
return util.touchInstallLockFile();
}
function handleError(error: any): void {
let installationInformation: InstallationInformation = getInstallationInformationInstance();
installationInformation.hasError = true;
installationInformation.telemetryProperties['stage'] = installationInformation.stage;
let errorMessage: string;
if (error instanceof PackageManagerError) {
// If this is a WebResponse error, log the IP that it resolved from the package URL
if (error instanceof PackageManagerWebResponseError) {
let webRequestPackageError: PackageManagerWebResponseError = error;
if (webRequestPackageError.socket) {
let address: any = webRequestPackageError.socket.address();
if (address) {
installationInformation.telemetryProperties['error.targetIP'] = address.address + ':' + address.port;
}
}
}
let packageError: PackageManagerError = error;
installationInformation.telemetryProperties['error.methodName'] = packageError.methodName;
installationInformation.telemetryProperties['error.message'] = packageError.message;
if (packageError.innerError) {
errorMessage = packageError.innerError.toString();
installationInformation.telemetryProperties['error.innerError'] = util.removePotentialPII(errorMessage);
} else {
errorMessage = packageError.message;
}
if (packageError.pkg) {
installationInformation.telemetryProperties['error.packageName'] = packageError.pkg.description;
installationInformation.telemetryProperties['error.packageUrl'] = packageError.pkg.url;
}
if (packageError.errorCode) {
installationInformation.telemetryProperties['error.errorCode'] = util.removePotentialPII(packageError.errorCode);
}
} else {
errorMessage = error.toString();
installationInformation.telemetryProperties['error.toString'] = util.removePotentialPII(errorMessage);
}
let outputChannelLogger: Logger = getOutputChannelLogger();
if (installationInformation.stage === 'downloadPackages') {
outputChannelLogger.appendLine("");
}
// Show the actual message and not the sanitized one
outputChannelLogger.appendLine(`Failed at stage: ${installationInformation.stage}`);
outputChannelLogger.appendLine(errorMessage);
outputChannelLogger.appendLine("");
outputChannelLogger.appendLine(`If you work in an offline environment or repeatedly see this error, try downloading a version of the extension with all the dependencies pre-included from https://github.com/Microsoft/vscode-cpptools/releases, then use the "Install from VSIX" command in VS Code to install it.`);
showOutputChannel();
}
function sendTelemetry(info: PlatformInformation): boolean {
let installBlob: InstallationInformation = getInstallationInformationInstance();
const success: boolean = !installBlob.hasError;
installBlob.telemetryProperties['success'] = success.toString();
if (info.distribution) {
installBlob.telemetryProperties['linuxDistroName'] = info.distribution.name;
installBlob.telemetryProperties['linuxDistroVersion'] = info.distribution.version;
}
if (success) {
util.setProgress(util.getProgressInstallSuccess());
let versionShown: PersistentState<number> = new PersistentState<number>("CPP.ReleaseNotesVersion", -1);
if (versionShown.Value < releaseNotesVersion) {
util.showReleaseNotes();
versionShown.Value = releaseNotesVersion;
}
}
installBlob.telemetryProperties['osArchitecture'] = info.architecture;
Telemetry.logDebuggerEvent("acquisition", installBlob.telemetryProperties);
return success;
}
async function postInstall(info: PlatformInformation): Promise<void> {
let outputChannelLogger: Logger = getOutputChannelLogger();
outputChannelLogger.appendLine("");
outputChannelLogger.appendLine("Finished installing dependencies");
outputChannelLogger.appendLine("");
const installSuccess: boolean = sendTelemetry(info);
// If there is a download failure, we shouldn't continue activating the extension in some broken state.
if (!installSuccess) {
return Promise.reject<void>("");
} else {
// Notify user's if debugging may not be supported on their OS.
util.checkDistro(info);
return finalizeExtensionActivation();
}
}
async function finalizeExtensionActivation(): Promise<void> {
const cpptoolsJsonFile: string = util.getExtensionFilePath("cpptools.json");
try {
const exists: boolean = await util.checkFileExists(cpptoolsJsonFile);
if (exists) {
const cpptoolsString: string = await util.readFileText(cpptoolsJsonFile);
await cpptoolsJsonUtils.processCpptoolsJson(cpptoolsString);
}
} catch (error) {
// Ignore any cpptoolsJsonFile errors
}
getTemporaryCommandRegistrarInstance().activateLanguageServer();
// Redownload cpptools.json after activation so it's not blocked.
// It'll be used after the extension reloads.
cpptoolsJsonUtils.downloadCpptoolsJsonPkg();
}
function rewriteManifest(): Promise<void> {
// Replace activationEvents with the events that the extension should be activated for subsequent sessions.
util.packageJson.activationEvents = [
"onLanguage:cpp",
"onLanguage:c",
"onCommand:extension.pickNativeProcess",
"onCommand:extension.pickRemoteNativeProcess",
"onCommand:C_Cpp.ConfigurationEdit",
"onCommand:C_Cpp.ConfigurationSelect",
"onCommand:C_Cpp.SwitchHeaderSource",
"onCommand:C_Cpp.Navigate",
"onCommand:C_Cpp.GoToDeclaration",
"onCommand:C_Cpp.PeekDeclaration",
"onCommand:C_Cpp.ToggleErrorSquiggles",
"onCommand:C_Cpp.ToggleIncludeFallback",
"onCommand:C_Cpp.ToggleDimInactiveRegions",
"onCommand:C_Cpp.ShowReleaseNotes",
"onCommand:C_Cpp.ResetDatabase",
"onCommand:C_Cpp.PauseParsing",
"onCommand:C_Cpp.ResumeParsing",
"onCommand:C_Cpp.ShowParsingCommands",
"onCommand:C_Cpp.TakeSurvey",
"onDebug"
];
return util.writeFileText(util.getPackageJsonPath(), util.getPackageJsonString());
}
+441
View File
@@ -0,0 +1,441 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as fs from 'fs';
import * as net from 'net';
import * as https from 'https';
import * as path from 'path';
import * as vscode from 'vscode';
import * as url from 'url';
import * as tmp from 'tmp';
import * as yauzl from 'yauzl';
import * as mkdirp from 'mkdirp';
import * as util from './common';
import { PlatformInformation } from './platform';
import * as Telemetry from './telemetry';
import { IncomingMessage, ClientRequest } from 'http';
import { Logger } from './logger';
export interface IPackage {
// Description of the package
description: string;
// URL of the package
url: string;
// Platforms for which the package should be downloaded
platforms: string[];
// Architectures for which the package is applicable
architectures: string[];
// Binaries in the package that should be executable when deployed
binaries: string[];
// Internal location to which the package was downloaded
tmpFile: tmp.SyncResult;
}
export class PackageManagerError extends Error {
constructor(
public message: string,
public methodName: string,
public pkg: IPackage = null,
public innerError: any = null,
public errorCode: string = '') {
super(message);
}
}
export class PackageManagerWebResponseError extends PackageManagerError {
constructor(
public socket: net.Socket,
public message: string,
public methodName: string,
public pkg: IPackage = null,
public innerError: any = null,
public errorCode: string = '') {
super(message, methodName, pkg, innerError, errorCode);
}
}
export class PackageManager {
private allPackages: IPackage[];
public constructor(
private platformInfo: PlatformInformation,
private outputChannel?: Logger,
private statusItem?: vscode.StatusBarItem) {
// Ensure our temp files get cleaned up in case of error
tmp.setGracefulCleanup();
}
public DownloadPackages(): Promise<void> {
return this.GetPackages()
.then((packages) => {
return this.BuildPromiseChain(packages, (pkg) => this.DownloadPackage(pkg));
});
}
public InstallPackages(): Promise<void> {
return this.GetPackages()
.then((packages) => {
return this.BuildPromiseChain(packages, (pkg) => this.InstallPackage(pkg));
});
}
/** Builds a chain of promises by calling the promiseBuilder function once per item in the list.
* Like Promise.all, but runs the promises in sequence rather than simultaneously.
*/
private BuildPromiseChain<TItem, TPromise>(items: TItem[], promiseBuilder: (TItem) => Promise<TPromise>): Promise<TPromise> {
let promiseChain: Promise<TPromise> = Promise.resolve<TPromise>(null);
for (let item of items) {
promiseChain = promiseChain.then(() => {
return promiseBuilder(item);
});
}
return promiseChain;
}
private GetPackageList(): Promise<IPackage[]> {
return new Promise<IPackage[]>((resolve, reject) => {
if (!this.allPackages) {
if (util.packageJson.runtimeDependencies) {
this.allPackages = <IPackage[]>util.packageJson.runtimeDependencies;
// Convert relative binary paths to absolute
for (let pkg of this.allPackages) {
if (pkg.binaries) {
pkg.binaries = pkg.binaries.map((value) => {
return util.getExtensionFilePath(value);
});
}
}
resolve(this.allPackages);
} else {
reject(new PackageManagerError('Package manifest does not exist', 'GetPackageList'));
}
} else {
resolve(this.allPackages);
}
});
}
private GetPackages(): Promise<IPackage[]> {
return this.GetPackageList()
.then((list) => {
return list.filter((value, index, array) => {
return (!value.architectures || value.architectures.indexOf(this.platformInfo.architecture) !== -1) &&
(!value.platforms || value.platforms.indexOf(this.platformInfo.platform) !== -1);
});
});
}
private async DownloadPackage(pkg: IPackage): Promise<void> {
this.AppendChannel(`Downloading package '${pkg.description}' `);
this.SetStatusText("$(cloud-download) Downloading packages...");
this.SetStatusTooltip(`Downloading package '${pkg.description}'...`);
const tmpResult: tmp.SyncResult = await this.CreateTempFile(pkg);
await this.DownloadPackageWithRetries(pkg, tmpResult);
}
private async CreateTempFile(pkg: IPackage): Promise<tmp.SyncResult> {
return new Promise<tmp.SyncResult>((resolve, reject) => {
tmp.file({ prefix: "package-" }, (err, path, fd, cleanupCallback) => {
if (err) {
return reject(new PackageManagerError('Error from temp.file', 'DownloadPackage', pkg, err));
}
return resolve(<tmp.SyncResult>{ name: path, fd: fd, removeCallback: cleanupCallback });
});
});
}
private async DownloadPackageWithRetries(pkg: IPackage, tmpResult: tmp.SyncResult): Promise<void> {
pkg.tmpFile = tmpResult;
let success: boolean = false;
let lastError: any = null;
let retryCount: number = 0;
const MAX_RETRIES: number = 5;
// Retry the download at most MAX_RETRIES times with 2-32 seconds delay.
do {
try {
await this.DownloadFile(pkg.url, pkg, retryCount);
success = true;
} catch (error) {
retryCount += 1;
lastError = error;
if (retryCount >= MAX_RETRIES) {
this.AppendChannel(` Failed to download ` + pkg.url);
throw error;
} else {
// This will skip the success = true.
this.AppendChannel(` Failed. Retrying...`);
continue;
}
}
} while (!success && retryCount < MAX_RETRIES);
this.AppendLineChannel(" Done!");
if (retryCount !== 0) {
// Log telemetry to see if retrying helps.
let telemetryProperties: { [key: string]: string } = {};
telemetryProperties["success"] = `OnRetry${retryCount}`;
if (lastError instanceof PackageManagerError) {
let packageError: PackageManagerError = lastError;
telemetryProperties['error.methodName'] = packageError.methodName;
telemetryProperties['error.message'] = packageError.message;
if (packageError.pkg) {
telemetryProperties['error.packageName'] = packageError.pkg.description;
telemetryProperties['error.packageUrl'] = packageError.pkg.url;
}
if (packageError.errorCode) {
telemetryProperties['error.errorCode'] = packageError.errorCode;
}
}
Telemetry.logDebuggerEvent("acquisition", telemetryProperties);
}
}
// reloadCpptoolsJson in main.ts uses ~25% of this function.
private DownloadFile(urlString: any, pkg: IPackage, delay: number): Promise<void> {
let parsedUrl: url.Url = url.parse(urlString);
let proxyStrictSSL: any = vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true);
let options: https.RequestOptions = {
host: parsedUrl.host,
path: parsedUrl.path,
agent: util.GetHttpsProxyAgent(),
rejectUnauthorized: proxyStrictSSL
};
return new Promise<void>((resolve, reject) => {
let secondsDelay: number = Math.pow(2, delay);
if (secondsDelay === 1) {
secondsDelay = 0;
}
if (secondsDelay > 4) {
this.AppendChannel(`Waiting ${secondsDelay} seconds...`);
}
setTimeout(() => {
if (!pkg.tmpFile || pkg.tmpFile.fd === 0) {
return reject(new PackageManagerError('Temporary Package file unavailable', 'DownloadFile', pkg));
}
let handleHttpResponse: (response: IncomingMessage) => void = (response: IncomingMessage) => {
if (response.statusCode === 301 || response.statusCode === 302) {
// Redirect - download from new location
let redirectUrl: string | string[];
if (typeof response.headers.location === "string") {
redirectUrl = response.headers.location;
} else {
redirectUrl = response.headers.location[0];
}
return resolve(this.DownloadFile(redirectUrl, pkg, 0));
} else if (response.statusCode !== 200) {
// Download failed - print error message
let errorMessage: string = `failed (error code '${response.statusCode}')`;
return reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response Error', 'DownloadFile', pkg, errorMessage, response.statusCode.toString()));
} else {
// Downloading - hook up events
let contentLength: any = response.headers['content-length'];
if (typeof response.headers['content-length'] === "string") {
contentLength = response.headers['content-length'];
} else {
contentLength = response.headers['content-length'][0];
}
let packageSize: number = parseInt(contentLength, 10);
let downloadedBytes: number = 0;
let downloadPercentage: number = 0;
let dots: number = 0;
let tmpFile: fs.WriteStream = fs.createWriteStream(null, { fd: pkg.tmpFile.fd });
this.AppendChannel(`(${Math.ceil(packageSize / 1024)} KB) `);
response.on('data', (data) => {
downloadedBytes += data.length;
// Update status bar item with percentage
let newPercentage: number = Math.ceil(100 * (downloadedBytes / packageSize));
if (newPercentage !== downloadPercentage) {
this.SetStatusTooltip(`Downloading package '${pkg.description}'... ${downloadPercentage}%`);
downloadPercentage = newPercentage;
}
// Update dots after package name in output console
let newDots: number = Math.ceil(downloadPercentage / 5);
if (newDots > dots) {
this.AppendChannel(".".repeat(newDots - dots));
dots = newDots;
}
});
response.on('end', () => {
return resolve();
});
response.on('error', (error) => {
return reject(new PackageManagerWebResponseError(response.socket, 'HTTP/HTTPS Response error', 'DownloadFile', pkg, error.stack, error.name));
});
// Begin piping data from the response to the package file
response.pipe(tmpFile, { end: false });
}
};
let request: ClientRequest = https.request(options, handleHttpResponse);
request.on('error', (error) => {
return reject(new PackageManagerError('HTTP/HTTPS Request error' + (urlString.includes("fwlink") ? ": fwlink" : ""), 'DownloadFile', pkg, error.stack, error.message));
});
// Execute the request
request.end();
}, secondsDelay * 1000);
});
}
private InstallPackage(pkg: IPackage): Promise<void> {
this.AppendLineChannel(`Installing package '${pkg.description}'`);
this.SetStatusText("$(desktop-download) Installing packages...");
this.SetStatusTooltip(`Installing package '${pkg.description}'`);
return new Promise<void>((resolve, reject) => {
if (!pkg.tmpFile || pkg.tmpFile.fd === 0) {
return reject(new PackageManagerError('Downloaded file unavailable', 'InstallPackage', pkg));
}
yauzl.fromFd(pkg.tmpFile.fd, { lazyEntries: true }, (err, zipfile) => {
if (err) {
return reject(new PackageManagerError('Zip file error', 'InstallPackage', pkg, err));
}
// setup zip file events
zipfile.on('end', () => {
return resolve();
});
zipfile.on('error', err => {
return reject(new PackageManagerError('Zip File Error', 'InstallPackage', pkg, err, err.code));
});
zipfile.readEntry();
zipfile.on('entry', (entry: yauzl.Entry) => {
let absoluteEntryPath: string = util.getExtensionFilePath(entry.fileName);
if (entry.fileName.endsWith("/")) {
// Directory - create it
mkdirp.mkdirp(absoluteEntryPath, { mode: 0o775 }, (err) => {
if (err) {
return reject(new PackageManagerError('Error creating directory', 'InstallPackage', pkg, err, err.code));
}
zipfile.readEntry();
});
} else {
util.checkFileExists(absoluteEntryPath).then((exists: boolean) => {
if (!exists) {
// File - extract it
zipfile.openReadStream(entry, (err, readStream: fs.ReadStream) => {
if (err) {
return reject(new PackageManagerError('Error reading zip stream', 'InstallPackage', pkg, err));
}
readStream.on('error', (err) => {
return reject(new PackageManagerError('Error in readStream', 'InstallPackage', pkg, err));
});
mkdirp.mkdirp(path.dirname(absoluteEntryPath), { mode: 0o775 }, async (err) => {
if (err) {
return reject(new PackageManagerError('Error creating directory', 'InstallPackage', pkg, err, err.code));
}
// Create as a .tmp file to avoid partially unzipped files
// counting as completed files.
let absoluteEntryTempFile: string = absoluteEntryPath + ".tmp";
if (fs.existsSync(absoluteEntryTempFile)) {
try {
await util.unlinkPromise(absoluteEntryTempFile);
} catch (err) {
return reject(new PackageManagerError(`Error unlinking file ${absoluteEntryTempFile}`, 'InstallPackage', pkg, err));
}
}
// Make sure executable files have correct permissions when extracted
let fileMode: number = (pkg.binaries && pkg.binaries.indexOf(absoluteEntryPath) !== -1) ? 0o755 : 0o664;
let writeStream: fs.WriteStream = fs.createWriteStream(absoluteEntryTempFile, { mode: fileMode });
writeStream.on('close', async () => {
try {
// Remove .tmp extension from the file.
await util.renamePromise(absoluteEntryTempFile, absoluteEntryPath);
} catch (err) {
return reject(new PackageManagerError(`Error renaming file ${absoluteEntryTempFile}`, 'InstallPackage', pkg, err));
}
// Wait till output is done writing before reading the next zip entry.
// Otherwise, it's possible to try to launch the .exe before it is done being created.
zipfile.readEntry();
});
writeStream.on('error', (err) => {
return reject(new PackageManagerError('Error in writeStream', 'InstallPackage', pkg, err));
});
readStream.pipe(writeStream);
});
});
} else {
// Skip the message for text files, because there is a duplicate text file unzipped.
if (path.extname(absoluteEntryPath) !== ".txt") {
this.AppendLineChannel(`Warning: File '${absoluteEntryPath}' already exists and was not updated.`);
}
zipfile.readEntry();
}
});
}
});
});
}).then(() => {
// Clean up temp file
pkg.tmpFile.removeCallback();
});
}
private AppendChannel(text: string): void {
if (this.outputChannel) {
this.outputChannel.append(text);
}
}
private AppendLineChannel(text: string): void {
if (this.outputChannel) {
this.outputChannel.appendLine(text);
}
}
private SetStatusText(text: string): void {
if (this.statusItem) {
this.statusItem.text = text;
this.statusItem.show();
}
}
private SetStatusTooltip(text: string): void {
if (this.statusItem) {
this.statusItem.tooltip = text;
this.statusItem.show();
}
}
}
+72
View File
@@ -0,0 +1,72 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as os from 'os';
import * as util from './common';
import { LinuxDistribution } from './linuxDistribution';
export class PlatformInformation {
constructor(public platform: string, public architecture: string, public distribution: LinuxDistribution) { }
public static GetPlatformInformation(): Promise<PlatformInformation> {
let platform: string = os.platform();
let architecturePromise: Promise<string>;
let distributionPromise: Promise<LinuxDistribution> = Promise.resolve<LinuxDistribution>(null);
switch (platform) {
case "win32":
architecturePromise = PlatformInformation.GetWindowsArchitecture();
break;
case "linux":
architecturePromise = PlatformInformation.GetUnixArchitecture();
distributionPromise = LinuxDistribution.GetDistroInformation();
break;
case "darwin":
architecturePromise = PlatformInformation.GetUnixArchitecture();
break;
}
return Promise.all<string | LinuxDistribution>([architecturePromise, distributionPromise])
.then(([arch, distro]: [string, LinuxDistribution]) => {
return new PlatformInformation(platform, arch, distro);
});
}
public static GetUnknownArchitecture(): string { return "Unknown"; }
private static GetWindowsArchitecture(): Promise<string> {
return util.execChildProcess('wmic os get osarchitecture', util.extensionContext.extensionPath)
.then((architecture) => {
if (architecture) {
let archArray: string[] = architecture.split(os.EOL);
if (archArray.length >= 2) {
let arch: string = archArray[1].trim();
// Note: This string can be localized. So, we'll just check to see if it contains 32 or 64.
if (arch.indexOf('64') >= 0) {
return "x86_64";
} else if (arch.indexOf('32') >= 0) {
return "x86";
}
}
}
return PlatformInformation.GetUnknownArchitecture();
}).catch((error) => {
return PlatformInformation.GetUnknownArchitecture();
});
}
private static GetUnixArchitecture(): Promise<string> {
return util.execChildProcess('uname -m', util.packageJson.extensionFolderPath)
.then((architecture) => {
if (architecture) {
return architecture.trim();
}
return null;
});
}
}
+60
View File
@@ -0,0 +1,60 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as util from './common';
interface IPackageInfo {
name: string;
version: string;
aiKey: string;
}
let telemetryReporter: TelemetryReporter;
export function activate(): void {
try {
telemetryReporter = createReporter();
} catch (e) {
// can't really do much about this
}
}
export function deactivate(): void {
if (telemetryReporter) {
telemetryReporter.dispose();
}
}
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }): void {
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
if (telemetryReporter) {
telemetryReporter.sendTelemetryEvent(eventNamePrefix + eventName, properties);
}
}
export function logLanguageServerEvent(eventName: string, properties?: { [key: string]: string }, metrics?: { [key: string]: number }): void {
const eventNamePrefix: string = "C_Cpp/LanguageServer/";
if (telemetryReporter) {
telemetryReporter.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics);
}
}
function createReporter(): TelemetryReporter {
let packageInfo: IPackageInfo = getPackageInfo();
if (packageInfo && packageInfo.aiKey) {
return new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
}
return null;
}
function getPackageInfo(): IPackageInfo {
return {
name: util.packageJson.publisher + "." + util.packageJson.name,
version: util.packageJson.version,
aiKey: util.packageJson.contributes.debuggers[0].aiKey
};
}
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as assert from 'assert';
suite(`Debug Integration Test: `, function() {
suiteSetup(async function() {
let extension = vscode.extensions.getExtension("ms-vscode.cpptools");
if (!extension.isActive) {
await extension.activate();
}
});
test("Starting (gdb) Launch from the workspace root should create an Active Debug Session", async () => {
await vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], "(gdb) Launch");
let debugSessionTerminated = new Promise(resolve => {
vscode.debug.onDidTerminateDebugSession((e) => resolve());
});
assert.equal(vscode.debug.activeDebugSession.type, "cppdbg");
await debugSessionTerminated;
});
});
+42
View File
@@ -0,0 +1,42 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as fs from "fs";
import * as path from 'path';
import { subscribeToAllLoggers } from "../../src/logger";
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
// host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.
var testRunner = require('vscode/lib/testrunner');
// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
useColors: true, // colored output from test results
timeout: 60000
});
const logFolder = path.join( __dirname, ".logs")
if (!fs.existsSync(logFolder)) {
fs.mkdirSync(logFolder);
}
const logFilePath = path.join(logFolder, "integrationTests.log");
subscribeToAllLoggers(message => fs.appendFileSync(logFilePath, message));
module.exports = testRunner;
@@ -0,0 +1,77 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as assert from 'assert';
import { getLanguageConfigFromPatterns } from '../../src/LanguageServer/languageConfig';
suite("multiline comment setting tests", function() {
suiteSetup(async function() {
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
if (!extension.isActive) {
await extension.activate();
}
});
let defaultRules: vscode.OnEnterRule[] = [
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' }
},
{
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: { indentAction: vscode.IndentAction.None, appendText: ' * ' }
},
{
beforeText: /^\s*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: { indentAction: vscode.IndentAction.None, appendText: '* ' }
},
{
beforeText: /^\s*\*\/\s*$/,
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
},
{
beforeText: /^\s*\*[^/]*\*\/\s*$/,
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
}
];
let defaultSLRules: vscode.OnEnterRule[] = [
{
beforeText: /^\s*\/\/\/.+$/,
action: { indentAction: vscode.IndentAction.None, appendText: '///' }
},
{
beforeText: /^\s*\/\/\/$/,
action: { indentAction: vscode.IndentAction.None, removeText: 0 }
}
];
test("Check the default OnEnterRules for C", () => {
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**" ]).onEnterRules;
assert.deepEqual(rules, defaultRules);
});
test("Check for removal of single line comment continuations for C", () => {
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**", "///" ]).onEnterRules;
assert.deepEqual(rules, defaultRules);
});
test("Check the default OnEnterRules for C++", () => {
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**" ]).onEnterRules;
assert.deepEqual(rules, defaultRules);
});
test("Make sure duplicate rules are removed", () => {
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**", { begin: "/**", continue: " * " }, "/**" ]).onEnterRules;
assert.deepEqual(rules, defaultRules);
});
test("Check single line rules for C++", () => {
let rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "///" ]).onEnterRules;
assert.deepEqual(rules, defaultSLRules);
});
});
@@ -0,0 +1,2 @@
program
program.exe
@@ -0,0 +1,32 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/program",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"windows": {
"miDebuggerPath": "C:\\MinGW\\bin\\gdb.exe"
},
"osx": {
"miDebuggerPath": "/usr/bin/lldb"
}
}
]
}
@@ -0,0 +1,16 @@
{
"version": "0.1.0",
"tasks": [
{
"taskName": "build",
"command": "g++",
"isShellCommand": true,
"args": ["main.cpp", "-g", "-o", "program"],
"showOutput": "always",
"isBuildCommand": true,
"windows": {
"command": "C:\\MinGW\\bin\\g++.exe"
}
}
]
}
@@ -0,0 +1,3 @@
int main(int argc, char* arv[]) {
return 0;
}
@@ -0,0 +1,15 @@
#!/usr/bin/env node
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
path = require('path');
if (process.env.CODE_TESTS_PATH
&& process.env.CODE_TESTS_PATH.startsWith('.')){
process.env.CODE_TESTS_PATH = path.join(process.cwd(), process.env.CODE_TESTS_PATH.substr(2));
}
require(path.resolve(__dirname, '../node_modules/vscode/bin/test'));
+128
View File
@@ -0,0 +1,128 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as assert from 'assert';
import * as os from 'os';
import { LinuxDistribution } from '../../src/linuxDistribution';
import { WmicProcessParser, PsProcessParser } from '../../src/Debugger/nativeAttach';
suite("LinuxDistro Tests", () => {
test("Parse valid os-release file", () => {
const dataUbuntu1404 = 'NAME="Ubuntu"' + os.EOL +
'VERSION="14.04.4 LTS, Trusty Tahr"' + os.EOL +
'ID=ubuntu' + os.EOL +
'ID_LIKE=debian' + os.EOL +
'PRETTY_NAME="Ubuntu 14.04.4 LTS"' + os.EOL +
'VERSION_ID="14.04"' + os.EOL +
'HOME_URL="http://www.ubuntu.com/"' + os.EOL +
'SUPPORT_URL="http://help.ubuntu.com/"' + os.EOL +
'BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"';
const dataUbuntu1510 = 'NAME="Ubuntu"' + os.EOL +
'VERSION="15.10 (Wily Werewolf)"' + os.EOL +
'ID=ubuntu' + os.EOL +
'ID_LIKE=debian' + os.EOL +
'PRETTY_NAME="Ubuntu 15.10"' + os.EOL +
'VERSION_ID="15.10"' + os.EOL +
'HOME_URL="http://www.ubuntu.com/"' + os.EOL +
'SUPPORT_URL="http://help.ubuntu.com/"' + os.EOL +
'BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"';
const dataCentos73 = 'NAME="CentOS Linux"' + os.EOL +
'VERSION="7 (Core)"' + os.EOL +
'ID="centos"' + os.EOL +
'ID_LIKE="rhel fedora"' + os.EOL +
'VERSION_ID="7"' + os.EOL +
'PRETTY_NAME="CentOS Linux 7 (Core)"' + os.EOL +
'ANSI_COLOR="0;31"' + os.EOL +
'CPE_NAME="cpe:/o:centos:centos:7"' + os.EOL +
'HOME_URL="https://www.centos.org/"' + os.EOL +
'BUG_REPORT_URL="https://bugs.centos.org/"' + os.EOL +
os.EOL +
'CENTOS_MANTISBT_PROJECT="CentOS-7"' + os.EOL +
'CENTOS_MANTISBT_PROJECT_VERSION="7"' + os.EOL +
'REDHAT_SUPPORT_PRODUCT="centos"' + os.EOL +
'REDHAT_SUPPORT_PRODUCT_VERSION="7"';
let ubuntu1404 = LinuxDistribution.getDistroInformation(dataUbuntu1404);
let ubuntu1510 = LinuxDistribution.getDistroInformation(dataUbuntu1510);
let centos73 = LinuxDistribution.getDistroInformation(dataCentos73);
assert.equal(ubuntu1404.name, 'ubuntu');
assert.equal(ubuntu1404.version, '"14.04"');
assert.equal(ubuntu1510.name, 'ubuntu');
assert.equal(ubuntu1510.version, '"15.10"');
assert.equal(centos73.name, '"centos"');
assert.equal(centos73.version, '"7"');
});
test("Parse invalid os-release file", () => {
const data = 'garbage"';
let unknown = LinuxDistribution.getDistroInformation(data);
assert.equal(unknown.name, 'unknown');
assert.equal(unknown.version, 'unknown');
});
});
suite("Pick Process Tests", () => {
test("Parse valid wmic output", () => {
// output from the command used in WmicAttachItemsProvider
const wmicOutput = 'CommandLine=' + os.EOL +
'Name=System Idle Process' + os.EOL +
'ProcessId=0' + os.EOL +
'' + os.EOL +
'' + os.EOL +
'CommandLine="C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\ONENOTE.EXE"' + os.EOL +
'Name=ONENOTE.EXE' + os.EOL +
'ProcessId=6540' + os.EOL +
'' + os.EOL +
'' + os.EOL +
`CommandLine=\\??\\C:\\windows\\system32\\conhost.exe 0x4` + os.EOL +
'Name=conhost.exe' + os.EOL +
'ProcessId=59148' + os.EOL;
let parsedOutput = WmicProcessParser.ParseProcessFromWmic(wmicOutput);
let process1 = parsedOutput[0];
let process2 = parsedOutput[1];
let process3 = parsedOutput[2];
assert.equal(process1.commandLine, '');
assert.equal(process1.name, 'System Idle Process');
assert.equal(process1.pid, '0');
assert.equal(process2.commandLine, '"C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\ONENOTE.EXE"');
assert.equal(process2.name, 'ONENOTE.EXE');
assert.equal(process2.pid, '6540');
assert.equal(process3.commandLine, 'C:\\windows\\system32\\conhost.exe 0x4');
assert.equal(process3.name, 'conhost.exe');
assert.equal(process3.pid, '59148');
});
test("Parse valid ps output", () => {
// output from the command used in PsAttachItemsProvider
const psOutput = ' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + os.EOL +
'15470 ScopedBookmarkAgent ScopedBookmarkAgent' + os.EOL +
'15220 mdworker mdworker -s mdworker -c MDSImporterWorker -m com.apple.mdworker.shared' + os.EOL;
let parsedOutput = PsProcessParser.ParseProcessFromPs(psOutput);
let process1 = parsedOutput[0];
let process2 = parsedOutput[1];
let process3 = parsedOutput[2];
assert.equal(process1.commandLine, 'ScopedBookmarkAgent');
assert.equal(process1.name, 'ScopedBookmarkAgent');
assert.equal(process1.pid, '15470');
assert.equal(process2.commandLine, 'mdworker -s mdworker -c MDSImporterWorker -m com.apple.mdworker.shared');
assert.equal(process2.name, 'mdworker');
assert.equal(process2.pid, '15220');
});
});
+27
View File
@@ -0,0 +1,27 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
// host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.
var testRunner = require('vscode/lib/testrunner');
// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
useColors: true // colored output from test results
});
module.exports = testRunner;
+96
View File
@@ -0,0 +1,96 @@
# /* --------------------------------------------------------------------------------------------
# * Copyright (c) Microsoft Corporation. All Rights Reserved.
# * See 'LICENSE' in the project root for license information.
# * ------------------------------------------------------------------------------------------ */
#!/usr/bin/env bash
fail() {
echo "$1" >&2
exit 1
}
usage() {
echo "Usage: $0 [-v] path-to-extension path-to-miengine path-to-opendebug"
echo " e.g. $0 ~/.vscode/extensions/ms-vscode.cpptools-0.5.0 ~/src/MIEngine ~/src/OpenDebugAD7"
echo
echo " Parameters can also be provided by environment variables:"
echo " CPPDBG_EXTENSION_PATH (current value: ${CPPDBG_EXTENSION_PATH:-(none)})"
echo " MIENGINE_SRC_PATH (current value: ${MIENGINE_SRC_PATH:-(none)})"
echo " OPENDEBUG_SRC_PATH (current value: ${OPENDEBUG_SRC_PATH:-(none)})"
exit 0
}
remove_existing_binaries() {
local BIN_PATH=$1
local RM_FLAGS="-f"
if [ "${VERBOSE}" == "1" ] ; then
RM_FLAGS="${RM_FLAGS} -v"
fi
rm ${RM_FLAGS} ${BIN_PATH}/*.dll || fail "Failed to clean up existing DLLs!"
rm ${RM_FLAGS} ${BIN_PATH}/*.exe || fail "Failed to clean up existing EXEs!"
rm ${RM_FLAGS} ${BIN_PATH}/*.mdb || fail "Failed to clean up existing MDBs!"
}
link_file() {
local SRC=$1
local DEST=$2
if [ "${VERBOSE}" == "1" ] ; then
echo "Linking '${SRC}' -> '${DEST}'"
fi
ln -s ${SRC} ${DEST} || fail "Failed to link file '${SRC}' to '${DEST}'!"
}
link_files() {
local DEST_PATH=$1
local SRC_PATH=$2
shift 2
while [ ! -z $1 ] ; do
link_file ${SRC_PATH}/$1 ${DEST_PATH}/$1
# Link symbols, if present
if [ -e ${SRC_PATH}/$1.mdb ] ; then
link_file ${SRC_PATH}/$1.mdb ${DEST_PATH}/$1.mdb
fi
shift
done
}
VERBOSE=0
if [ "$1" == "-v" ] ; then
VERBOSE=1
shift
fi
EXTENSION_PATH=${1:-${CPPDBG_EXTENSION_PATH}}
MIENGINE_PATH=${2:-${MIENGINE_SRC_PATH}}
OPENDEBUG_PATH=${3:-${OPENDEBUG_SRC_PATH}}
if [ "$1" == "--help" -o -z "${EXTENSION_PATH}" -o -z "${MIENGINE_PATH}" -o -z "${OPENDEBUG_PATH}" ] ; then
usage
fi
EXTENSION_BIN=${EXTENSION_PATH}/debugAdapters/bin
remove_existing_binaries ${EXTENSION_BIN}
# Link main binaries
link_files ${EXTENSION_BIN} ${OPENDEBUG_PATH}/out/Desktop.Debug OpenDebugAD7.exe Microsoft.DebugEngineHost.dll
link_files ${EXTENSION_BIN} ${MIENGINE_PATH}/bin/Desktop.Debug Microsoft.MICore.dll Microsoft.MIDebugEngine.dll Microsoft.MICore.XmlSerializers.dll osxlaunchhelper.scpt
# Link dependencies
link_files ${EXTENSION_BIN} ${OPENDEBUG_PATH}/out/Desktop.Debug Newtonsoft.Json.dll
link_files ${EXTENSION_BIN} ${MIENGINE_PATH}/bin/Desktop.Debug Microsoft.VisualStudio.Debugger.Interop.10.0.dll Microsoft.VisualStudio.Debugger.Interop.11.0.dll Microsoft.VisualStudio.Debugger.Interop.12.0.dll Microsoft.VisualStudio.Debugger.InteropA.dll
# Link engine JSON to real assembly location
if [ ! -e ${OPENDEBUG_PATH}/out/Desktop.Debug/cppdbg.ad7Engine.json ] ; then
link_files ${OPENDEBUG_PATH}/out/Desktop.Debug ${EXTENSION_BIN} cppdbg.ad7Engine.json
fi
echo "Done!"
+18
View File
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "out",
"lib": [
"es6"
],
"sourceMap": true,
"rootDir": ".",
"removeComments": true,
"noImplicitUseStrict": true
},
"exclude": [
"node_modules",
"server"
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"rules": {
"curly": true,
"file-header": [true, ".*"],
"indent": [true, "spaces", 4],
"new-parens": true,
"no-consecutive-blank-lines": true,
"no-construct": true,
"no-duplicate-variable": true,
"no-unused-expression-chai": true,
"no-unused-variable": true,
"no-var-keyword": true,
"one-line": [true, "check-catch", "check-finally", "check-else", "check-open-brace", "check-whitespace"],
"promise-must-complete": true,
"semicolon": true,
"triple-equals": true,
"type-literal-delimiter": true,
"typedef": [true, "variable-declaration", "call-signature"],
"whitespace": [true, "check-branch", "check-operator", "check-separator", "check-preblock", "check-type"]
},
"rulesDirectory": ["node_modules/tslint-microsoft-contrib", "node_modules/tslint-no-unused-expression-chai/rules"]
}
+1
View File
@@ -8,6 +8,7 @@
* step-by-step instructions to reproduce the issue
* A small code sample, zipped up project, or open source repo we can use to verify the bug
* Relevant settings from your settings.json, c_cpp_properties.json, and/or launch.json files
* Any log messages present in the Output window (use "C_Cpp.loggingLevel": "Information" in settings.json)
Please also take a look at our documentation, as we may already have answers for your questions:
* https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation

Some files were not shown because too many files have changed in this diff Show More