Compare commits

...
125 Commits
Author SHA1 Message Date
Sean McManus 084a8e708c Merge pull request #3630 from microsoft/0_23_1_release
0 23 1 release
2019-05-10 15:57:24 -07:00
Sean McManus 045d50bb90 Merge branch 'release' into 0_23_1_release 2019-05-10 15:17:20 -07:00
Sean McManus 68eda19665 Update version. 2019-05-10 15:14:16 -07:00
Sean McManus ae564c8428 Update changelog for 0.23.1. (#3629) 2019-05-10 15:12:41 -07:00
Sean McManus 5241ce28e0 Add telemetry for missing language service extension binary (#3611)
Add telemetry for missing language service extension binary
2019-05-10 14:55:10 -07:00
Sean McManus febb880e32 Fix launch.json creation with intelliSenseEngine Disabled. (#3612)
* Fix launch.json creation with intelliSenseEngine Disabled.
2019-05-09 15:56:30 -07:00
Sean McManus d1c344b944 Fix .vscodeignore issues. (#3623) 2019-05-09 14:49:00 -07:00
Colen Garoutte-Carson a19d1c325e Fix issue with extension context not being set before initializeTemporaryCommandRegistrar (#3622) 2019-05-09 13:48:23 -07:00
Sean McManus 82225338c4 Update ThirdPartyNotices.txt -- removed a lot of unnecessary stuff. (#3606)
* Update ThirdPartyNotices.txt -- removed a lot of unnecessary stuff.
* Minor update to changelog.
2019-05-08 12:11:55 -07:00
Sean McManus fa72ab582d Seanmcm/update dependencies (#3605)
* Update the dependencies.
2019-05-07 17:19:57 -07:00
Sean McManus 0b3e43c93f Update TPN. (#3601) 2019-05-07 12:51:21 -07:00
Sean McManus 8b332a7795 Update version and fwlinks. (#3600)
* Update version and fwlinks.
* Some package-lock.json changes.
2019-05-07 12:18:10 -07:00
Sean McManus 39ab866a10 Merge pull request #3595 from microsoft/seanmcm/0_23_0_release
Seanmcm/0 23 0 release
2019-05-06 18:47:28 -07:00
Sean McManus d4cdfe6994 Merge branch 'release' into seanmcm/0_23_0_release 2019-05-06 18:42:11 -07:00
Sean McManus 4e20f27127 Seanmcm/0 23 0 changelog (#3593)
* 0.23.0 changelog.
2019-05-06 18:31:48 -07:00
Michelle Matias 4e2f1b8ba5 update release notes for 5-2019 (#3592)
* update release notes for 5-2019
2019-05-06 18:21:54 -07:00
Sean McManus 0cffa4e27a Dev/waan/fix test run (#3581)
* Fix integration tests and fail if tests fail
2019-05-06 16:51:51 -07:00
Colen Garoutte-Carson b67e701fc9 Address issue with trailing backslashes in config path not squiggled (#3573) 2019-05-01 15:58:19 -07:00
Sean McManus 77f3747630 Fix includePath code actions and configuration actions. (#3576)
* Fix `includePath` code actions amd configuration actions.
2019-05-01 14:26:55 -07:00
Sean McManus dc8813f449 Fix undefined access if there's no includePath. (#3572)
* Fix undefined access if there's no includePath.
2019-05-01 11:38:57 -07:00
Sean McManus e0543a64c1 Seanmcm/0 23 0 insiders2 changelog2 (#3571)
* Update changelog for crash fixes.
2019-04-30 16:12:52 -07:00
Sean McManus e5b118c707 Update changelog for 0.23.0-insiders2. (#3570)
* Update changelog for 0.23.0-insiders2.
2019-04-30 14:23:34 -07:00
Colen Garoutte-Carson f465766d1e Undo tab size change (#3568) 2019-04-30 12:29:15 -07:00
Michelle Matias 7f4fc339c7 Add input validation on configuration UI (#3563)
* show errors on config UI
2019-04-29 19:10:15 -07:00
Sean McManus 788cee3ecf Fix out dir not getting created. (#3562) 2019-04-29 16:42:43 -07:00
Michelle Matias 05939c19a9 add depends on (#3561) 2019-04-29 16:14:24 -07:00
Colen Garoutte-Carson 110e683790 Work around issue with getting stale contents from openTextDocument (#3545)
* Work around issue with getting stale contents from openTextDocument

* Avoid calling openTextDocument when creating a new file, and use only writeFile.  Unsubscribe from window activation when settings UI is not visible.

* Switch to using editorTabSize for settings file
2019-04-29 15:17:01 -07:00
Andrew Wang 6a88c9917b Adding support for .env files for cppvsdbg (#3500)
* Adding support for .env files for cppvsdbg

This PR allows users to have a .env file that listed as
KEY=VALUE or KEY="VALUE WITH SPACE" to be used as environment variables
when launching a process. Anything that begins with '#' is treated as a
comment. Blank lines are ignored.

This .env file will be used if envFile passed in with the launch.json.
It will also work with the existing environment variable, however
anything listed in the .env file will overwrite anything from the
environment field in the launch.json.

* Update 'envFile' description and add documentation
2019-04-26 14:59:43 -07:00
Sean McManus 2ac33971ed Update webpack dependency, fix linter errors (#3544)
* Update webpack dependency.
* Fix lint errors.
2019-04-26 14:43:29 -07:00
Sean McManus a5905276ce Bobbrow/webpack (#3411)
* Use webpack to consolidate JavaScript files
2019-04-25 18:34:15 -07:00
Colen Garoutte-Carson d6726e5d42 Switch to using the installExtension command for offline/insider vsix installing (#3521) 2019-04-25 18:02:23 -07:00
Colen Garoutte-Carson aa6873b84e Work around vscode not treating .C files as C++ (#3536) 2019-04-25 17:53:07 -07:00
Colen Garoutte-Carson e3ddec66ee Update config squiggle parsing to squiggle bad paths delimited by semicolons (#3517) 2019-04-25 17:45:42 -07:00
Sean McManus 26d83d136e Skip first install release notes (#3534)
* Don't show release notes if the extension has never been installed before
2019-04-25 17:13:08 -07:00
Colen Garoutte-Carson 6f4439ca88 Various settings UI load/save related changes (#3529) 2019-04-25 10:09:10 -07:00
Colen Garoutte-Carson 3fbeba779c Unescape backslashes in settings for UI (#3527) 2019-04-24 13:49:43 -07:00
Colen Garoutte-Carson cfc908a1ac Update Select Configurations command to offer Edit Configs JSON option (#3519)
* Update Select Configurations command to offer Edit Configs JSON option

* Add 'Edit Configurations (UI)' option to Select Configuration menu
2019-04-24 11:19:53 -07:00
Sean McManus f3a02fde4e Change version. (#3520) 2019-04-23 18:10:57 -07:00
Sean McManus e863e88e95 Merge pull request #3516 from Microsoft/seanmcm/0_23_0_changelog2
Seanmcm/0 23 0 changelog2
2019-04-23 17:11:53 -07:00
Sean McManus bc70ea8c79 Merge branch 'master' into seanmcm/0_23_0_changelog2 2019-04-23 16:58:14 -07:00
Michelle Matias bbfea25a1d Config UI data sync fix (#3515)
* fix data sync, rewording

* add default to intellisense mode. rewording.

* fix lint

* update description

* remove extra padding
2019-04-23 16:57:50 -07:00
Sean McManus 968d6c5919 Add a reported by. 2019-04-23 14:46:32 -07:00
Sean McManus 33d23b3a5e Revert line endings. 2019-04-23 14:27:09 -07:00
Sean McManus 4bf3691f7f Move issue. 2019-04-23 14:26:27 -07:00
Sean McManus bf9d69a8ad Update changelog. 2019-04-23 14:22:35 -07:00
Bob Brown 9a78289fec encode the installation type in install telemetry (#3513) 2019-04-23 10:28:23 -07:00
Michelle Matias 7960904575 changelog for 0.23.0 insiders (#3499)
* Log new features and minor changes

* fix quotes

* Update changelog.

* Separate sections.

* Fix.

* Minor change.

* More changes.
2019-04-19 18:19:50 -07:00
Michelle Matias dd590ea1f5 Config UI - fix colors on some html elements. Change some wording. (#3498)
* fix empty compilerPath. Clarify some descriptions

* fix colors

* removed unused code
2019-04-19 18:08:55 -07:00
Sean McManus 5d1e503480 Merge pull request #3497 from Microsoft/seanmcm/showLogDiagnostics
Seanmcm/show log diagnostics
2019-04-19 15:50:49 -07:00
Sean McManus 3b15f515d1 Merge branch 'master' into seanmcm/showLogDiagnostics 2019-04-19 15:44:50 -07:00
Sean McManus d7a3384a07 Merge pull request #3495 from Microsoft/seanmcm/updateThirdPartyNotices
Update ThirdPartyNotices.txt
2019-04-19 15:44:30 -07:00
Sean McManus 4cdcd72990 Merge branch 'master' into seanmcm/showLogDiagnostics 2019-04-19 15:40:52 -07:00
Sean McManus 740705973e Merge branch 'master' into seanmcm/updateThirdPartyNotices 2019-04-19 15:34:26 -07:00
Colen Garoutte-Carson 3a78e96785 Add check for undefined compilerPath in isCompilerIntelliSenseModeCompatible (#3496) 2019-04-19 15:15:15 -07:00
Sean McManus 39b89bdb5b Undo newline change. 2019-04-19 14:33:37 -07:00
Sean McManus d4d68cb808 Show the log diagnostics. 2019-04-19 14:32:34 -07:00
Sean McManus d3e8958b29 Update ThirdPartyNotices.txt 2019-04-19 13:11:18 -07:00
Colen Garoutte-Carson 0e3fea978a Add command to log language service diagnostics (#3489)
* Add support for showing diagnostics
2019-04-18 18:12:08 -07:00
Sean McManus a39b1a5d6c Merge pull request #3486 from Microsoft/bobbrow/tasksIndentation
When generating tasks.json, use the editor's tab setting
2019-04-18 17:45:11 -07:00
Sean McManus f15994a58c Merge branch 'master' into bobbrow/tasksIndentation 2019-04-18 17:35:01 -07:00
Sean McManus 009c77d45f Merge pull request #3453 from Microsoft/seanmcm/fixJsonParse
Fix for 0.22.0 regression caused by squiggle work: https://github.com/Microsoft/vscode-cpptools/issues/3449 .
2019-04-18 17:34:41 -07:00
Sean McManus 94e213449f Merge branch 'master' into seanmcm/fixJsonParse 2019-04-18 17:14:14 -07:00
Michelle Matias 7ae6818bfb Add styling to configuration UI (#3487)
* add styling to configuration UI

* fix casing on command text. style cleanup

* edit wording for command palette tip

* change wording. Disable editing of config name

* update webview on config selection changed
2019-04-18 17:03:48 -07:00
Sean McManus 03a6c04629 Merge branch 'master' into seanmcm/fixJsonParse 2019-04-18 16:07:44 -07:00
Andrew Wang 8526bc90cb Add debugHeap toggle and turn off by default (#3488)
* Add debugHeap toggle and turn off by default

This PR adds a launch.json setting to enable debugHeap if users are
intersted in using it. By default, debug heap will be disabled.
2019-04-18 15:52:37 -07:00
Bob Brown 105760833d Merge branch 'master' into bobbrow/tasksIndentation 2019-04-18 15:04:33 -07:00
Colen Garoutte-Carson 239e4015d6 Add config squiggle for intelliSenseMode/compilerPath mismatch (#3483)
* Add squiggle for intelliSenseMode/compilerPath mismatch

* Break out function for isCompilerIntelliSenseModeCompatible.
2019-04-18 14:02:29 -07:00
Bob Brown (DEVDIV) 7e7b38acd7 When generating tasks.json, use the editor's tab setting 2019-04-18 11:22:04 -07:00
Sean McManus 260dc5d840 Merge branch 'master' into seanmcm/fixJsonParse 2019-04-17 18:01:34 -07:00
Michelle Matias 99b290513b Configuration UI (#3479)
* Add settings webview

* Add setting: useSettingsUI

* Use existing global setting (workbench.settings.editor == ui | json)

* handle changes from webview

* Add content security policy to html

* Move use of workbench settings into OtherSettings class

* sync ui and json file

* Add functions for each way to open settings (UI, JSON, based on config)

* Remove unnecesary command

* add telemetry. handle failed parse. Add UI command to toast notification.

* add newline

* fix value properties of HTML element

* fix another html value

* fix formatting

* add typedef

* fix more formatting and ===

* fix code styling. fixed some bugs.

* move configDirty flag reset

* add typedef to onWindowStateChanged

* small clean up
2019-04-17 16:31:46 -07:00
Sean McManus 76b3d9ca28 Merge pull request #3455 from Microsoft/seanmcm/fixMultiRootHover
Fix hover using the active client instead of the owning client.
2019-04-17 16:11:19 -07:00
Sean McManus 806dc8ac43 Merge branch 'master' into seanmcm/fixMultiRootHover 2019-04-17 16:04:30 -07:00
Colen Garoutte-Carson 03cf4d7aaf Default intelliSenseEngineFallback to Disabled. Add additional settings value to errorSquiggles (#3421)
* Update package.json to reflect new values

* Break ToggleErrorSquiggles out into Enable/Disable

* Update localization files
2019-04-17 16:00:28 -07:00
Sean McManus 569a7cb53d Merge pull request #3478 from Microsoft/seanmcm/fixRegExpInConfigName
Seanmcm/fix reg exp in config name
2019-04-17 14:17:03 -07:00
Sean McManus 6de2250fef Merge branch 'master' into seanmcm/fixRegExpInConfigName 2019-04-17 14:08:29 -07:00
Sean McManus ae861b3605 Change sorting. 2019-04-17 14:07:19 -07:00
Bob Brown 2aeadbd395 Update FAQs.md for ipch folder (#3424) 2019-04-16 22:03:38 -07:00
Sean McManus 0b500cefb7 Fix line endings. 2019-04-16 14:57:28 -07:00
Sean McManus 2e8cd7f406 Fix bug with special chars in config name. 2019-04-16 14:56:23 -07:00
Sean McManus 8c8c2c22e3 Undo line changes. 2019-04-16 14:35:34 -07:00
Sean McManus bdc8322da3 Go back to my original fix. 2019-04-16 14:34:39 -07:00
Sean McManus eeb2ba207c Work in progress. 2019-04-16 14:11:34 -07:00
Sean McManus f848bf392a Fix hover using the active client instead of the owning client. 2019-04-11 18:18:29 -07:00
Sean McManus f72a3ded96 Undo activation events change. 2019-04-11 16:00:05 -07:00
Sean McManus 31b993941b Another attempt to undo changes. 2019-04-11 15:59:07 -07:00
Sean McManus 59b0b3f924 Merge branch 'seanmcm/fixJsonParse' of https://github.com/Microsoft/vscode-cpptools into seanmcm/fixJsonParse 2019-04-11 15:57:57 -07:00
Sean McManus 5b90fc6bd3 Attempt to undo commits. 2019-04-11 15:57:06 -07:00
Sean McManus a4e9df0e6e Merge branch 'seanmcm/fixJsonParse' of https://github.com/Microsoft/vscode-cpptools into seanmcm/fixJsonParse 2019-04-11 15:55:17 -07:00
Sean McManus 3ef0b7597f Undo checked in files. 2019-04-11 15:54:47 -07:00
Sean McManus 74c9b0b967 Replace 3 replace with 1.
Signed-off-by: Sean McManus <[email protected]>
2019-04-11 15:52:29 -07:00
Sean McManus 3b5a8466d7 Update line endings. 2019-04-11 15:27:22 -07:00
Sean McManus fbf8ed4e35 Fix bug with json parsing. 2019-04-11 15:26:07 -07:00
Colen Garoutte-Carson c978eb0755 Reorder contents of provideCustomConfiguration, as an optimization (#3437) 2019-04-11 10:06:24 -07:00
Sean McManus 0f67f54b42 Seanmcm/small changes for insiders (#3435)
* Update changelog.
* Remove confusing quotes from clang_format_style descriptions, and use the Visual Studio style as the clang_format_style examples.
2019-04-08 21:50:46 -07:00
Sean McManus b770030ec2 Update changelog for 0.22.2-insiders. (#3409)
* Update changelog for 0.22.2-insiders.
2019-04-04 14:11:08 -07:00
Colen Garoutte-Carson 8129ce337e Add call to notifyWhenReady, to prevent crash (#3406)
Addresses an issue with a prior change, which added use of languageClient when it may not yet be available.

Use requestWhenReady(), to prevent crash.
2019-04-04 13:00:34 -07:00
Colen Garoutte-Carson 93a88c948a Ensure clearCustomConfigurations() is called when changing the configurationProvider (#3404)
* Ensure clearCustomConfigurations() is called when changing the configurationProvider
2019-04-03 17:00:14 -07:00
Sean McManus 34d8874754 Seanmcm/disable cpp squiggles (#3405)
* Add enableConfigurationSquiggles.
2019-04-03 16:42:44 -07:00
Sean McManus 0773ec8c41 Fix compile_commands prompt not being per-folder. (#3399) 2019-04-03 13:07:19 -07:00
Colen Garoutte-Carson 9f842ac0d9 Add use of queryTranslationUnitSource to determine if custom configuration can be skipped (#3393)
Add call in provideCustomConfiguration to new QueryTranslationUnitSourceRequest. Use result to decide whether it's necessary to request a custom configuration.

* Add queryTranslationUnitSource

* Update "Building the Extension.md"
2019-04-03 12:39:17 -07:00
Sean McManus e8d0ded816 Fix for null ref race condition when using custom config providers. (#3377)
* Fix for null ref race condition when using custom config providers.
2019-04-02 15:22:25 -07:00
Tara Raj f5bdac9889 Merge pull request #3314 from Microsoft/taraj/box-sample
Taraj/box sample
2019-04-02 14:36:59 -07:00
Sean McManus eb976d5ca5 Merge branch 'master' into taraj/box-sample 2019-03-28 19:11:35 -07:00
Sean McManus d5a902e144 Enable environment variables with intelliSenseCachePath. (#3368)
* Enable environment variables with intelliSenseCachePath.
2019-03-27 18:28:07 -07:00
Sean McManus b0c2d54144 Merge branch 'master' into taraj/box-sample 2019-03-27 18:02:57 -07:00
Sean McManus bcdabc9c36 Attempt to fix Azure Pipelines Cl. (#3371) 2019-03-27 17:02:53 -07:00
Sean McManus e054287c48 Update for 0.22.2. (#3359) 2019-03-27 12:40:57 -07:00
Sean McManus dcf480990b Merge branch 'master' into taraj/box-sample 2019-03-26 12:52:53 -07:00
Sean McManus 02a3152f0f Fix duplicate build task when compilerPath has args. (#3360) 2019-03-26 12:52:27 -07:00
Sean McManus 77806f657f Add squiggle for compilerPath with args and spaces missing quotes. (#3358) 2019-03-26 12:41:59 -07:00
Bob Brown 7e5f22f862 updates 2019-03-25 21:10:52 -07:00
Sean McManus 0f8e7b2d7b Merge branch 'master' into taraj/box-sample 2019-03-25 15:34:43 -07:00
Sean McManus 088276b4af Seanmcm/component governance (#3346)
* Add Component Governance.
2019-03-25 11:44:55 -07:00
Tara Raj a7cefc9d4d Merge branch 'master' into taraj/box-sample 2019-03-22 09:53:05 -07:00
Bob Brown 30d8a1daa4 Update FAQ.md 2019-03-22 09:08:58 -07:00
Bob Brown (DEVDIV) 148ae1d325 ignore cache files 2019-03-22 08:52:21 -07:00
Tara Raj 968ce8acba Adding gitignore file 2019-03-21 12:56:54 -07:00
Tara Raj ff6e13e829 Add Box Sample and Remove Stale Clang Sample 2019-03-21 11:45:05 -07:00
Sean McManus c18592b5a3 Merge pull request #3332 from Microsoft/0_22_1_release
0 22 1 release
2019-03-20 19:06:23 -07:00
Sean McManus fee924b374 Merge branch 'release' into 0_22_1_release 2019-03-20 18:46:03 -07:00
Sean McManus 6724e13c63 Update for 0.22.1. 2019-03-20 18:44:44 -07:00
Sean McManus 798e90574c Update for 0.22.1. (#3331) 2019-03-20 18:24:13 -07:00
Sean McManus 1eb064e020 Build tasks.json deletion. Configure Task. (#3328)
* Build tasks.json deletion. Configure Task.
2019-03-20 15:39:06 -07:00
Tara Raj 7088f546aa Additional box sample files 2019-03-18 19:53:33 -07:00
Tara Raj 64ca48b50e BoxConsoleSample for build and debug demo 2019-03-18 19:52:49 -07:00
63 changed files with 8702 additions and 3478 deletions
+7
View File
@@ -0,0 +1,7 @@
# ignore cache files for sample projects
.vscode/ipch
browse*.db*
*.obj
*.pdb
*.exe
*.ilk
@@ -0,0 +1,19 @@
#ifndef BOX_H
#define BOX_H
/**
* Definition of a box object with three dimensions.
*/
struct box
{
int length;
int width;
int height;
int volume()
{
return length * width * height;
}
};
#endif
+24
View File
@@ -0,0 +1,24 @@
# Box Sample
This sample is a simple C++ program that computes and outputs the volume of a box.
We use this example in our blog posts to illustrate new extension features.
## Build and Debug Active File
Available as of March 2019, "Build and Debug Active File" automatically configures the build tasks and kicks off a build and debug session. There are
three ways to get started with this feature.
### Command
While editing a file in your workspace folder, you can open the command palette and select the `C/C++: Build and Debug Active File` command.
This option will generate a tasks.json file for you, build your active source file, and then launch the debugger.
![Open command palette and select Build and Debug Active File](build_debug_command.png)
### Context Menu
While editing a file in a workspace folder, you can right click in the editor field and select the "Build and Debug Active File" context menu option.
This option will generate a tasks.json file for you, build your active source file, and then launch the debugger.
![Right click and select Build and Debug Active File](build_debug_context_menu.png)
### F5
Another way to begin building and debugging your active file is to execute the command by pressing <kbd>F5</kbd>. This method will configure
both a tasks.json and launch.json file for you, build your active source file, and then launch the debugger.
@@ -0,0 +1,16 @@
#include <iostream>
#include "Objects/box.h"
using namespace std;
/**
* Calculate and print the volume of a box.
*/
int main()
{
box package{ 10, 10, 10 };
cout << "Package length: " << package.length << endl;
cout << "Package width: " << package.width << endl;
cout << "Package height: " << package.height << endl;
cout << "Package volume: " << package.volume() << endl;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

@@ -1,2 +0,0 @@
main.exe
main.exe.dSYM
-17
View File
@@ -1,17 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/main.exe", // this is executable to launch the debugger with
"args": ["YourNameHere"],
"stopAtEntry": true, // if true then stop at the main entry (function)
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": true,
"MIMode": "lldb"
}
]
}
-19
View File
@@ -1,19 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "clang++",
"command": "clang++ --debug -o main.exe main.cpp",
// "--debug" enables debugging symbols
// "-o main.exe" specifies the output executable
// "main.cpp" is the source file to compile
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
-10
View File
@@ -1,10 +0,0 @@
# README
This is a sample debuggable C++ project. It uses the vendor provided version of clang installed. `tasks.json` and `launch.json` have been edited to demonstrate how to create a configuration for a C++ project that builds with clang.
There's a sample build task in `.vscode/tasks.json`; you can also see the build configurations by using the menu option `Configure` -> `Configure Tasks` or by clicking the gear icon in the Debug Panel.
To run a build, use the menu option `Tasks` -> `Run Build Task...`.
There's a sample debug configuration in `.vscode/launch.json`; you can also see the configuration by using the menu option `Debug` -> `Open Configurations`.
To debug the build, use the menu option `Debug` -> `Start Debugging`. The executable will launch and stop in the main function.
-17
View File
@@ -1,17 +0,0 @@
#include <iostream>
#include <string>
using namespace std;
void greet(const string& person) {
cout << "Hello, " << person << "!" << endl;
}
int main(int argc, char** argv) {
if(argc >= 2) {
greet(argv[1]);
} else {
cerr << "insufficient args, usage: " << argv[0] << " personNameHere" << endl;
}
return 0;
}
+2 -1
View File
@@ -3,7 +3,8 @@
These steps will allow you to debug the TypeScript code that is part of the Microsoft CppTools extension for Visual Studio Code.
Prerequisite steps:
* Clone [this](https://github.com/Microsoft/vscode-cpptools) repository.
* Clone the release branch of [this](https://github.com/Microsoft/vscode-cpptools) repository.
* git clone -b release https://github.com/Microsoft/vscode-cpptools
* Install [npm](https://nodejs.org).
* From a command line, run the following commands from the **Extension** folder in the root of the repository:
* `npm install` will install the dependencies needed to build the extension.
+20
View File
@@ -2,6 +2,8 @@
## Table of Contents
* Setup: [Debugging Setup](#debugging-setup)
* Setup: [What is the .vscode/ipch folder?](#what-is-the-vscodeipch-folder)
* Setup: [How do I disable the IntelliSense cache (ipch)?](#how-do-i-disable-the-intellisense-cache-ipch)
* Debugger: [Why is debugging not working?](#why-is-debugging-not-working)
* Build: [How to enable debug symbols](#how-to-enable-debug-symbols)
* Logging: [How to enable logging](#how-to-enable-logging)
@@ -15,6 +17,24 @@ The file **launch.json** will now be open for editing with a new configuration.
See the [**Documentation/Debugger**](https://github.com/Microsoft/vscode-cpptools/tree/master/Documentation/Debugger) folder in this repository for more in-depth documentation on how to configure the debugger.
## What is the .vscode/ipch folder?
The language server caches information about included header files to improve the performance of IntelliSense. When you edit C/C++ files in your workspace folder, the language server will store cache files in the `.vscode/ipch` folder by default. VS Code per-workspace storage folders were not selected for the following reasons:
* The workspace storage location provided by VS Code is somewhat obscure and we had reservations about writing GB's worth of files in this location where users may not see them or know where to find them.
* Parity with Visual Studio. This is how Visual Studio works and they receive little to no feedback/complaints on the location.
With this in mind we knew that we wouldn't be able to please everyone, so we provided settings to allow you to customize this the way that works best for your situation. We also figured that putting the files in the workspace folder would bring the issue to your attention quickly so that you can take action if you don't like the default behavior.
#### `"C_Cpp.intelliSenseCachePath": <string>`
This setting allows you to set workspace or global overrides for the cache path. For example, if you want to share a single cache location for all workspace folders, you just open the VS Code settings, and add a "User" setting for "IntelliSense Cache Path".
#### `"C_Cpp.intelliSenseCacheSize": <number>`
This setting allows you to set a limit on the amount of caching the extension does. This is an approximation, but the extension will make a best effort to keep the cache size as close to the limit you set as possible. If you are sharing the cache location across workspaces as explained above, you can still increase/decrease the limit, but you should make sure that you add a "User" setting for "IntelliSense Cache Size".
## How do I disable the IntelliSense cache (ipch)?
If you do not want to use the IntelliSense caching feature to improve the performance of IntelliSense, you can disable the feature by setting the "IntelliSense Cache Size" setting to 0. (or `"C_Cpp.intelliSenseCacheSize": 0"` in the JSON settings editor)
## Why is debugging not working?
### My breakpoints aren't being hit
+1 -1
View File
@@ -31,7 +31,7 @@ If you want IntelliSense to operate on your files even when all #include directi
The most common reason for this is missing include paths and defines. The easiest way to fix this on each platform is as follows:
**Linux/Mac**
* Set `"intelliSenseMode": "clang-x64"` and `"compilerPath"` in **c_cpp_properties.json** to the path to your compiler.
* Set `"intelliSenseMode": "clang-x64"` or `"intelliSenseMode": "gcc-x64"` and `"compilerPath"` in **c_cpp_properties.json** to the path to your compiler.
**Windows**
* If you are using a Microsoft compiler from Visual Studio, set `"intelliSenseMode": "msvc-x64"`, but don't add the `"compilerPath"` property to **c_cpp_properties.json**.
+1 -1
View File
@@ -3,6 +3,7 @@ node_modules
# ignore compliled typescript
out
dist
# ignore downloaded extension files and folders
server
@@ -18,4 +19,3 @@ install.lock
# ignore vscode test
.vscode-test/
browse*db*
+5 -4
View File
@@ -13,9 +13,9 @@
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "TypeScript Compile",
"preLaunchTask": "Compile Dev",
},
{
"name": "Launch Tests",
@@ -47,13 +47,14 @@
"args": [
"${workspaceFolder}/test/integrationTests/testAssets/SimpleCppProject",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests"
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests/languageServer"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
]
],
"preLaunchTask": "Pretest"
},
]
}
+30
View File
@@ -53,6 +53,36 @@
"dependsOn": [
"TypeScript Compile"
]
},
{
"label": "Compile Dev",
"group": "build",
"isBackground": false,
"type": "shell",
"command": "npm",
"args": [
"run",
"compileDev"
],
"dependsOn": [
"TypeScript Compile"
],
"problemMatcher": "$tsc-watch"
},
{
"label": "Pretest",
"group": "build",
"isBackground": false,
"type": "shell",
"command": "npm",
"args": [
"run",
"pretest"
],
"dependsOn": [
"TypeScript Compile"
],
"problemMatcher": "$tsc-watch"
}
]
}
+30 -9
View File
@@ -1,15 +1,36 @@
obj/**
# ignore vscode settings for extension development
.vscode/**
typings/**
out/test/**
# ignore binaries
obj/**
# ignore source files
tools/**
notices/**
test/**
src/**
**/*.map
.gitignore
# ignore .js files that are webpacked or only used for development
out/src/**
out/tools/**
# ignore ts files in ui
ui/*.ts
# ignore Azure-Pipelines files
jobs/**
# ignore development files
tsconfig.json
test.tsconfig.json
tslint.json
webpack.config.js
tscCompileList.txt
gulpfile.js
.gitattributes
.gitignore
CMakeLists.txt
debugAdapters/install.lock*
out/src/Debugger/copyScript.js
tools/**
out/tools/**
notices/**
typings/**
**/*.map
+69
View File
@@ -1,5 +1,74 @@
# C/C++ for Visual Studio Code Change Log
## Version 0.23.1: May 13, 2019
### Bug Fixes
* Fix `launch.json` creation when `intelliSenseEngine` is `"Disabled"`. [#3583](https://github.com/microsoft/vscode-cpptools/issues/3583)
* Fix C/C++ commands not working if the language service isn't activated. [#3615](https://github.com/microsoft/vscode-cpptools/issues/3615)
* Fix missing extension `"Details"` page. [#3621](https://github.com/microsoft/vscode-cpptools/issues/3621)
* Fix some random crashes related to IntelliSense inactive region processing.
## Version 0.23.0: May 6, 2019
### New Features
* Add a configuration UI editor to edit IntelliSense settings defined in the underlying `c_cpp_properties.json` file. [PR #3479](https://github.com/Microsoft/vscode-cpptools/pull/3479), [PR #3487](https://github.com/Microsoft/vscode-cpptools/pull/3487), [PR #3519](https://github.com/Microsoft/vscode-cpptools/pull/3519), [#3524](https://github.com/Microsoft/vscode-cpptools/issues/3524), [PR #3563](https://github.com/Microsoft/vscode-cpptools/pull/3563), [#3526](https://github.com/Microsoft/vscode-cpptools/issues/3526)
* Add a new command `C/C++: Edit configurations (UI)` to open the UI editor.
* Replace the `C/C++: Edit configurations...` command with `C/C++: Edit configurations (JSON)` to open `c_cpp_properties.json`.
* The default whether to open the UI editor or JSON file is based on the `workbench.settings.editor` setting.
* Add command `C/C++: Log Diagnostics` to log language service diagnostics. [PR #3489](https://github.com/Microsoft/vscode-cpptools/pull/3489)
* Add support for `.env` files for `cppvsdbg`. [#3490](https://github.com/Microsoft/vscode-cpptools/issues/3490)
### Other Changes
* Enable flag `/permissive-` as an argument to `compilerPath` with `cl.exe`. [#1589](https://github.com/Microsoft/vscode-cpptools/issues/1589), [#3446](https://github.com/Microsoft/vscode-cpptools/issues/3446)
* Configuration squiggles for `c_cpp_properties.json` now validates if the setting values of `compilerPath` and `intelliSenseMode` match on Windows. [#2983](https://github.com/Microsoft/vscode-cpptools/issues/2983)
* Enable `-fms-extensions` to be used as an argument to `compilerPath` on Linux/Mac. [#3063](https://github.com/Microsoft/vscode-cpptools/issues/3063)
* Change the default value of `C_Cpp.intelliSenseEngineFallback` setting to `Disabled`. [#3165](https://github.com/Microsoft/vscode-cpptools/issues/3165)
* Add squiggle when `compilerPath` uses spaces and arguments without `"`. [#3357](https://github.com/Microsoft/vscode-cpptools/issues/3357)
* Change the `Disabled` value for `C_Cpp.errorSquiggles` to stop showing missing header squiggles. [#3361](https://github.com/Microsoft/vscode-cpptools/issues/3361)
* Add `enableConfigurationSquiggles` setting to allow squiggles to be disabled for `c_cpp_properties.json`. [#3403](https://github.com/Microsoft/vscode-cpptools/issues/3403)
* Switch to using the `installExtension` command for offline/insider vsix installing (to reduce install failures). [#3408](https://github.com/Microsoft/vscode-cpptools/issues/3408)
* Add a better example to the description of `C_Cpp.clang_format_style` and `C_Cpp.clang_format_fallback_style`. [#3419](https://github.com/Microsoft/vscode-cpptools/issues/3419)
* Add a new (default) value of `EnabledIfIncludesResolve` to `C_Cpp.errorSquiggles`, which only shows error squiggles if include headers are successfully resolved. [PR #3421](https://github.com/Microsoft/vscode-cpptools/pull/3421)
* Disable debug heap by default with cppvsdbg. [#3484](https://github.com/Microsoft/vscode-cpptools/issues/3484)
* Reported by Djoulihen (@Djoulihen)
* Enable configuration squiggles for paths delimited by semicolons. [PR #3517](https://github.com/Microsoft/vscode-cpptools/pull/3517)
* Don't show release notes if the extension has never been installed before. [#3533](https://github.com/Microsoft/vscode-cpptools/issues/3533)
* Remove IntelliSense fallback code actions.
### Bug Fixes
* Fix browsing for functions with BOOST_FOREACH. [#953](https://github.com/Microsoft/vscode-cpptools/issues/953)
* Fix code action sometimes not appearing over a squiggled identifier. [#1436](https://github.com/microsoft/vscode-cpptools/issues/1436)
* Work around issue with VS Code not treating `.C` files as C++ files [Microsoft/vscode#59369](https://github.com/Microsoft/vscode/issues/59369) -- `.C` files become associated by name in `files.associations`. [#2558](https://github.com/Microsoft/vscode-cpptools/issues/2558)
* Fix various IntelliSense parsing bugs. [#2824](https://github.com/Microsoft/vscode-cpptools/issues/2824), [#3110](https://github.com/Microsoft/vscode-cpptools/issues/3110), [#3168](https://github.com/Microsoft/vscode-cpptools/issues/3168)
* Preserve newlines in documentation comments. [#2937](https://github.com/Microsoft/vscode-cpptools/issues/2937)
* Fix documentation comments above multi-line templates (and some other issues). [#3162](https://github.com/Microsoft/vscode-cpptools/issues/3162)
* Fix "Extension causes high cpu load" due to module loading. [#3213](https://github.com/Microsoft/vscode-cpptools/issues/3213)
* Fix auto-removal of compiler-provided paths in `includePath` when they end with a directory separator on Windows. [#3245](https://github.com/Microsoft/vscode-cpptools/issues/3245)
* Fix duplicate compiler build tasks appearing when `compilerPath` has arguments. [PR #3360](https://github.com/Microsoft/vscode-cpptools/pull/3360)
* Fix environment variables not resolving with `C_Cpp.intelliSenseCachePath`. [#3367](https://github.com/Microsoft/vscode-cpptools/issues/3367)
* Fix the formatting of snippets text. [#3376](https://github.com/Microsoft/vscode-cpptools/issues/3376)
* Fix the default `AccessModifierOffset` used when formatting. [#3376](https://github.com/Microsoft/vscode-cpptools/issues/3376)
* Fix null reference during initialization when using custom configuration providers. [PR #3377](https://github.com/Microsoft/vscode-cpptools/pull/3377)
* Fix symbol parsing when `__MINGW_ATTRIB_*` is used. [#3390](https://github.com/Microsoft/vscode-cpptools/issues/3390)
* Fix `compile_commands.json` configuration prompt being disabled per user instead of per folder. [PR #3399](https://github.com/Microsoft/vscode-cpptools/pull/3399)
* Fix `.cmd` and `.bat` files not working for `compilerPath` on Windows. [#3428](https://github.com/Microsoft/vscode-cpptools/issues/3428)
* Fix `compilerPath` with arguments that are surrounded by quotes. [#3428](https://github.com/Microsoft/vscode-cpptools/issues/3428)
* Fix documentation comments interpreting special characters as markdown. [#3441](https://github.com/Microsoft/vscode-cpptools/issues/3441)
* Fix hover using the configuration of the active document instead of the hovered document. [#3452](https://github.com/Microsoft/vscode-cpptools/issues/3452)
* Fix `c_cpp_properties.json` squiggles when the configuration name has regex characters. [PR #3478](https://github.com/Microsoft/vscode-cpptools/pull/3478)
* Use the `editor.tabSize` setting instead of `2` when creating build tasks. [PR #3486](https://github.com/Microsoft/vscode-cpptools/pull/3486)
* Fix some potential crashes on hover. [#3509](https://github.com/Microsoft/vscode-cpptools/issues/3509)
* Fix for `NullReferenceException` occurring when `"args"` is not specified in `launch.json`. [#3532](https://github.com/Microsoft/vscode-cpptools/issues/3532)
* Fix `Go to Definition` giving no results when IntelliSense doesn't find the symbol. [#3549](https://github.com/Microsoft/vscode-cpptools/issues/3549)
* Fix configuration squiggles with trailing backslashes. [PR #3573](https://github.com/Microsoft/vscode-cpptools/pull/3573)
* Fix `includePath` code actions, configuration prompts, and the `C/C++: Change configuration provider...` command. [PR #3576](https://github.com/Microsoft/vscode-cpptools/pull/3576)
* Fix randomly occurring crash (that could occur when opening files while IntelliSense squiggles are pending).
* Fix crash on hover (that could occur when document comments have blank lines).
* Fix icon of parameters in completion results.
## Version 0.22.1: March 21, 2019
* Fix `tasks.json` with single-line comments being overwritten when `Build and Debug Active File` is used. [#3327](https://github.com/Microsoft/vscode-cpptools/issues/3327)
* Fix an invalid `compilerPath` property getting added to `tasks.json` after doing `Configure Task` with a C/C++ compiler.
* Add IntelliSense caching for macOS 10.13 or later (0.22.0 only supported Windows and Linux).
## Version 0.22.0: March 19, 2019
### Major Changes
* Add warning squiggles for invalid properties and paths in `c_cpp_properties.json`. [#2799](https://github.com/Microsoft/vscode-cpptools/issues/2799), [PR #3283](https://github.com/Microsoft/vscode-cpptools/pull/3283)
+15 -17
View File
@@ -205,22 +205,20 @@
<tr>
<td>
<div>
<h2 class="caption">March 2019 Update</h2>
<div>Thank you for installing the C/C++ extension! We're excited to announce the following features in the March update:<br/>
<h3 style="font-weight: 600">IntelliSense caching</h3>
On Windows and Linux, the extension will now cache header information to improve IntelliSense speed for your code files. Support for macOS will be available in a future release.<br/>
<h2 class="caption">May 2019 Update</h2>
<div>Thank you for installing the C/C++ extension! We're excited to announce the following features in the May update:<br/>
<h3 style="font-weight: 600">IntelliSense configuration settings editor UI</h3>
The extension now has a UI editor to edit basic IntelliSense configuration settings defined in the underlying <code>c_cpp_properties.json</code> file.<br/>
<br/>
<em style="font-weight: 600">Please Note:</em> The extension writes the cache to disk in order to achieve this performance improvement. By default the cache files will be stored in your workspace
folder's ".vscode" folder, but you can change this location by using the <code>"C_Cpp.intelliSenseCachePath"</code> setting. You can also control how much disk space can be
used for the cache with the <code>"C_Cpp.intelliSenseCacheSize"</code> setting. The default is 5120 MB as the caches for individual translation units can be large,
depending on the size and number of included headers.<br/>
<h3 style="font-weight: 600">Build and debug the active source file</h3>
We added a command to help you generate build and debug tasks for single code files. Since this feature writes out tasks.json and launch.json files, it currently requires
that a workspace folder be opened in VS Code first. After that, you can press F5 or select the command from the context menu to configure the tasks or kick off a build and debug
session.<br/>
<h3 style="font-weight: 600">Configuration squiggles</h3>
We added additional validation to the <code>c_cpp_properties.json</code> file to assist in diagnosing potential configuration mistakes. They will show up as problems in the
problems window.<br/>
You can get to the IntelliSense configuration settings editor UI through the command palette (Ctrl+Shift+P) and running the <code>C/C++: Edit configurations (UI)</code> command.
The <code>c_cpp_properties.json</code> file can be opened by running the <code>C/C++: Edit configurations (JSON)</code> command.
<br/>
<br/>
<em style="font-weight: 600">Please Note:</em> When configuring IntelliSense for the first time, VS Code will open the UI editor or JSON file based on your <code>workbench.settings.editor</code> setting.
If <code>workbench.settings.editor</code> is set to “ui”, then the UI editor will open by default, and if it is set to “json”, then the JSON file will open by default. You can view that setting under VS Code preferences → settings → “Workbench Settings Editor”.<br/>
<h3 style="font-weight: 600">Log diagnostics command</h3>
We added the command <code>C/C++: Log Diagnostics</code> to help diagnose IntelliSense issues. Running the command shows IntelliSense information of the current translation unit that is associated with the active file.<br/>
<br/>
<br/>
Additional features and bug fixes are detailed in the <a href="https://github.com/Microsoft/vscode-cpptools/releases">full release notes</a>.</div>
@@ -246,9 +244,9 @@
<td>
<div>
<h3 class="caption">Blog Posts</h3>
<div><a href="https://devblogs.microsoft.com/cppblog/vscode-cpp-may-2019-update/">May 2019 Update</a></div>
<div><a href="https://devblogs.microsoft.com/cppblog/visual-studio-code-c-c-extension-march-2019-update/">March 2019 Update</a></div>
<div><a href="https://devblogs.microsoft.com/cppblog/vs-code-cpp-extension-january-2019-update/">January 2019 Update</a></div>
<div><a href="https://devblogs.microsoft.com/cppblog/visual-studio-code-cpp-extension-october-2018-update-and-a-simplified-insiders-program/">October 2018 Update</a></div>
<div><a href="https://devblogs.microsoft.com/cppblog/visual-studio-code-c-c-extension-august-2018-update/">August 2018 Update</a></div>
</div>
</td>
</tr>
File diff suppressed because it is too large Load Diff
+8
View File
@@ -142,6 +142,11 @@
"version": {
"type": "integer",
"description": "Version of the configuration file. This property is managed by the extension. Please do not change it."
},
"enableConfigurationSquiggles": {
"type": "boolean",
"default": true,
"description": "Controls whether the extension will report errors detected in c_cpp_properties.json."
}
},
"properties": {
@@ -153,6 +158,9 @@
},
"version": {
"$ref": "#/definitions/version"
},
"enableConfigurationSquiggles": {
"$ref": "#/definitions/enableConfigurationSquiggles"
}
},
"required": [
-19
View File
@@ -29,28 +29,9 @@ gulp.task('unitTests', (done) => {
});
});
gulp.task('integrationTests', (done) => {
env.set({
CODE_TESTS_PATH: "./out/test/integrationTests",
CODE_TESTS_WORKSPACE: "./test/integrationTests/testAssets/SimpleCppProject"
});
return gulp.src('./test/runVsCodeTestsWithAbsolutePaths.js', {read: false})
.pipe(mocha({ ui: "tdd" }))
.once('error', err => {
done();
process.exit(1);
})
.once('end', () => {
done();
process.exit();
});
});
/// Misc Tasks
const allTypeScript = [
'src/**/*.ts',
'tools/**/*.ts',
'!**/*.d.ts',
'!**/typings**'
];
+52 -58
View File
@@ -1,58 +1,52 @@
parameters:
name: ''
pool: ''
jobs:
- job: Windows
pool:
vmImage: 'vs2017-win2016'
steps:
- task: NodeTool@0
displayName: 'Use Node 8.x'
inputs:
versionSpec: 8.x
- script: npm install
displayName: "Install Dependencies"
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: npm run compile
displayName: "Compile Sources"
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: npm run pr-check
displayName: 'Validate Extension/package.json'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: npm run tslint
displayName: 'Run Linter'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: 'npm run unitTests'
displayName: 'Run unit tests'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
continueOnError: true
- script: 'copy "$(Build.SourcesDirectory)\Extension\out\test\integrationTests\MockDebugger\debugAdapterDescriptorFactory.js" "$(Build.SourcesDirectory)\Extension\out\src\Debugger\debugAdapterDescriptorFactory.js" /Y'
displayName: Replace Debug Adapter Descriptor Factory
- script: 'node node_modules/vscode/bin/test'
displayName: 'Run debug integration tests'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
continueOnError: true
env:
CODE_TESTS_PATH: '$(Build.SourcesDirectory)\Extension\out\test\integrationTests\debug'
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)\Extension'
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)\Extension\test\integrationTests\testAssets\SimpleCppProject'
CODE_DISABLE_EXTENSIONS: 1
- script: 'node node_modules/vscode/bin/test'
displayName: 'Run languageServer integration tests'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
continueOnError: true
env:
CODE_TESTS_PATH: '$(Build.SourcesDirectory)\Extension\out\test\integrationTests\languageServer'
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)\Extension'
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)\Extension\test\integrationTests\testAssets\SimpleCppProject'
CODE_DISABLE_EXTENSIONS: 1
parameters:
name: ''
pool: ''
jobs:
- job: Windows
pool:
vmImage: 'vs2017-win2016'
steps:
- task: NodeTool@0
displayName: 'Use Node 8.x'
inputs:
versionSpec: 8.x
- script: npm install
displayName: "Install Dependencies"
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: npm run compile
displayName: "Compile Sources"
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: npm run pr-check
displayName: 'Validate Extension/package.json'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: npm run tslint
displayName: 'Run Linter'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: 'npm run unitTests'
displayName: 'Run unit tests'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
continueOnError: true
- script: npm run pretest
displayName: "Compile Test Sources"
workingDirectory: '$(Build.SourcesDirectory)\Extension'
- script: 'node node_modules/vscode/bin/test'
displayName: 'Run languageServer integration tests'
workingDirectory: '$(Build.SourcesDirectory)\Extension'
env:
CODE_TESTS_PATH: '$(Build.SourcesDirectory)\Extension\out\test\integrationTests\languageServer'
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)\Extension'
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)\Extension\test\integrationTests\testAssets\SimpleCppProject'
CODE_DISABLE_EXTENSIONS: 1
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
continueOnError: true
+58 -67
View File
@@ -1,67 +1,58 @@
parameters:
name: ''
pool: ''
jobs:
- job: ${{ parameters.name }}
pool: ${{ parameters.pool }}
steps:
- task: NodeTool@0
displayName: 'Use Node 8.x'
inputs:
versionSpec: 8.x
- script: npm install
displayName: "Install Dependencies"
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: npm run compile
displayName: "Compile Sources"
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: npm run pr-check
displayName: 'Validate Extension/package.json'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: npm run tslint
displayName: 'Run Linter'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: 'npm run unitTests'
displayName: 'Run unit tests'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
continueOnError: true
- script: |
set -e
/usr/bin/Xvfb :10 -ac >> /tmp/Xvfb.out 2>&1 &
disown -ar
displayName: 'Start xvfb'
- script: |
cp $(Build.SourcesDirectory)/Extension/out/test/integrationTests/MockDebugger/debugAdapterDescriptorFactory.js $(Build.SourcesDirectory)/Extension/out/src/Debugger/debugAdapterDescriptorFactory.js
displayName: Replace Debug Adapter Descriptor Factory
- script: 'node node_modules/vscode/bin/test'
displayName: 'Run debug integration tests'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
continueOnError: true
env:
MOCK_DEBUG: 1
DISPLAY: :10
CODE_TESTS_PATH: '$(Build.SourcesDirectory)/Extension/out/test/integrationTests/debug'
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)/Extension'
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)/Extension/test/integrationTests/testAssets/SimpleCppProject'
CODE_DISABLE_EXTENSIONS: 1
- script: 'node node_modules/vscode/bin/test'
displayName: 'Run languageServer integration tests'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
continueOnError: true
env:
DISPLAY: :10
CODE_TESTS_PATH: '$(Build.SourcesDirectory)/Extension/out/test/integrationTests/languageServer'
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)/Extension'
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)/Extension/test/integrationTests/testAssets/SimpleCppProject'
CODE_DISABLE_EXTENSIONS: 1
parameters:
name: ''
pool: ''
jobs:
- job: ${{ parameters.name }}
pool: ${{ parameters.pool }}
steps:
- task: NodeTool@0
displayName: 'Use Node 8.x'
inputs:
versionSpec: 8.x
- script: npm install
displayName: "Install Dependencies"
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: npm run compile
displayName: "Compile Sources"
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: npm run pr-check
displayName: 'Validate Extension/package.json'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: npm run tslint
displayName: 'Run Linter'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: 'npm run unitTests'
displayName: 'Run unit tests'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
continueOnError: true
- script: |
set -e
/usr/bin/Xvfb :10 -ac >> /tmp/Xvfb.out 2>&1 &
disown -ar
displayName: 'Start xvfb'
- script: npm run pretest
displayName: "Compile Test Sources"
workingDirectory: '$(Build.SourcesDirectory)/Extension'
- script: 'node node_modules/vscode/bin/test'
displayName: 'Run languageServer integration tests'
workingDirectory: '$(Build.SourcesDirectory)/Extension'
env:
DISPLAY: :10
CODE_TESTS_PATH: '$(Build.SourcesDirectory)/Extension/out/test/integrationTests/languageServer'
CODE_EXTENSIONS_PATH: '$(Build.SourcesDirectory)/Extension'
CODE_TESTS_WORKSPACE: '$(Build.SourcesDirectory)/Extension/test/integrationTests/testAssets/SimpleCppProject'
CODE_DISABLE_EXTENSIONS: 1
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
continueOnError: true
+2720 -1469
View File
File diff suppressed because it is too large Load Diff
+82 -47
View File
@@ -2,7 +2,7 @@
"name": "cpptools",
"displayName": "C/C++",
"description": "C/C++ IntelliSense, debugging, and code browsing.",
"version": "0.22.0",
"version": "0.23.1",
"publisher": "ms-vscode",
"preview": true,
"icon": "LanguageCCPP_color_128x.png",
@@ -41,7 +41,7 @@
"activationEvents": [
"*"
],
"main": "./out/src/main",
"main": "./dist/main",
"contributes": {
"problemMatchers": [
{
@@ -77,13 +77,13 @@
"C_Cpp.clang_format_style": {
"type": "string",
"default": "file",
"description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use \"{key: value, ...}\" to set specific parameters, e.g.: \"{ BasedOnStyle: LLVM, IndentWidth: 8 }\"",
"description": "Coding style, currently supports: Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit. Use \"file\" to load the style from a .clang-format file in the current or parent directory. Use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4 }",
"scope": "resource"
},
"C_Cpp.clang_format_fallbackStyle": {
"type": "string",
"default": "Visual Studio",
"description": "Name of the predefined style used as a fallback in case clang-format is invoked with style \"file\" but the .clang-format file is not found. Possible values are Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit, none, or use \"{key: value, ...}\" to set specific parameters, e.g.: \"{ BasedOnStyle: LLVM, IndentWidth: 8 }\"",
"description": "Name of the predefined style used as a fallback in case clang-format is invoked with style \"file\" but the .clang-format file is not found. Possible values are Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit, none, or use {key: value, ...} to set specific parameters. For example, the \"Visual Studio\" style is similar to: { BasedOnStyle: LLVM, UseTab: Never, IndentWidth: 4, TabWidth: 4, BreakBeforeBraces: Allman, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: false, ColumnLimit: 0, AccessModifierOffset: -4 }",
"scope": "resource"
},
"C_Cpp.clang_format_sortIncludes": {
@@ -117,7 +117,7 @@
"Enabled",
"Disabled"
],
"default": "Enabled",
"default": "Disabled",
"description": "Controls whether the IntelliSense engine will automatically switch to the Tag Parser for translation units containing #include errors.",
"scope": "resource"
},
@@ -135,10 +135,11 @@
"type": "string",
"enum": [
"Enabled",
"Disabled"
"Disabled",
"EnabledIfIncludesResolve"
],
"default": "Enabled",
"description": "Controls whether suspected compile errors detected by the IntelliSense engine will be reported back to the editor. Warnings about #includes that could not be located will always be reported to the editor. This setting is ignored by the Tag Parser engine.",
"default": "EnabledIfIncludesResolve",
"description": "Controls whether suspected compile errors detected by the IntelliSense engine will be reported back to the editor. This setting is ignored by the Tag Parser engine.",
"scope": "resource"
},
"C_Cpp.dimInactiveRegions": {
@@ -470,6 +471,15 @@
"description": "The value to use for the system include path. If set, it overrides the system include path acquired via \"compilerPath\" and \"compileCommands\" settings.",
"scope": "resource"
},
"C_Cpp.default.enableConfigurationSquiggles": {
"type": [
"boolean",
"null"
],
"default": null,
"description": "Controls whether the extension will report errors detected in c_cpp_properties.json.",
"scope": "resource"
},
"C_Cpp.updateChannel": {
"type": "string",
"enum": [
@@ -500,8 +510,13 @@
"category": "C/C++"
},
{
"command": "C_Cpp.ConfigurationEdit",
"title": "%c_cpp.command.configurationEdit.title%",
"command": "C_Cpp.ConfigurationEditJSON",
"title": "%c_cpp.command.configurationEditJSON.title%",
"category": "C/C++"
},
{
"command": "C_Cpp.ConfigurationEditUI",
"title": "%c_cpp.command.configurationEditUI.title%",
"category": "C/C++"
},
{
@@ -525,8 +540,13 @@
"category": "C/C++"
},
{
"command": "C_Cpp.ToggleErrorSquiggles",
"title": "%c_cpp.command.toggleErrorSquiggles.title%",
"command": "C_Cpp.EnableErrorSquiggles",
"title": "%c_cpp.command.enableErrorSquiggles.title%",
"category": "C/C++"
},
{
"command": "C_Cpp.DisableErrorSquiggles",
"title": "%c_cpp.command.disableErrorSquiggles.title%",
"category": "C/C++"
},
{
@@ -573,6 +593,11 @@
"command": "C_Cpp.BuildAndDebugActiveFile",
"title": "%c_cpp.command.buildAndDebugActiveFile.title%",
"category": "C/C++"
},
{
"command": "C_Cpp.LogDiagnostics",
"title": "%c_cpp.command.logDiagnostics.title%",
"category": "C/C++"
}
],
"keybindings": [
@@ -1176,6 +1201,11 @@
},
"default": []
},
"envFile": {
"type": "string",
"description": "Absolute path to a file containing environment variable definitions. These file has key value pairs sepearted by an equals sign per line. E.g. KEY=VALUE",
"default": "${workspaceFolder}/.env"
},
"symbolSearchPath": {
"type": "string",
"description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".",
@@ -1208,6 +1238,11 @@
"<source-path>": "<target-path>"
}
},
"enableDebugHeap": {
"type": "boolean",
"description": "If false, the process will be launched with debug heap disabled. This sets the environment variable '_NO_DEBUG_HEAP' to '1'.",
"default": false
},
"logging": {
"type": "object",
"description": "Optional flags to determine what types of messages should be logged to the Debug Console.",
@@ -1403,55 +1438,55 @@
},
"scripts": {
"compile": "npm run vscode:prepublish",
"compileDev": "webpack --mode development",
"generateOptionsSchema": "gulp generateOptionsSchema",
"integrationTests": "gulp integrationTests",
"postinstall": "node ./node_modules/vscode/bin/install",
"pretest": "tsc -p ./",
"pretest": "tsc -p test.tsconfig.json",
"pr-check": "gulp pr-check",
"test": "gulp allTests",
"tslint": "gulp tslint",
"unitTests": "gulp unitTests",
"vscode:prepublish": "node ./src/Support/prepublish.js",
"watch": "tsc -watch -p ./"
"vscode:prepublish": "node ./tools/prepublish.js && webpack --mode production",
"watch": "webpack --watch --mode development"
},
"devDependencies": {
"@types/mocha": "^5.2.6",
"@types/node": "^8.10.43",
"@types/node": "^12.0.0",
"async-child-process": "^1.1.1",
"await-notify": "^1.0.1",
"child-process": "^1.0.2",
"extend": "3.0.2",
"gulp": "^4.0.0",
"gulp-env": "0.4.0",
"gulp-mocha": "5.0.0",
"gulp-tslint": "8.1.2",
"mocha": "^5.2.0",
"tslint": "5.8.0",
"tslint-microsoft-contrib": "5.0.1",
"tslint-no-unused-expression-chai": "0.0.3",
"typescript": "^2.9.2",
"vrsource-tslint-rules": "^5.8.3",
"vscode": "^1.1.30"
"gulp": "^4.0.2",
"gulp-env": "^0.4.0",
"gulp-mocha": "^6.0.0",
"gulp-tslint": "^8.1.4",
"tslint": "^5.16.0",
"tslint-microsoft-contrib": "^6.1.1",
"tslint-no-unused-expression-chai": "^0.1.4",
"ts-loader": "^6.0.0",
"typescript": "^3.4.5",
"vrsource-tslint-rules": "^6.0.0",
"vscode": "^1.1.34",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.2"
},
"dependencies": {
"@types/minimatch": "^3.0.3",
"http-proxy-agent": "~2.1.0",
"https-proxy-agent": "~2.2.0",
"jsonc-parser": "^1.0.0",
"minimatch": "~3.0.4",
"mkdirp": "~0.5.1",
"tmp": "~0.0.33",
"vscode-cpptools": "2.1.1",
"vscode-debugadapter": "~1.33.0",
"vscode-debugprotocol": "~1.33.0",
"escape-string-regexp": "^2.0.0",
"http-proxy-agent": "^2.1.0",
"https-proxy-agent": "^2.2.1",
"jsonc-parser": "^2.1.0",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.1",
"tmp": "^0.1.0",
"vscode-cpptools": "^2.1.2",
"vscode-debugadapter": "^1.34.0",
"vscode-debugprotocol": "^1.34.0",
"vscode-extension-telemetry": "^0.1.1",
"vscode-languageclient": "5.1.1",
"yauzl": "~2.10.0"
"vscode-languageclient": "^5.2.1",
"yauzl": "^2.10.0"
},
"runtimeDependencies": [
{
"description": "C/C++ language components (Linux / x86_64)",
"url": "https://go.microsoft.com/fwlink/?linkid=2065016",
"url": "https://go.microsoft.com/fwlink/?linkid=2092043",
"platforms": [
"linux"
],
@@ -1465,7 +1500,7 @@
},
{
"description": "C/C++ language components (Linux / x86)",
"url": "https://go.microsoft.com/fwlink/?linkid=2065017",
"url": "https://go.microsoft.com/fwlink/?linkid=2092112",
"platforms": [
"linux"
],
@@ -1481,7 +1516,7 @@
},
{
"description": "C/C++ language components (OS X)",
"url": "https://go.microsoft.com/fwlink/?linkid=2064955",
"url": "https://go.microsoft.com/fwlink/?linkid=2092042",
"platforms": [
"darwin"
],
@@ -1492,7 +1527,7 @@
},
{
"description": "C/C++ language components (Windows)",
"url": "https://go.microsoft.com/fwlink/?linkid=2065027",
"url": "https://go.microsoft.com/fwlink/?linkid=2092111",
"platforms": [
"win32"
],
@@ -1613,4 +1648,4 @@
"binaries": []
}
]
}
}
+6 -3
View File
@@ -1,12 +1,14 @@
{
"c_cpp.command.configurationSelect.title": "Scegli una configurazione...",
"c_cpp.command.configurationProviderSelect.title": "Cambia provider configurazioni...",
"c_cpp.command.configurationEdit.title": "Modifica configurazioni...",
"c_cpp.command.configurationEditJSON.title": "Modifica configurazioni (JSON)",
"c_cpp.command.configurationEditUI.title": "Modifica configurazioni (UI)",
"c_cpp.command.goToDeclaration.title": "Vai a dichiarazione",
"c_cpp.command.peekDeclaration.title": "Visualizza dichiarazione",
"c_cpp.command.switchHeaderSource.title": "Visualizza Header/Sorgente",
"c_cpp.command.navigate.title": "Naviga...",
"c_cpp.command.toggleErrorSquiggles.title": "Attiva/Disattiva sottolineamento errori",
"c_cpp.command.enableErrorSquiggles.title": "Attiva sottolineamento errori",
"c_cpp.command.disableErrorSquiggles.title": "Disattiva sottolineamento errori",
"c_cpp.command.toggleIncludeFallback.title": "Attiva/Disattiva motore di fallback IntelliSense negli errori di inclusione",
"c_cpp.command.toggleDimInactiveRegions.title": "Attiva/Disattiva colorazione regioni inattive",
"c_cpp.command.showReleaseNotes.title": "Mostra note di rilascio",
@@ -15,5 +17,6 @@
"c_cpp.command.resumeParsing.title": "Riprendi l'analisi del codice",
"c_cpp.command.showParsingCommands.title": "Mostra comandi per l'analisi del codice",
"c_cpp.command.takeSurvey.title": "Partecipa al Sondaggio",
"c_cpp.command.buildAndDebugActiveFile.title": "Compila ed Esegui il debug del file attivo"
"c_cpp.command.buildAndDebugActiveFile.title": "Compila ed Esegui il debug del file attivo",
"c_cpp.command.logDiagnostics.title": "Registra Diagnostica"
}
+6 -3
View File
@@ -1,12 +1,14 @@
{
"c_cpp.command.configurationSelect.title": "Select a configuration...",
"c_cpp.command.configurationProviderSelect.title": "Change configuration provider...",
"c_cpp.command.configurationEdit.title": "Edit configurations...",
"c_cpp.command.configurationEditJSON.title": "Edit configurations (JSON)",
"c_cpp.command.configurationEditUI.title": "Edit configurations (UI)",
"c_cpp.command.goToDeclaration.title": "Go to Declaration",
"c_cpp.command.peekDeclaration.title": "Peek Declaration",
"c_cpp.command.switchHeaderSource.title": "Switch Header/Source",
"c_cpp.command.navigate.title": "Navigate...",
"c_cpp.command.toggleErrorSquiggles.title": "Toggle error squiggles",
"c_cpp.command.enableErrorSquiggles.title": "Enable error squiggles",
"c_cpp.command.disableErrorSquiggles.title": "Disable error squiggles",
"c_cpp.command.toggleIncludeFallback.title": "Toggle IntelliSense engine fallback on include errors",
"c_cpp.command.toggleDimInactiveRegions.title": "Toggle inactive region colorization",
"c_cpp.command.showReleaseNotes.title": "Show release notes",
@@ -15,5 +17,6 @@
"c_cpp.command.resumeParsing.title": "Resume parsing",
"c_cpp.command.showParsingCommands.title": "Show parsing commands",
"c_cpp.command.takeSurvey.title": "Take survey",
"c_cpp.command.buildAndDebugActiveFile.title": "Build and Debug Active File"
"c_cpp.command.buildAndDebugActiveFile.title": "Build and Debug Active File",
"c_cpp.command.logDiagnostics.title": "Log Diagnostics"
}
+6 -3
View File
@@ -1,12 +1,14 @@
{
"c_cpp.command.configurationSelect.title": "选择配置...",
"c_cpp.command.configurationProviderSelect.title": "更换配置提供程序...",
"c_cpp.command.configurationEdit.title": "编辑配置...",
"c_cpp.command.configurationEditJSON.title": "编辑配置 (JSON)",
"c_cpp.command.configurationEditUI.title": "编辑配置 (UI)",
"c_cpp.command.goToDeclaration.title": "跳转到声明",
"c_cpp.command.peekDeclaration.title": "查看声明",
"c_cpp.command.switchHeaderSource.title": "切换头文件/源文件",
"c_cpp.command.navigate.title": "导航...",
"c_cpp.command.toggleErrorSquiggles.title": "切换错误下划线",
"c_cpp.command.enableErrorSquiggles.title": "启用错误下划线",
"c_cpp.command.disableErrorSquiggles.title": "禁用错误下划线",
"c_cpp.command.toggleIncludeFallback.title": "切换IntelliSense引擎头文件包含错误回退",
"c_cpp.command.toggleDimInactiveRegions.title": "切换非活跃区域着色",
"c_cpp.command.showReleaseNotes.title": "查看版本说明",
@@ -15,5 +17,6 @@
"c_cpp.command.resumeParsing.title": "继续解析",
"c_cpp.command.showParsingCommands.title": "查看解析命令",
"c_cpp.command.takeSurvey.title": "调查问卷",
"c_cpp.command.buildAndDebugActiveFile.title": "生成和调试当前文件"
"c_cpp.command.buildAndDebugActiveFile.title": "生成和调试当前文件",
"c_cpp.command.logDiagnostics.title": "记录诊断"
}
@@ -0,0 +1,85 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as fs from 'fs';
export interface Environment {
name: string;
value: string;
}
export class ParsedEnvironmentFile {
public Env: Environment[];
public Warning: string | null;
private constructor(env: Environment[], warning: string | null) {
this.Env = env;
this.Warning = warning;
}
public static CreateFromFile(envFile: string, initialEnv: Environment[] | undefined): ParsedEnvironmentFile {
let content: string = fs.readFileSync(envFile, "utf8");
return this.CreateFromContent(content, envFile, initialEnv);
}
public static CreateFromContent(content: string, envFile: string, initialEnv: Environment[] | undefined): ParsedEnvironmentFile {
// Remove UTF-8 BOM if present
if (content.charAt(0) === '\uFEFF') {
content = content.substr(1);
}
let parseErrors: string[] = [];
let env: Map<string, any> = new Map();
if (initialEnv) {
// Convert array to map to prevent duplicate keys being created.
// If a duplicate key is found, replace it.
initialEnv.forEach((e) => {
env.set(e.name, e.value);
});
}
content.split("\n").forEach(line => {
// Split the line between key and value
const r: RegExpMatchArray = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (r !== null) {
const key: string = r[1];
let value: string = r[2] || "";
if ((value.length > 0) && (value.charAt(0) === '"') && (value.charAt(value.length - 1) === '"')) {
value = value.replace(/\\n/gm, "\n");
}
value = value.replace(/(^['"]|['"]$)/g, "");
env.set(key, value);
} else {
// Blank lines and lines starting with # are no parse errors
const comments: RegExp = new RegExp(/^\s*(#|$)/);
if (!comments.test(line)) {
parseErrors.push(line);
}
}
});
// show error message if single lines cannot get parsed
let warning: string = null;
if (parseErrors.length !== 0) {
warning = "Ignoring non-parseable lines in envFile " + envFile + ": ";
parseErrors.forEach(function (value, idx, array): void {
warning += "\"" + value + "\"" + ((idx !== array.length - 1) ? ", " : ".");
});
}
// Convert env map back to array.
const arrayEnv: Environment[] = [];
for (let key of env.keys()) {
arrayEnv.push({name: key, value: env.get(key)});
}
return new ParsedEnvironmentFile(arrayEnv, warning);
}
}
@@ -16,6 +16,7 @@ import { buildAndDebugActiveFileStr } from './extension';
import { IConfiguration, IConfigurationSnippet, DebuggerType, MIConfigurations, WindowsConfigurations, WSLConfigurations, PipeTransportConfigurations } from './configurations';
import { parse } from 'jsonc-parser';
import { PlatformInformation } from '../platform';
import { Environment, ParsedEnvironmentFile } from './ParsedEnvironmentFile';
function isDebugLaunchStr(str: string): boolean {
return str === "(gdb) Launch" || str === "(lldb) Launch" || str === "(Windows) Launch";
@@ -94,7 +95,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
* Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder.
*/
async provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration[]> {
let buildTasks: vscode.Task[] = await getBuildTasks();
let buildTasks: vscode.Task[] = await getBuildTasks(true);
if (buildTasks.length === 0) {
return Promise.resolve(this.provider.getInitialConfigurations(this.type));
}
@@ -179,10 +180,41 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
*/
resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.DebugConfiguration> {
if (config) {
// Fail if cppvsdbg type is running on non-Windows
if (config.type === 'cppvsdbg' && os.platform() !== 'win32') {
vscode.window.showErrorMessage("Debugger of type: 'cppvsdbg' is only available on Windows. Use type: 'cppdbg' on the current OS platform.");
return undefined;
if (config.type === 'cppvsdbg') {
// Fail if cppvsdbg type is running on non-Windows
if (os.platform() !== 'win32') {
vscode.window.showErrorMessage("Debugger of type: 'cppvsdbg' is only available on Windows. Use type: 'cppdbg' on the current OS platform.");
return undefined;
}
// Disable debug heap by default, enable if 'enableDebugHeap' is set.
if (!config.enableDebugHeap) {
const disableDebugHeapEnvSetting : Environment = {"name" : "_NO_DEBUG_HEAP", "value" : "1"};
if (config.environment && util.isArray(config.environment)) {
config.environment.push(disableDebugHeapEnvSetting);
} else {
config.environment = [disableDebugHeapEnvSetting];
}
}
// Add environment variables from .env file
if (config.envFile) {
try {
const parsedFile: ParsedEnvironmentFile = ParsedEnvironmentFile.CreateFromFile(config.envFile.replace(/\${workspaceFolder}/g, folder.uri.path), config["environment"]);
// show error message if single lines cannot get parsed
if (parsedFile.Warning) {
CppConfigurationProvider.showFileWarningAsync(parsedFile.Warning, config.envFile);
}
config.environment = parsedFile.Env;
delete config.envFile;
} catch (e) {
throw new Error("Can't parse envFile " + config.envFile);
}
}
}
// Modify WSL config for OpenDebugAD7
@@ -211,6 +243,17 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider {
// if config or type is not specified, return null to trigger VS Code to open a configuration file https://github.com/Microsoft/vscode/issues/54213
return config && config.type ? config : null;
}
private static async showFileWarningAsync(message: string, fileName: string) : Promise<void> {
const openItem: vscode.MessageItem = { title: 'Open envFile' };
let result: vscode.MessageItem = await vscode.window.showWarningMessage(message, openItem);
if (result && result.title === openItem.title) {
let doc: vscode.TextDocument = await vscode.workspace.openTextDocument(fileName);
if (doc) {
vscode.window.showTextDocument(doc);
}
}
}
}
export class CppVsDbgConfigurationProvider extends CppConfigurationProvider {
+4 -1
View File
@@ -91,12 +91,15 @@ export function initialize(context: vscode.ExtensionContext): void {
await util.ensureBuildTaskExists(selection.configuration.preLaunchTask);
Telemetry.logDebuggerEvent("buildAndDebug", { "success": "false" });
} catch (e) {
if (e && e.message === util.failedToParseTasksJson) {
vscode.window.showErrorMessage(util.failedToParseTasksJson);
}
return Promise.resolve();
}
} else {
return Promise.resolve();
// TODO uncomment this when single file mode works correctly.
// const buildTasks: vscode.Task[] = await getBuildTasks();
// const buildTasks: vscode.Task[] = await getBuildTasks(true);
// const task: vscode.Task = buildTasks.find(task => task.name === selection.configuration.preLaunchTask);
// await vscode.tasks.executeTask(task);
// delete selection.configuration.preLaunchTask;
+158 -61
View File
@@ -113,11 +113,44 @@ interface CompileCommandsPaths {
paths: string[];
}
interface QueryTranslationUnitSourceParams {
uri: string;
}
export enum QueryTranslationUnitSourceConfigDisposition {
/**
* No custom config needed for this file
*/
ConfigNotNeeded = 0,
/**
* Custom config is needed for this file
*/
ConfigNeeded = 1,
/**
* Custom config is needed for the ancestor file returned in uri
*/
AncestorConfigNeeded = 2
}
interface QueryTranslationUnitSourceResult {
uri: string;
configDisposition: QueryTranslationUnitSourceConfigDisposition;
}
interface GetDiagnosticsResult {
diagnostics: string;
}
// Requests
const NavigationListRequest: RequestType<TextDocumentIdentifier, string, void, void> = new RequestType<TextDocumentIdentifier, string, void, void>('cpptools/requestNavigationList');
const GoToDeclarationRequest: RequestType<void, void, void, void> = new RequestType<void, void, void, void>('cpptools/goToDeclaration');
const QueryCompilerDefaultsRequest: RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void> = new RequestType<QueryCompilerDefaultsParams, configs.CompilerDefaults, void, void>('cpptools/queryCompilerDefaults');
const QueryTranslationUnitSourceRequest: RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void, void> = new RequestType<QueryTranslationUnitSourceParams, QueryTranslationUnitSourceResult, void, void>('cpptools/queryTranslationUnitSource');
const SwitchHeaderSourceRequest: RequestType<SwitchHeaderSourceParams, string, void, void> = new RequestType<SwitchHeaderSourceParams, string, void, void>('cpptools/didSwitchHeaderSource');
const GetDiagnosticsRequest: RequestType<void, GetDiagnosticsResult, void, void> = new RequestType<void, GetDiagnosticsResult, void, void>('cpptools/getDiagnostics');
// Notifications to the server
const DidOpenNotification: NotificationType<DidOpenTextDocumentParams, void> = new NotificationType<DidOpenTextDocumentParams, void>('textDocument/didOpen');
@@ -147,6 +180,7 @@ const DebugLogNotification: NotificationType<OutputNotificationBody, void> = ne
const InactiveRegionNotification: NotificationType<InactiveRegionParams, void> = new NotificationType<InactiveRegionParams, void>('cpptools/inactiveRegions');
const CompileCommandsPathsNotification: NotificationType<CompileCommandsPaths, void> = new NotificationType<CompileCommandsPaths, void>('cpptools/compileCommandsPaths');
const UpdateClangFormatPathNotification: NotificationType<string, void> = new NotificationType<string, void>('cpptools/updateClangFormatPath');
const UpdateIntelliSenseCachePathNotification: NotificationType<string, void> = new NotificationType<string, void>('cpptools/updateIntelliSenseCachePath');
class BlockingTask<T> {
private dependency: BlockingTask<any>;
@@ -202,6 +236,7 @@ export interface Client {
updateCustomConfigurations(requestingProvider?: CustomConfigurationProvider1): Thenable<void>;
updateCustomBrowseConfiguration(requestingProvider?: CustomConfigurationProvider1): Thenable<void>;
provideCustomConfiguration(document: vscode.TextDocument): Promise<void>;
logDiagnostics(): Promise<void>;
getCurrentConfigName(): Thenable<string>;
getCompilerPath(): Thenable<string>;
getKnownCompilers(): Thenable<configs.KnownCompiler[]>;
@@ -223,9 +258,12 @@ export interface Client {
handleConfigurationProviderSelectCommand(): void;
handleShowParsingCommands(): void;
handleConfigurationEditCommand(): void;
handleConfigurationEditJSONCommand(): void;
handleConfigurationEditUICommand(): void;
handleAddToIncludePathCommand(path: string): void;
onInterval(): void;
dispose(): Thenable<void>;
addFileAssociations(fileAssociations: string, is_c: boolean): void;
}
export function createClient(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder): Client {
@@ -245,6 +283,7 @@ class DefaultClient implements Client {
private trackedDocuments = new Set<vscode.TextDocument>();
private outputChannel: vscode.OutputChannel;
private debugChannel: vscode.OutputChannel;
private diagnosticsChannel: vscode.OutputChannel;
private crashTimes: number[] = [];
private isSupported: boolean = true;
private inactiveRegionsDecorations = new Map<string, DecorationRangesPair>();
@@ -318,16 +357,6 @@ class DefaultClient implements Client {
this.configuration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
this.disposables.push(this.configuration);
// The configurations will not be sent to the language server until the default include paths and frameworks have been set.
// The event handlers must be set before this happens.
languageClient.sendRequest(QueryCompilerDefaultsRequest, {}).then((compilerDefaults: configs.CompilerDefaults) => {
this.configuration.CompilerDefaults = compilerDefaults;
// Only register the real commands after the extension has finished initializing,
// e.g. prevents empty c_cpp_properties.json from generation.
registerCommands();
});
this.languageClient = languageClient;
this.settingsTracker = getTracker(this.RootUri);
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
@@ -336,6 +365,16 @@ class DefaultClient implements Client {
// Listen for messages from the language server.
this.registerNotifications();
this.registerFileWatcher();
// The configurations will not be sent to the language server until the default include paths and frameworks have been set.
// The event handlers must be set before this happens.
return languageClient.sendRequest(QueryCompilerDefaultsRequest, {}).then((compilerDefaults: configs.CompilerDefaults) => {
this.configuration.CompilerDefaults = compilerDefaults;
// Only register the real commands after the extension has finished initializing,
// e.g. prevents empty c_cpp_properties.json from generation.
registerCommands();
});
},
(err) => {
this.isSupported = false; // Running on an OS we don't support yet.
@@ -363,6 +402,7 @@ class DefaultClient implements Client {
let serverModule: string = getLanguageServerFileName();
let exeExists: boolean = fs.existsSync(serverModule);
if (!exeExists) {
telemetry.logLanguageServerEvent("missingLanguageServerBinary");
throw String('Missing binary at ' + serverModule);
}
let serverName: string = this.getName(workspaceFolder);
@@ -374,7 +414,8 @@ class DefaultClient implements Client {
let settings: CppSettings = new CppSettings(workspaceFolder ? workspaceFolder.uri : null);
let other: OtherSettings = new OtherSettings(workspaceFolder ? workspaceFolder.uri : null);
let storagePath: string = util.extensionContext.storagePath;
let storagePath: string = util.extensionContext ? util.extensionContext.storagePath :
path.join((workspaceFolder ? workspaceFolder.uri.fsPath : ""), "/.vscode");
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
storagePath = path.join(storagePath, serverName);
}
@@ -383,13 +424,11 @@ class DefaultClient implements Client {
let intelliSenseCacheDisabled: boolean = false;
if (os.platform() === "darwin") {
intelliSenseCacheDisabled = true;
// TODO: Re-enable this after the performance is improved on Mac.
//const releaseParts: string[] = os.release().split(".");
//if (releaseParts.length >= 1) {
// // AutoPCH doesn't work for older Mac OS's.
// intelliSenseCacheDisabled = parseInt(releaseParts[0]) < 17;
//}
const releaseParts: string[] = os.release().split(".");
if (releaseParts.length >= 1) {
// AutoPCH doesn't work for older Mac OS's.
intelliSenseCacheDisabled = parseInt(releaseParts[0]) < 17;
}
}
let clientOptions: LanguageClientOptions = {
@@ -408,7 +447,7 @@ class DefaultClient implements Client {
clang_format_fallbackStyle: settings.clangFormatFallbackStyle,
clang_format_sortIncludes: settings.clangFormatSortIncludes,
formatting: settings.formatting,
extension_path: util.extensionContext.extensionPath,
extension_path: util.extensionPath,
exclude_files: other.filesExclude,
exclude_search: other.searchExclude,
storage_path: storagePath,
@@ -416,7 +455,7 @@ class DefaultClient implements Client {
intelliSenseEngine: settings.intelliSenseEngine,
intelliSenseEngineFallback: settings.intelliSenseEngineFallback,
intelliSenseCacheDisabled: intelliSenseCacheDisabled,
intelliSenseCachePath : settings.intelliSenseCachePath,
intelliSenseCachePath : util.resolveVariables(settings.intelliSenseCachePath, this.AdditionalEnvironment),
intelliSenseCacheSize : settings.intelliSenseCacheSize,
autocomplete: settings.autoComplete,
errorSquiggles: settings.errorSquiggles,
@@ -478,6 +517,10 @@ class DefaultClient implements Client {
let settings: CppSettings = new CppSettings(this.RootUri);
this.languageClient.sendNotification(UpdateClangFormatPathNotification, util.resolveVariables(settings.clangFormatPath, this.AdditionalEnvironment));
}
if (changedSettings["intelliSenseCachePath"]) {
let settings: CppSettings = new CppSettings(this.RootUri);
this.languageClient.sendNotification(UpdateIntelliSenseCachePathNotification, util.resolveVariables(settings.intelliSenseCachePath, this.AdditionalEnvironment));
}
this.configuration.onDidChangeSettings();
telemetry.logLanguageServerEvent("CppSettingsChange", changedSettings, null);
}
@@ -605,6 +648,18 @@ class DefaultClient implements Client {
});
}
public async logDiagnostics(): Promise<void> {
let response: GetDiagnosticsResult = await this.requestWhenReady(() => this.languageClient.sendRequest(GetDiagnosticsRequest, null));
if (!this.diagnosticsChannel) {
this.diagnosticsChannel = vscode.window.createOutputChannel("C/C++ Diagnostics");
this.disposables.push(this.diagnosticsChannel);
}
let header: string = `-------- Diagnostics - ${new Date().toLocaleString()}\n`;
let version: string = `Version: ${util.packageJson.version}\n`;
this.diagnosticsChannel.appendLine(`${header}${version}${response.diagnostics}`);
this.diagnosticsChannel.show(false);
}
public async provideCustomConfiguration(document: vscode.TextDocument): Promise<void> {
let tokenSource: CancellationTokenSource = new CancellationTokenSource();
let providers: CustomConfigurationProviderCollection = getCustomConfigProviders();
@@ -618,6 +673,15 @@ class DefaultClient implements Client {
}
let providerName: string = providerId;
let params: QueryTranslationUnitSourceParams = {
uri: document.uri.toString()
};
let response: QueryTranslationUnitSourceResult = await this.requestWhenReady(() => this.languageClient.sendRequest(QueryTranslationUnitSourceRequest, params));
if (response.configDisposition === QueryTranslationUnitSourceConfigDisposition.ConfigNotNeeded) {
return Promise.resolve();
}
let tuUri: vscode.Uri = vscode.Uri.parse(response.uri);
let configName: string = await this.getCurrentConfigName();
const notReadyMessage: string = `${providerName} is not ready`;
let provideConfigurationAsync: () => Thenable<SourceFileConfigurationItem[]> = async () => {
@@ -630,8 +694,8 @@ class DefaultClient implements Client {
}
providerName = provider.name;
if (await provider.canProvideConfiguration(document.uri, tokenSource.token)) {
return provider.provideConfigurations([document.uri], tokenSource.token);
if (await provider.canProvideConfiguration(tuUri, tokenSource.token)) {
return provider.provideConfigurations([tuUri], tokenSource.token);
}
}
} catch (err) {
@@ -644,6 +708,11 @@ class DefaultClient implements Client {
(configs: SourceFileConfigurationItem[]) => {
if (configs && configs.length > 0) {
this.sendCustomConfigurations(configs, true);
if (response.configDisposition === QueryTranslationUnitSourceConfigDisposition.AncestorConfigNeeded) {
// replacing uri with original uri
let newConfig: SourceFileConfigurationItem = { uri: document.uri, configuration: configs[0].configuration };
this.sendCustomConfigurations([newConfig], true);
}
}
},
(err) => {
@@ -651,7 +720,7 @@ class DefaultClient implements Client {
return;
}
let settings: CppSettings = new CppSettings(this.RootUri);
if (settings.configurationWarnings === "Enabled" && !this.isExternalHeader(document) && !vscode.debug.activeDebugSession) {
if (settings.configurationWarnings === "Enabled" && !this.isExternalHeader(document.uri) && !vscode.debug.activeDebugSession) {
const dismiss: string = "Dismiss";
const disable: string = "Disable Warnings";
let message: string = `'${providerName}' is unable to provide IntelliSense configuration information for '${document.uri.fsPath}'. ` +
@@ -672,8 +741,8 @@ class DefaultClient implements Client {
});
}
private isExternalHeader(document: vscode.TextDocument): boolean {
return util.isHeader(document) && !document.uri.toString().startsWith(this.RootUri.toString());
private isExternalHeader(uri: vscode.Uri): boolean {
return util.isHeader(uri) && !uri.toString().startsWith(this.RootUri.toString());
}
private getCustomConfigurationProviderId(): Thenable<string|undefined> {
@@ -881,7 +950,11 @@ class DefaultClient implements Client {
// TODO: Move this code to a different place?
if (cppSettings.autoAddFileAssociations && payload.navigation.startsWith("<def")) {
this.addFileAssociations(payload.navigation.substr(4));
let fileAssociations: string = payload.navigation.substr(4);
let is_c: boolean = fileAssociations.startsWith("c");
// Skip over rest of header: c>; or >;
fileAssociations = fileAssociations.substr(is_c ? 3 : 2);
this.addFileAssociations(fileAssociations, is_c);
return;
}
@@ -895,41 +968,41 @@ class DefaultClient implements Client {
this.model.navigationLocation.Value = currentNavigation;
}
private addFileAssociations(fileAssociations: string): void {
public addFileAssociations(fileAssociations: string, is_c: boolean): void {
let settings: OtherSettings = new OtherSettings(this.RootUri);
let assocs: any = settings.filesAssociations;
let is_c: boolean = fileAssociations.startsWith("c");
// Skip over rest of header: c>; or >;
fileAssociations = fileAssociations.substr(is_c ? 3 : 2);
let filesAndPaths: string[] = fileAssociations.split(";");
let foundNewAssociation: boolean = false;
for (let i: number = 0; i < filesAndPaths.length - 1; ++i) {
for (let i: number = 0; i < filesAndPaths.length; ++i) {
let fileAndPath: string[] = filesAndPaths[i].split("@");
let file: string = fileAndPath[0];
let filePath: string = fileAndPath[1];
if ((file in assocs) || (("**/" + file) in assocs)) {
continue; // File already has an association.
}
let j: number = file.lastIndexOf('.');
if (j !== -1) {
let ext: string = file.substr(j);
if ((("*" + ext) in assocs) || (("**/*" + ext) in assocs)) {
continue; // Extension already has an association.
// Skip empty or malformed
if (fileAndPath.length === 2) {
let file: string = fileAndPath[0];
let filePath: string = fileAndPath[1];
if ((file in assocs) || (("**/" + file) in assocs)) {
continue; // File already has an association.
}
}
let foundGlobMatch: boolean = false;
for (let assoc in assocs) {
if (minimatch(filePath, assoc)) {
foundGlobMatch = true;
break; // Assoc matched a glob pattern.
let j: number = file.lastIndexOf('.');
if (j !== -1) {
let ext: string = file.substr(j);
if ((("*" + ext) in assocs) || (("**/*" + ext) in assocs)) {
continue; // Extension already has an association.
}
}
let foundGlobMatch: boolean = false;
for (let assoc in assocs) {
if (minimatch(filePath, assoc)) {
foundGlobMatch = true;
break; // Assoc matched a glob pattern.
}
}
if (foundGlobMatch) {
continue;
}
assocs[file] = is_c ? "c" : "cpp";
foundNewAssociation = true;
}
if (foundGlobMatch) {
continue;
}
assocs[file] = is_c ? "c" : "cpp";
foundNewAssociation = true;
}
if (foundNewAssociation) {
settings.filesAssociations = assocs;
@@ -959,22 +1032,31 @@ class DefaultClient implements Client {
let showIntelliSenseFallbackMessage: PersistentState<boolean> = new PersistentState<boolean>("CPP.showIntelliSenseFallbackMessage", true);
if (showIntelliSenseFallbackMessage.Value) {
ui.showConfigureIncludePathMessage(() => {
let learnMorePanel: string = "Configuration Help";
let configJSON: string = "Configure (JSON)";
let configUI: string = "Configure (UI)";
let dontShowAgain: string = "Don't Show Again";
let fallbackMsg: string = this.configuration.VcpkgInstalled ?
"Update your IntelliSense settings or use Vcpkg to install libraries to help find missing headers." :
"Configure your IntelliSense settings to help find missing headers.";
return vscode.window.showInformationMessage(fallbackMsg, learnMorePanel, dontShowAgain).then((value) => {
return vscode.window.showInformationMessage(fallbackMsg, configJSON, configUI, dontShowAgain).then((value) => {
switch (value) {
case learnMorePanel:
let uri: vscode.Uri = vscode.Uri.parse(`https://go.microsoft.com/fwlink/?linkid=864631`);
vscode.commands.executeCommand('vscode.open', uri);
case configJSON:
vscode.commands.getCommands(true).then((commands: string[]) => {
if (commands.indexOf("workbench.action.problems.focus") >= 0) {
vscode.commands.executeCommand("workbench.action.problems.focus");
}
});
this.handleConfigurationEditJSONCommand();
telemetry.logLanguageServerEvent("SettingsCommand", { "toast": "json" }, null);
break;
case configUI:
vscode.commands.getCommands(true).then((commands: string[]) => {
if (commands.indexOf("workbench.action.problems.focus") >= 0) {
vscode.commands.executeCommand("workbench.action.problems.focus");
}
}
});
this.handleConfigurationEditCommand();
this.handleConfigurationEditUICommand();
telemetry.logLanguageServerEvent("SettingsCommand", { "toast": "ui" }, null);
break;
case dontShowAgain:
showIntelliSenseFallbackMessage.Value = false;
@@ -1040,7 +1122,7 @@ class DefaultClient implements Client {
return;
}
let ask: PersistentState<boolean> = new PersistentState<boolean>("CPP.showCompileCommandsSelection", true);
let ask: PersistentFolderState<boolean> = new PersistentFolderState<boolean>("CPP.showCompileCommandsSelection", true, this.RootPath);
if (!ask.Value) {
return;
}
@@ -1161,6 +1243,9 @@ class DefaultClient implements Client {
}).then(() => {
let newProvider: string = this.configuration.CurrentConfigurationProvider;
if (this.configurationProvider !== newProvider) {
if (this.configurationProvider) {
this.clearCustomConfigurations();
}
this.configurationProvider = newProvider;
this.updateCustomConfigurations();
this.updateCustomBrowseConfiguration();
@@ -1314,7 +1399,15 @@ class DefaultClient implements Client {
}
public handleConfigurationEditCommand(): void {
this.notifyWhenReady(() => this.configuration.handleConfigurationEditCommand(vscode.window.showTextDocument));
this.notifyWhenReady(() => this.configuration.handleConfigurationEditCommand(null, vscode.window.showTextDocument));
}
public handleConfigurationEditJSONCommand(): void {
this.notifyWhenReady(() => this.configuration.handleConfigurationEditJSONCommand(null, vscode.window.showTextDocument));
}
public handleConfigurationEditUICommand(): void {
this.notifyWhenReady(() => this.configuration.handleConfigurationEditUICommand(null, vscode.window.showTextDocument));
}
public handleAddToIncludePathCommand(path: string): void {
@@ -1379,6 +1472,7 @@ class NullClient implements Client {
updateCustomConfigurations(requestingProvider?: CustomConfigurationProvider1): Thenable<void> { return Promise.resolve(); }
updateCustomBrowseConfiguration(requestingProvider?: CustomConfigurationProvider1): Thenable<void> { return Promise.resolve(); }
provideCustomConfiguration(document: vscode.TextDocument): Promise<void> { return Promise.resolve(); }
logDiagnostics(): Promise<void> { return Promise.resolve(); }
getCurrentConfigName(): Thenable<string> { return Promise.resolve(""); }
getCompilerPath(): Thenable<string> { return Promise.resolve(""); }
getKnownCompilers(): Thenable<configs.KnownCompiler[]> { return Promise.resolve([]); }
@@ -1400,6 +1494,8 @@ class NullClient implements Client {
handleConfigurationProviderSelectCommand(): void {}
handleShowParsingCommands(): void {}
handleConfigurationEditCommand(): void {}
handleConfigurationEditJSONCommand(): void {}
handleConfigurationEditUICommand(): void {}
handleAddToIncludePathCommand(path: string): void {}
onInterval(): void {}
dispose(): Thenable<void> {
@@ -1407,4 +1503,5 @@ class NullClient implements Client {
this.stringEvent.dispose();
return Promise.resolve();
}
addFileAssociations(fileAssociations: string, is_c: boolean): void {}
}
+458 -127
View File
@@ -10,10 +10,12 @@ import * as vscode from 'vscode';
import * as util from '../common';
import * as telemetry from '../telemetry';
import { PersistentFolderState } from './persistentState';
import { CppSettings } from './settings';
import { CppSettings, OtherSettings } from './settings';
import { ABTestSettings, getABTestSettings } from '../abTesting';
import { getCustomConfigProviders } from './customProviders';
import { SettingsPanel } from './settingsPanel';
import * as os from 'os';
import escapeStringRegExp = require('escape-string-regexp');
const configVersion: number = 4;
type Environment = { [key: string]: string | string[] };
@@ -42,6 +44,7 @@ export interface ConfigurationJson {
configurations: Configuration[];
env?: {[key: string]: string | string[]};
version: number;
enableConfigurationSquiggles?: boolean;
}
export interface Configuration {
@@ -61,6 +64,12 @@ export interface Configuration {
browse?: Browse;
}
export interface ConfigurationErrors {
compilerPath?: string;
includePath?: string;
intelliSenseMode?: string;
}
export interface Browse {
path?: string[];
limitSymbolsToIncludedHeaders?: boolean | string;
@@ -111,6 +120,7 @@ export class CppProperties {
private diagnosticCollection: vscode.DiagnosticCollection;
private prevSquiggleMetrics: Map<string, { [key: string]: number }> = new Map<string, { [key: string]: number }>();
private rootfs: string = null;
private settingsPanel: SettingsPanel = undefined;
// Any time the default settings are parsed and assigned to `this.configurationJson`,
// we want to track when the default includes have been added to it.
@@ -123,9 +133,7 @@ export class CppProperties {
this.currentConfigurationIndex = new PersistentFolderState<number>("CppProperties.currentConfigurationIndex", -1, rootPath);
this.configFolder = path.join(rootPath, ".vscode");
this.diagnosticCollection = vscode.languages.createDiagnosticCollection(rootPath);
this.buildVcpkgIncludePath();
this.disposables.push(vscode.Disposable.from(this.configurationsChanged, this.selectionChanged, this.compileCommandsChanged));
}
@@ -171,7 +179,8 @@ export class CppProperties {
this.propertiesFile = null;
}
this.configFileWatcher = vscode.workspace.createFileSystemWatcher(path.join(this.configFolder, this.configurationGlobPattern));
let settingsPath: string = path.join(this.configFolder, this.configurationGlobPattern);
this.configFileWatcher = vscode.workspace.createFileSystemWatcher(settingsPath);
this.disposables.push(this.configFileWatcher);
this.configFileWatcher.onDidCreate((uri) => {
this.propertiesFile = uri;
@@ -185,7 +194,24 @@ export class CppProperties {
});
this.configFileWatcher.onDidChange(() => {
this.handleConfigurationChange();
// If the file is one of the textDocument's vscode is tracking, we need to wait for an
// onDidChangeTextDocument event, or we may get old/cached contents when we open it.
let alreadyTracking: boolean = false;
for (let i: number = 0; i < vscode.workspace.textDocuments.length; i++) {
if (vscode.workspace.textDocuments[i].uri.fsPath === settingsPath) {
alreadyTracking = true;
break;
}
}
if (!alreadyTracking) {
this.handleConfigurationChange();
}
});
vscode.workspace.onDidChangeTextDocument((e: vscode.TextDocumentChangeEvent) => {
if (e.document.uri.fsPath === settingsPath) {
this.handleConfigurationChange();
}
});
this.handleConfigurationChange();
@@ -201,6 +227,22 @@ export class CppProperties {
private onSelectionChanged(): void {
this.selectionChanged.fire(this.CurrentConfigurationIndex);
if (this.settingsPanel) {
this.ensurePropertiesFile().then(() => {
if (this.propertiesFile) {
// Clear out any modifications we may have made internally by parsing the json file
if (this.parsePropertiesFile(false)) {
// Update the UI with new selected configuration
this.settingsPanel.updateConfigUI(
this.configurationJson.configurations[this.currentConfigurationIndex.Value],
this.getErrorsForConfigUI());
} else {
// Parse failed, open json file
vscode.workspace.openTextDocument(this.propertiesFile);
}
}
});
}
this.handleSquiggles();
}
@@ -355,35 +397,51 @@ export class CppProperties {
}
}
private isCompilerIntelliSenseModeCompatible(): boolean {
// Check if intelliSenseMode and compilerPath are compatible
// cl.exe and msvc mode should be used together
// Ignore if compiler path is not set or intelliSenseMode is not set
if (this.CurrentConfiguration.compilerPath === undefined ||
this.CurrentConfiguration.compilerPath === "" ||
this.CurrentConfiguration.compilerPath === "${default}" ||
this.CurrentConfiguration.intelliSenseMode === undefined ||
this.CurrentConfiguration.intelliSenseMode === "" ||
this.CurrentConfiguration.intelliSenseMode === "${default}") {
return true;
}
let compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(this.CurrentConfiguration.compilerPath);
return compilerPathAndArgs.compilerPath.endsWith("cl.exe") === (this.CurrentConfiguration.intelliSenseMode === "msvc-x64");
}
public addToIncludePathCommand(path: string): void {
this.handleConfigurationEditCommand((document: vscode.TextDocument) => {
this.handleConfigurationEditCommand(() => {
telemetry.logLanguageServerEvent("addToIncludePath");
this.parsePropertiesFile(); // Clear out any modifications we may have made internally.
this.parsePropertiesFile(true); // Clear out any modifications we may have made internally.
let config: Configuration = this.CurrentConfiguration;
if (config.includePath === undefined) {
config.includePath = ["${default}"];
}
config.includePath.splice(config.includePath.length, 0, path);
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
this.writeToJson();
this.handleConfigurationChange();
});
}, null);
}
public updateCustomConfigurationProvider(providerId: string): Thenable<void> {
return new Promise<void>((resolve) => {
if (this.propertiesFile) {
this.handleConfigurationEditCommand((document: vscode.TextDocument) => {
this.parsePropertiesFile(); // Clear out any modifications we may have made internally.
this.handleConfigurationEditJSONCommand(() => {
this.parsePropertiesFile(true); // Clear out any modifications we may have made internally.
let config: Configuration = this.CurrentConfiguration;
if (providerId) {
config.configurationProvider = providerId;
} else {
delete config.configurationProvider;
}
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
this.writeToJson();
this.handleConfigurationChange();
resolve();
});
}, null);
} else {
let settings: CppSettings = new CppSettings(this.rootUri);
if (providerId) {
@@ -398,20 +456,25 @@ export class CppProperties {
}
public setCompileCommands(path: string): void {
this.handleConfigurationEditCommand((document: vscode.TextDocument) => {
this.parsePropertiesFile(); // Clear out any modifications we may have made internally.
this.handleConfigurationEditJSONCommand(() => {
this.parsePropertiesFile(true); // Clear out any modifications we may have made internally.
let config: Configuration = this.CurrentConfiguration;
config.compileCommands = path;
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
this.writeToJson();
this.handleConfigurationChange();
});
}, null);
}
public select(index: number): Configuration {
if (index === this.configurationJson.configurations.length) {
this.handleConfigurationEditCommand(vscode.window.showTextDocument);
this.handleConfigurationEditUICommand(null, vscode.window.showTextDocument);
return;
}
if (index === this.configurationJson.configurations.length + 1) {
this.handleConfigurationEditJSONCommand(null, vscode.window.showTextDocument);
return;
}
this.currentConfigurationIndex.Value = index;
this.onSelectionChanged();
}
@@ -548,59 +611,93 @@ export class CppProperties {
}
}
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);
});
public handleConfigurationEditCommand(onCreation: () => void, showDocument: (document: vscode.TextDocument) => void): void {
let otherSettings: OtherSettings = new OtherSettings(this.rootUri);
if (otherSettings.settingsEditor === "ui") {
this.handleConfigurationEditUICommand(onCreation, showDocument);
} else {
fs.mkdir(this.configFolder, (e: NodeJS.ErrnoException) => {
if (!e || e.code === 'EEXIST') {
let fullPathToFile: string = path.join(this.configFolder, "c_cpp_properties.json");
let filePath: vscode.Uri = vscode.Uri.file(fullPathToFile).with({ scheme: "untitled" });
vscode.workspace.openTextDocument(filePath).then((document: vscode.TextDocument) => {
let edit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
if (this.configurationJson) {
this.resetToDefaultSettings(true);
this.handleConfigurationEditJSONCommand(onCreation, showDocument);
}
}
public handleConfigurationEditJSONCommand(onCreation: () => void, showDocument: (document: vscode.TextDocument) => void): void {
this.ensurePropertiesFile().then(() => {
console.assert(this.propertiesFile);
if (onCreation) {
onCreation();
}
// Directly open the json file
vscode.workspace.openTextDocument(this.propertiesFile).then((document: vscode.TextDocument) => {
if (showDocument) {
showDocument(document);
}
});
});
}
public handleConfigurationEditUICommand(onCreation: () => void, showDocument: (document: vscode.TextDocument) => void): void {
this.ensurePropertiesFile().then(() => {
if (this.propertiesFile) {
if (onCreation) {
onCreation();
}
if (this.parsePropertiesFile(false)) {
// Parse successful, show UI
if (this.settingsPanel === undefined) {
this.settingsPanel = new SettingsPanel();
this.settingsPanel.SettingsPanelActivated(() => this.onSettingsPanelActivated());
this.settingsPanel.ConfigValuesChanged(() => this.saveConfigurationUI());
this.disposables.push(this.settingsPanel);
}
this.settingsPanel.createOrShow(
this.configurationJson.configurations[this.currentConfigurationIndex.Value],
this.getErrorsForConfigUI());
} else {
// Parse failed, open json file
vscode.workspace.openTextDocument(this.propertiesFile).then((document: vscode.TextDocument) => {
if (showDocument) {
showDocument(document);
}
this.applyDefaultIncludePathsAndFrameworks();
let settings: CppSettings = new CppSettings(this.rootUri);
if (settings.defaultConfigurationProvider) {
this.configurationJson.configurations.forEach(config => {
config.configurationProvider = settings.defaultConfigurationProvider;
});
settings.update("default.configurationProvider", undefined); // delete the setting
}
let savedKnownCompilers: KnownCompiler[] = this.configurationJson.configurations[0].knownCompilers;
delete this.configurationJson.configurations[0].knownCompilers;
edit.insert(document.uri, new vscode.Position(0, 0), JSON.stringify(this.configurationJson, null, 4));
this.configurationJson.configurations[0].knownCompilers = savedKnownCompilers;
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 onSettingsPanelActivated(): void {
if (this.configurationJson) {
this.ensurePropertiesFile().then(() => {
if (this.propertiesFile) {
if (this.parsePropertiesFile(false)) {
// The settings UI became visible or active.
// Ensure settingsPanel has copy of latest current configuration
this.settingsPanel.updateConfigUI(
this.configurationJson.configurations[this.currentConfigurationIndex.Value],
this.getErrorsForConfigUI());
} else {
// Parse failed, open json file
vscode.workspace.openTextDocument(this.propertiesFile);
}
}
});
}
}
private saveConfigurationUI(): void {
this.parsePropertiesFile(false); // Clear out any modifications we may have made internally.
let config: Configuration = this.settingsPanel.getLastValuesFromConfigUI();
this.configurationJson.configurations[this.currentConfigurationIndex.Value] = config;
this.settingsPanel.updateErrors(this.getErrorsForConfigUI());
this.writeToJson();
}
private handleConfigurationChange(): void {
if (this.propertiesFile === undefined) {
return; // Occurs when propertiesFile hasn't been checked yet.
}
this.configFileWatcherFallbackTime = new Date();
if (this.propertiesFile) {
this.parsePropertiesFile();
this.parsePropertiesFile(true);
// 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) {
@@ -620,18 +717,55 @@ export class CppProperties {
this.updateServerOnFolderSettingsChange();
}
private parsePropertiesFile(): void {
private async ensurePropertiesFile(): Promise<void> {
if (this.propertiesFile && fs.existsSync(this.propertiesFile.fsPath)) {
return;
} else {
try {
if (!fs.existsSync(this.configFolder)) {
fs.mkdirSync(this.configFolder);
}
let fullPathToFile: string = path.join(this.configFolder, "c_cpp_properties.json");
if (this.configurationJson) {
this.resetToDefaultSettings(true);
}
this.applyDefaultIncludePathsAndFrameworks();
let settings: CppSettings = new CppSettings(this.rootUri);
if (settings.defaultConfigurationProvider) {
this.configurationJson.configurations.forEach(config => {
config.configurationProvider = settings.defaultConfigurationProvider;
});
settings.update("default.configurationProvider", undefined); // delete the setting
}
let savedKnownCompilers: KnownCompiler[] = this.configurationJson.configurations[0].knownCompilers;
delete this.configurationJson.configurations[0].knownCompilers;
await util.writeFileText(fullPathToFile, JSON.stringify(this.configurationJson, null, 4));
this.configurationJson.configurations[0].knownCompilers = savedKnownCompilers;
this.propertiesFile = vscode.Uri.file(path.join(this.configFolder, "c_cpp_properties.json"));
} catch (err) {
vscode.window.showErrorMessage(`Failed to create "${this.configFolder}": ${err.message}`);
}
}
return;
}
private parsePropertiesFile(handleSquiggles: boolean): boolean {
let success: boolean = true;
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.
}
// Replace all \<escape character> with \\<character>.
// Otherwise, the JSON.parse result will have the \<escape character> missing.
readResults = readResults.replace(/\\/g, '\\\\');
readResults = readResults.replace(/\\\\"/g, '\\"'); // Need to revert the change to \".
if (handleSquiggles) {
// Replace all \<escape character> with \\<character>, except for \"
// Otherwise, the JSON.parse result will have the \<escape character> missing.
readResults = util.escapeForSquiggles(readResults);
}
// Try to use the same configuration as before the change.
let newJson: ConfigurationJson = JSON.parse(readResults);
if (!newJson || !newJson.configurations || newJson.configurations.length === 0) {
@@ -692,31 +826,198 @@ export class CppProperties {
if (dirty) {
try {
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
this.writeToJson();
} catch (err) {
// Ignore write errors, the file may be under source control. Updated settings will only be modified in memory.
vscode.window.showWarningMessage(`Attempt to update "${this.propertiesFile.fsPath}" failed (do you have write access?)`);
success = false;
}
}
this.handleSquiggles();
} catch (err) {
vscode.window.showErrorMessage(`Failed to parse "${this.propertiesFile.fsPath}": ${err.message}`);
throw err;
success = false;
}
if (handleSquiggles && success) {
this.handleSquiggles();
}
return success;
}
private resolvePath(path: string, isWindows: boolean): string {
if (!path || path === "${default}") {
return "";
}
let result: string = "";
// first resolve variables
result = util.resolveVariables(path, this.ExtendedEnvironment);
if (result.includes("${workspaceFolder}")) {
result = result.replace("${workspaceFolder}", this.rootUri.fsPath);
}
if (result.includes("${workspaceRoot}")) {
result = result.replace("${workspaceRoot}", this.rootUri.fsPath);
}
if (result.includes("${vcpkgRoot}") && util.getVcpkgRoot()) {
result = result.replace("${vcpkgRoot}", util.getVcpkgRoot());
}
if (result.includes("*")) {
result = result.replace(/\*/g, "");
}
// resolve WSL paths
if (isWindows && result.startsWith("/")) {
const mntStr: string = "/mnt/";
if (result.length > "/mnt/c/".length && result.substr(0, mntStr.length) === mntStr) {
result = result.substr(mntStr.length);
result = result.substr(0, 1) + ":" + result.substr(1);
} else if (this.rootfs && this.rootfs.length > 0) {
result = this.rootfs + result.substr(1);
// TODO: Handle WSL symlinks.
}
}
return result;
}
private getErrorsForConfigUI(): ConfigurationErrors {
let errors: ConfigurationErrors = {};
const isWindows: boolean = os.platform() === 'win32';
// Validate compilerPath
let resolvedCompilerPath: string = this.resolvePath(this.CurrentConfiguration.compilerPath, isWindows);
let compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(resolvedCompilerPath);
if (resolvedCompilerPath &&
// Don't error cl.exe paths because it could be for an older preview build.
!(isWindows && compilerPathAndArgs.compilerPath.endsWith("cl.exe"))) {
resolvedCompilerPath = resolvedCompilerPath.trim();
// Error when the compiler's path has spaces without quotes but args are used.
// Except, exclude cl.exe paths because it could be for an older preview build.
let compilerPathNeedsQuotes: boolean =
compilerPathAndArgs.additionalArgs &&
!resolvedCompilerPath.startsWith('"') &&
compilerPathAndArgs.compilerPath.includes(" ");
let compilerPathErrors: string[] = [];
if (compilerPathNeedsQuotes) {
compilerPathErrors.push(`Compiler path with spaces and arguments is missing double quotes " around the path.`);
}
// Get compiler path without arguments before checking if it exists
resolvedCompilerPath = compilerPathAndArgs.compilerPath;
let pathExists: boolean = true;
let existsWithExeAdded: (path: string) => boolean = (path: string) => {
return isWindows && !path.startsWith("/") && fs.existsSync(path + ".exe");
};
if (!fs.existsSync(resolvedCompilerPath)) {
if (existsWithExeAdded(resolvedCompilerPath)) {
resolvedCompilerPath += ".exe";
} else {
// Check again for a relative path.
const relativePath: string = this.rootUri.fsPath + path.sep + resolvedCompilerPath;
if (!fs.existsSync(relativePath)) {
if (existsWithExeAdded(resolvedCompilerPath)) {
resolvedCompilerPath += ".exe";
} else {
pathExists = false;
}
} else {
resolvedCompilerPath = relativePath;
}
}
}
if (!pathExists) {
let message: string = `Cannot find: ${resolvedCompilerPath}`;
compilerPathErrors.push(message);
} else if (!util.checkFileExistsSync(resolvedCompilerPath)) {
let message: string = `Path is not a file: ${resolvedCompilerPath}`;
compilerPathErrors.push(message);
}
if (compilerPathErrors.length > 0) {
errors.compilerPath = compilerPathErrors.join('\n');
}
}
// Validate includePath
let includePathErrors: string[] = [];
if (this.CurrentConfiguration.includePath) {
for (let includePath of this.CurrentConfiguration.includePath) {
let pathExists: boolean = true;
let resolvedIncludePath: string = this.resolvePath(includePath, isWindows);
if (!resolvedIncludePath) {
continue;
}
// Check if resolved path exists
if (!fs.existsSync(resolvedIncludePath)) {
// Check for relative path if resolved path does not exists
const relativePath: string = this.rootUri.fsPath + path.sep + resolvedIncludePath;
if (!fs.existsSync(relativePath)) {
pathExists = false;
} else {
resolvedIncludePath = relativePath;
}
}
if (!pathExists) {
let message: string = `Cannot find: ${resolvedIncludePath}`;
includePathErrors.push(message);
continue;
}
// Check if path is a directory
if (!util.checkDirectoryExistsSync(resolvedIncludePath)) {
let message: string = `Path is not a directory: ${resolvedIncludePath}`;
includePathErrors.push(message);
}
}
if (includePathErrors.length > 0) {
errors.includePath = includePathErrors.join('\n');
}
}
// Validate intelliSenseMode
if (isWindows && !this.isCompilerIntelliSenseModeCompatible()) {
errors.intelliSenseMode = `IntelliSense mode ${this.CurrentConfiguration.intelliSenseMode} is incompatible with compiler path.`;
}
return errors;
}
private handleSquiggles(): void {
if (!this.propertiesFile) {
return;
}
if (this.configurationJson.enableConfigurationSquiggles === false) {
this.diagnosticCollection.clear();
return;
}
const settings: CppSettings = new CppSettings(this.rootUri);
if (settings.defaultEnableConfigurationSquiggles === false) {
this.diagnosticCollection.clear();
return;
}
vscode.workspace.openTextDocument(this.propertiesFile).then((document: vscode.TextDocument) => {
let diagnostics: vscode.Diagnostic[] = new Array<vscode.Diagnostic>();
// Get the text of the current configuration.
let curText: string = document.getText();
let curTextStartOffset: number = 0;
const configStart: number = curText.search(new RegExp(`{\\s*"name"\\s*:\\s*"${this.CurrentConfiguration.name}"`));
if (!this.CurrentConfiguration.name) {
return;
}
const configStart: number = curText.search(new RegExp(`{\\s*"name"\\s*:\\s*"${escapeStringRegExp(this.CurrentConfiguration.name)}"`));
if (configStart === -1) {
telemetry.logLanguageServerEvent("ConfigSquiggles", { "error": "config name not first" });
return;
@@ -736,21 +1037,46 @@ export class CppProperties {
}
curText = curText.substr(0, nextNameStart2);
}
if (this.prevSquiggleMetrics[this.CurrentConfiguration.name] === undefined) {
this.prevSquiggleMetrics[this.CurrentConfiguration.name] = { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0, CompilerPathMissingQuotes: 0, CompilerModeMismatch: 0 };
}
let newSquiggleMetrics: { [key: string]: number } = { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0, CompilerPathMissingQuotes: 0, CompilerModeMismatch: 0 };
const isWindows: boolean = os.platform() === 'win32';
// TODO: Add other squiggles.
// Check if intelliSenseMode and compilerPath are compatible
if (isWindows) {
// cl.exe is only available on Windows
const intelliSenseModeStart: number = curText.search(/\s*\"intelliSenseMode\"\s*:\s*\"/);
if (intelliSenseModeStart !== -1) {
const intelliSenseModeValueStart: number = curText.indexOf('"', curText.indexOf(":", intelliSenseModeStart));
const intelliSenseModeValueEnd: number = intelliSenseModeStart === -1 ? -1 : curText.indexOf('"', intelliSenseModeValueStart + 1) + 1;
if (!this.isCompilerIntelliSenseModeCompatible()) {
let message: string = `intelliSenseMode ${this.CurrentConfiguration.intelliSenseMode} is incompatible with compilerPath.`;
let diagnostic: vscode.Diagnostic = new vscode.Diagnostic(
new vscode.Range(document.positionAt(curTextStartOffset + intelliSenseModeValueStart),
document.positionAt(curTextStartOffset + intelliSenseModeValueEnd)),
message, vscode.DiagnosticSeverity.Warning);
diagnostics.push(diagnostic);
newSquiggleMetrics.CompilerModeMismatch++;
}
}
}
// Check for path-related squiggles.
let paths: Set<string> = new Set<string>();
for (let pathArray of [ (this.CurrentConfiguration.browse ? this.CurrentConfiguration.browse.path : undefined),
this.CurrentConfiguration.includePath, this.CurrentConfiguration.macFrameworkPath, this.CurrentConfiguration.forcedInclude ] ) {
if (pathArray) {
for (let curPath of pathArray) {
paths.add(`"${curPath}"`);
paths.add(`${curPath}`);
}
}
}
if (this.CurrentConfiguration.compileCommands) {
paths.add(`"${this.CurrentConfiguration.compileCommands}"`);
paths.add(`${this.CurrentConfiguration.compileCommands}`);
}
if (this.CurrentConfiguration.compilerPath) {
@@ -766,58 +1092,34 @@ export class CppProperties {
const compilerPathStart: number = curText.search(/\s*\"compilerPath\"\s*:\s*\"/);
const compilerPathEnd: number = compilerPathStart === -1 ? -1 : curText.indexOf('"', curText.indexOf('"', curText.indexOf(":", compilerPathStart)) + 1) + 1;
if (this.prevSquiggleMetrics[this.CurrentConfiguration.name] === undefined) {
this.prevSquiggleMetrics[this.CurrentConfiguration.name] = { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0 };
}
let newSquiggleMetrics: { [key: string]: number } = { PathNonExistent: 0, PathNotAFile: 0, PathNotADirectory: 0 };
const isWindows: boolean = os.platform() === 'win32';
for (let curPath of paths) {
const isCompilerPath: boolean = curPath === this.CurrentConfiguration.compilerPath;
let resolvedPath: string = isCompilerPath ? curPath : curPath.substr(1, curPath.length - 2); // Remove the surrounding quotes.
// Resolve special path cases.
if (resolvedPath === "${default}") {
if (curPath === "${default}") {
// TODO: Add squiggles for when the C_Cpp.default.* paths are invalid.
continue;
}
resolvedPath = util.resolveVariables(resolvedPath, this.ExtendedEnvironment);
if (resolvedPath.includes("${workspaceFolder}")) {
resolvedPath = resolvedPath.replace("${workspaceFolder}", this.rootUri.fsPath);
}
if (resolvedPath.includes("${workspaceRoot}")) {
resolvedPath = resolvedPath.replace("${workspaceRoot}", this.rootUri.fsPath);
}
if (resolvedPath.includes("${vcpkgRoot}")) {
resolvedPath = resolvedPath.replace("${vcpkgRoot}", util.getVcpkgRoot());
}
if (resolvedPath.includes("*")) {
resolvedPath = resolvedPath.replace(/\*/g, "");
let resolvedPath: string = this.resolvePath(curPath, isWindows);
if (!resolvedPath) {
continue;
}
// TODO: Invalid paths created from environment variables are not detected.
// Handle WSL paths.
const isWSL: boolean = isWindows && resolvedPath.startsWith("/");
if (isWSL) {
const mntStr: string = "/mnt/";
if (resolvedPath.length > "/mnt/c/".length && resolvedPath.substr(0, mntStr.length) === mntStr) {
resolvedPath = resolvedPath.substr(mntStr.length);
resolvedPath = resolvedPath.substr(0, 1) + ":" + resolvedPath.substr(1);
} else if (this.rootfs && this.rootfs.length > 0) {
resolvedPath = this.rootfs + resolvedPath.substr(1);
// TODO: Handle WSL symlinks.
}
}
let compilerPathNeedsQuotes: boolean = false;
if (isCompilerPath) {
resolvedPath = resolvedPath.trim();
let compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(resolvedPath);
if (isWindows && compilerPathAndArgs.compilerPath.endsWith("cl.exe")) {
continue; // Don't squiggle invalid cl.exe paths because it could be for an older preview build.
}
// Squiggle when the compiler's path has spaces without quotes but args are used.
compilerPathNeedsQuotes = compilerPathAndArgs.additionalArgs && !resolvedPath.startsWith('"') && compilerPathAndArgs.compilerPath.includes(" ");
resolvedPath = compilerPathAndArgs.compilerPath;
curPath = curPath.replace(/\"/g, `\\"`);
}
const isWSL: boolean = isWindows && resolvedPath.startsWith("/");
let pathExists: boolean = true;
let existsWithExeAdded: (path: string) => boolean = (path: string) => {
return isCompilerPath && isWindows && !isWSL && fs.existsSync(path + ".exe");
@@ -848,34 +1150,55 @@ export class CppProperties {
}
// Iterate through the text and apply squiggles.
for (let curOffset: number = curText.indexOf(curPath); curOffset !== -1; curOffset = curText.indexOf(curPath, curOffset + curPath.length)) {
let message: string;
if (!pathExists) {
message = `Cannot find "${resolvedPath}".`;
newSquiggleMetrics.PathNonExistent++;
} else {
// Check for file versus path mismatches.
if ((curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd) ||
(curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd) ||
(curOffset >= compilerPathStart && curOffset <= compilerPathEnd)) {
if (util.checkFileExistsSync(resolvedPath)) {
continue;
}
message = `Path is not a file: "${resolvedPath}".`;
newSquiggleMetrics.PathNotAFile++;
// Escape the path string for literal use in a regular expression
// Need to escape any quotes to match the original text
let escapedPath: string = curPath.replace(/\"/g, '\\\"');
escapedPath = escapedPath.replace(/[-\"\/\\^$*+?.()|[\]{}]/g, '\\$&');
// Create a pattern to search for the path with either a quote or semicolon immediately before and after,
// and extend that pattern to the next quote before and next quote after it.
let pattern: RegExp = new RegExp(`"[^"]*?(?<="|;)${escapedPath}(?="|;).*?"`);
let matches: string[] = curText.match(pattern);
if (matches) {
let curOffset: number = 0;
let endOffset: number = 0;
for (let curMatch of matches) {
curOffset = curText.substr(endOffset).search(pattern) + endOffset;
endOffset = curOffset + curMatch.length;
let message: string;
if (!pathExists) {
message = `Cannot find "${resolvedPath}".`;
newSquiggleMetrics.PathNonExistent++;
} else {
if (util.checkDirectoryExistsSync(resolvedPath)) {
continue;
// Check for file versus path mismatches.
if ((curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd) ||
(curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd) ||
(curOffset >= compilerPathStart && curOffset <= compilerPathEnd)) {
if (compilerPathNeedsQuotes) {
message = `Compiler path with spaces and arguments is missing \\" around the path.`;
newSquiggleMetrics.CompilerPathMissingQuotes++;
} else {
if (util.checkFileExistsSync(resolvedPath)) {
continue;
}
message = `Path is not a file: "${resolvedPath}".`;
newSquiggleMetrics.PathNotAFile++;
}
} else {
if (util.checkDirectoryExistsSync(resolvedPath)) {
continue;
}
message = `Path is not a directory: "${resolvedPath}".`;
newSquiggleMetrics.PathNotADirectory++;
}
message = `Path is not a directory: "${resolvedPath}".`;
newSquiggleMetrics.PathNotADirectory++;
}
let diagnostic: vscode.Diagnostic = new vscode.Diagnostic(
new vscode.Range(document.positionAt(curTextStartOffset + curOffset),
document.positionAt(curTextStartOffset + endOffset)),
message, vscode.DiagnosticSeverity.Warning);
diagnostics.push(diagnostic);
}
let diagnostic: vscode.Diagnostic = new vscode.Diagnostic(
new vscode.Range(document.positionAt(curTextStartOffset + curOffset),
document.positionAt(curTextStartOffset + curOffset + curPath.length + (!isCompilerPath ? -1 : 0))),
message, vscode.DiagnosticSeverity.Warning);
diagnostics.push(diagnostic);
}
}
if (diagnostics.length !== 0) {
@@ -895,6 +1218,9 @@ export class CppProperties {
if (newSquiggleMetrics.PathNotADirectory !== this.prevSquiggleMetrics[this.CurrentConfiguration.name].PathNotADirectory) {
changedSquiggleMetrics.PathNotADirectory = newSquiggleMetrics.PathNotADirectory;
}
if (newSquiggleMetrics.CompilerPathMissingQuotes !== this.prevSquiggleMetrics[this.CurrentConfiguration.name].CompilerPathMissingQuotes) {
changedSquiggleMetrics.CompilerPathMissingQuotes = newSquiggleMetrics.CompilerPathMissingQuotes;
}
if (Object.keys(changedSquiggleMetrics).length > 0) {
telemetry.logLanguageServerEvent("ConfigSquiggles", null, changedSquiggleMetrics);
}
@@ -948,6 +1274,11 @@ export class CppProperties {
}
}
private writeToJson(): void {
console.assert(this.propertiesFile);
fs.writeFileSync(this.propertiesFile.fsPath, JSON.stringify(this.configurationJson, null, 4));
}
public checkCppProperties(): void {
// Check for change properties in case of file watcher failure.
let propertiesFile: string = path.join(this.configFolder, "c_cpp_properties.json");
+80 -19
View File
@@ -42,6 +42,7 @@ let buildInfoCache: BuildInfo | null = null;
const taskSourceStr: string = "C/C++";
const cppInstallVsixStr: string = 'C/C++: Install vsix -- ';
let taskProvider: vscode.Disposable;
const intelliSenseDisabledError: string = "Do not activate the extension when IntelliSense is disabled.";
/**
* activate: set up the extension for language services
@@ -71,7 +72,7 @@ export function activate(activationEventOccurred: boolean): void {
taskProvider = vscode.tasks.registerTaskProvider(taskSourceStr, {
provideTasks: () => {
return getBuildTasks();
return getBuildTasks(false);
},
resolveTask(task: vscode.Task): vscode.Task {
// Currently cannot implement because VS Code does not call this. Can implement custom output file directory when enabled.
@@ -114,7 +115,7 @@ export interface BuildTaskDefinition extends vscode.TaskDefinition {
/**
* Generate tasks to build the current file based on the user's detected compilers, the user's compilerPath setting, and the current file's extension.
*/
export async function getBuildTasks(): Promise<vscode.Task[]> {
export async function getBuildTasks(returnComplerPath: boolean): Promise<vscode.Task[]> {
const editor: vscode.TextEditor = vscode.window.activeTextEditor;
if (!editor) {
return [];
@@ -150,7 +151,15 @@ export async function getBuildTasks(): Promise<vscode.Task[]> {
// for the active file, remove duplicate compiler names, then finally add the user's compilerPath setting.
let compilerPaths: string[];
const isWindows: boolean = os.platform() === 'win32';
const activeClient: Client = getActiveClient();
let activeClient: Client;
try {
activeClient = getActiveClient();
} catch (e) {
if (!e || e.message !== intelliSenseDisabledError) {
console.error("Unknown error calling getActiveClient().");
}
return []; // Language service features may be disabled.
}
let userCompilerPath: string = await activeClient.getCompilerPath();
if (userCompilerPath) {
userCompilerPath = userCompilerPath.trim();
@@ -171,8 +180,13 @@ export async function getBuildTasks(): Promise<vscode.Task[]> {
let map: Map<string, string> = new Map<string, string>();
const insertOrAssignEntry: (compilerPath: string) => void = (compilerPath: string): void => {
const basename: string = path.basename(compilerPath);
//map.has(basename) ? map.basename] = compilerPath :
let basename: string = compilerPath;
if (compilerPath === userCompilerPath) {
// Make sure the compiler args are not part of the basename.
const compilerPathAndArgs: util.CompilerPathAndArgs = util.extractCompilerPathAndArgs(compilerPath);
basename = compilerPathAndArgs.compilerPath;
}
basename = path.basename(basename);
map.set(basename, compilerPath);
};
compilerPaths.forEach(insertOrAssignEntry);
@@ -243,6 +257,10 @@ export async function getBuildTasks(): Promise<vscode.Task[]> {
task.definition = kind; // The constructor for vscode.Task will eat the definition. Reset it by reassigning.
task.group = vscode.TaskGroup.Build;
if (!returnComplerPath) {
delete task.definition.compilerPath;
}
return task;
});
}
@@ -271,7 +289,7 @@ function onActivationEvent(): void {
function realActivation(): void {
if (new CppSettings().intelliSenseEngine === "Disabled") {
throw new Error("Do not activate the extension when IntelliSense is disabled.");
throw new Error(intelliSenseDisabledError);
} else {
console.log("activating extension");
let checkForConflictingExtensions: PersistentState<boolean> = new PersistentState<boolean>("CPP." + util.packageJson.version + ".checkForConflictingExtensions", true);
@@ -412,7 +430,15 @@ function onInterval(): void {
* Install a VSIX package. This helper function will exist until VSCode offers a command to do so.
* @param updateChannel The user's updateChannel setting.
*/
function installVsix(vsixLocation: string, updateChannel: string): Promise<void> {
function installVsix(vsixLocation: string): Thenable<void> {
let userVersion: PackageVersion = new PackageVersion(vscode.version);
// 1.33.0 introduces workbench.extensions.installExtension. 1.32.3 was immediately prior.
let lastVersionWithoutInstallExtensionCommand: PackageVersion = new PackageVersion('1.32.3');
if (userVersion.isGreaterThan(lastVersionWithoutInstallExtensionCommand)) {
return vscode.commands.executeCommand('workbench.extensions.installExtension', vscode.Uri.file(vsixLocation));
}
// Get the path to the VSCode command -- replace logic later when VSCode allows calling of
// workbench.extensions.action.installVSIX from TypeScript w/o instead popping up a file dialog
return PlatformInformation.GetPlatformInformation().then((platformInfo) => {
@@ -446,21 +472,20 @@ function installVsix(vsixLocation: string, updateChannel: string): Promise<void>
return Promise.reject(new Error('Failed to find VS Code script'));
}
// 1.28.0 changes the CLI for making installations
let userVersion: PackageVersion = new PackageVersion(vscode.version);
let breakingVersion: PackageVersion = new PackageVersion('1.28.0');
if (userVersion.isGreaterThan(breakingVersion, 'insider')) {
// 1.28.0 changes the CLI for making installations. 1.27.2 was immediately prior.
let oldVersion: PackageVersion = new PackageVersion('1.27.2');
if (userVersion.isGreaterThan(oldVersion)) {
return new Promise<void>((resolve, reject) => {
let process: ChildProcess;
try {
process = spawn(vsCodeScriptPath, ['--install-extension', vsixLocation, '--force']);
// Timeout the process if no response is sent back. Ensures this Promise resolves/rejects
const timer: NodeJS.Timer = setTimeout(() => {
process.kill();
reject(new Error('Failed to receive response from VS Code script process for installation within 30s.'));
}, 30000);
process.on('exit', (code: number) => {
clearInterval(timer);
if (code !== 0) {
@@ -554,7 +579,7 @@ async function suggestInsidersChannel(): Promise<void> {
}
}
function applyUpdate(buildInfo: BuildInfo, updateChannel: string): Promise<void> {
function applyUpdate(buildInfo: BuildInfo): Promise<void> {
return new Promise<void>((resolve, reject) => {
tmp.file({postfix: '.vsix'}, async (err, vsixPath, fd, cleanupCallback) => {
if (err) {
@@ -592,7 +617,7 @@ function applyUpdate(buildInfo: BuildInfo, updateChannel: string): Promise<void>
break;
}
try {
await installVsix(vsixPath, updateChannel);
await installVsix(vsixPath);
} catch (error) {
reject(error);
return;
@@ -634,7 +659,7 @@ async function checkAndApplyUpdate(updateChannel: string): Promise<void> {
if (!buildInfo) {
return; // No need to update.
}
await applyUpdate(buildInfo, updateChannel);
await applyUpdate(buildInfo);
}
/*********************************************
@@ -655,9 +680,12 @@ export function registerCommands(): void {
disposables.push(vscode.commands.registerCommand('C_Cpp.ResetDatabase', onResetDatabase));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationSelect', onSelectConfiguration));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationProviderSelect', onSelectConfigurationProvider));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEditJSON', onEditConfigurationJSON));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEditUI', onEditConfigurationUI));
disposables.push(vscode.commands.registerCommand('C_Cpp.ConfigurationEdit', onEditConfiguration));
disposables.push(vscode.commands.registerCommand('C_Cpp.AddToIncludePath', onAddToIncludePath));
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleErrorSquiggles', onToggleSquiggles));
disposables.push(vscode.commands.registerCommand('C_Cpp.EnableErrorSquiggles', onEnableSquiggles));
disposables.push(vscode.commands.registerCommand('C_Cpp.DisableErrorSquiggles', onDisableSquiggles));
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleIncludeFallback', onToggleIncludeFallback));
disposables.push(vscode.commands.registerCommand('C_Cpp.ToggleDimInactiveRegions', onToggleDimInactiveRegions));
disposables.push(vscode.commands.registerCommand('C_Cpp.ShowReleaseNotes', onShowReleaseNotes));
@@ -665,6 +693,7 @@ export function registerCommands(): void {
disposables.push(vscode.commands.registerCommand('C_Cpp.ResumeParsing', onResumeParsing));
disposables.push(vscode.commands.registerCommand('C_Cpp.ShowParsingCommands', onShowParsingCommands));
disposables.push(vscode.commands.registerCommand('C_Cpp.TakeSurvey', onTakeSurvey));
disposables.push(vscode.commands.registerCommand('C_Cpp.LogDiagnostics', onLogDiagnostics));
disposables.push(vscode.commands.registerCommand('cpptools.activeConfigName', onGetActiveConfigName));
getTemporaryCommandRegistrarInstance().executeDelayedCommands();
}
@@ -780,6 +809,26 @@ function onSelectConfigurationProvider(): void {
}
}
function onEditConfigurationJSON(): void {
onActivationEvent();
telemetry.logLanguageServerEvent("SettingsCommand", { "palette": "json" }, null);
if (!isFolderOpen()) {
vscode.window.showInformationMessage('Open a folder first to edit configurations');
} else {
selectClient().then(client => client.handleConfigurationEditJSONCommand(), rejected => {});
}
}
function onEditConfigurationUI(): void {
onActivationEvent();
telemetry.logLanguageServerEvent("SettingsCommand", { "palette": "ui" }, null);
if (!isFolderOpen()) {
vscode.window.showInformationMessage('Open a folder first to edit configurations');
} else {
selectClient().then(client => client.handleConfigurationEditUICommand(), rejected => {});
}
}
function onEditConfiguration(): void {
onActivationEvent();
if (!isFolderOpen()) {
@@ -799,11 +848,18 @@ function onAddToIncludePath(path: string): void {
}
}
function onToggleSquiggles(): void {
function onEnableSquiggles(): void {
onActivationEvent();
// This only applies to the active client.
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
settings.toggleSetting("errorSquiggles", "Enabled", "Disabled");
settings.update<string>("errorSquiggles", "Enabled");
}
function onDisableSquiggles(): void {
onActivationEvent();
// This only applies to the active client.
let settings: CppSettings = new CppSettings(clients.ActiveClient.RootUri);
settings.update<string>("errorSquiggles", "Disabled");
}
function onToggleIncludeFallback(): void {
@@ -851,6 +907,11 @@ function onGetActiveConfigName(): Thenable<string> {
return clients.ActiveClient.getCurrentConfigName();
}
function onLogDiagnostics(): void {
onActivationEvent();
clients.ActiveClient.logDiagnostics();
}
function reportMacCrashes(): void {
if (process.platform === "darwin") {
prevCrashFile = "";
@@ -12,19 +12,24 @@ class PersistentStateBase<T> {
private key: string;
private defaultvalue: T;
private state: vscode.Memento;
private curvalue: T;
constructor(key: string, defaultValue: T, state: vscode.Memento) {
this.key = key;
this.defaultvalue = defaultValue;
this.state = state;
this.curvalue = defaultValue;
}
public get Value(): T {
return this.state.get<T>(this.key, this.defaultvalue);
return this.state ? this.state.get<T>(this.key, this.defaultvalue) : this.curvalue;
}
public set Value(newValue: T) {
this.state.update(this.key, newValue);
if (this.state) {
this.state.update(this.key, newValue);
}
this.curvalue = newValue;
}
public get DefaultValue(): T {
@@ -35,13 +40,13 @@ class PersistentStateBase<T> {
// Abstraction for global state that persists across activations but is not present in a settings file
export class PersistentState<T> extends PersistentStateBase<T> {
constructor(key: string, defaultValue: T) {
super(key, defaultValue, util.extensionContext.globalState);
super(key, defaultValue, util.extensionContext ? util.extensionContext.globalState : null);
}
}
export class PersistentWorkspaceState<T> extends PersistentStateBase<T> {
constructor(key: string, defaultValue: T) {
super(key, defaultValue, util.extensionContext.workspaceState);
super(key, defaultValue, util.extensionContext ? util.extensionContext.workspaceState : null);
}
}
+15 -1
View File
@@ -4,6 +4,7 @@
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as path from 'path';
import { Middleware } from 'vscode-languageclient';
import { ClientCollection } from './clientCollection';
import { Client } from './client';
@@ -23,6 +24,14 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid
didOpen: (document, sendMessage) => {
if (clients.checkOwnership(me, document)) {
me.TrackedDocuments.add(document);
// Work around vscode treating ".C" as c, by adding this file name to file associations as cpp
if (document.uri.path.endsWith(".C")) {
let fileName: string = path.basename(document.uri.fsPath);
let mappingString: string = fileName + "@" + document.uri.fsPath;
me.addFileAssociations(mappingString, false);
}
me.provideCustomConfiguration(document).then(() => {
sendMessage(document);
}, () => {
@@ -49,7 +58,12 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid
provideCompletionItem: invoke4,
resolveCompletionItem: invoke2,
provideHover: invoke3,
provideHover: (document, position, token, next: (document, position, token) => any) => {
if (clients.checkOwnership(me, document)) {
return me.requestWhenReady(() => next(document, position, token));
}
return null;
},
provideSignatureHelp: invoke3,
provideDefinition: invoke3,
provideReferences: invoke4,
+3 -1
View File
@@ -72,6 +72,7 @@ export class CppSettings extends Settings {
public get defaultDatabaseFilename(): string { return super.Section.get<string>("default.browse.databaseFilename"); }
public get defaultLimitSymbolsToIncludedHeaders(): boolean { return super.Section.get<boolean>("default.browse.limitSymbolsToIncludedHeaders"); }
public get defaultSystemIncludePath(): string[] { return super.Section.get<string[]>("default.systemIncludePath"); }
public get defaultEnableConfigurationSquiggles(): boolean { return super.Section.get<boolean>("default.enableConfigurationSquiggles"); }
public toggleSetting(name: string, value1: string, value2: string): void {
let value: string = super.Section.get<string>(name);
@@ -92,10 +93,11 @@ export class OtherSettings {
this.resource = resource;
}
public get editorTabSize(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("editor", this.resource).get("tabSize"); }
public get editorTabSize(): number { return vscode.workspace.getConfiguration("editor", this.resource).get<number>("tabSize"); }
public get filesAssociations(): any { return vscode.workspace.getConfiguration("files", null).get("associations"); }
public get filesExclude(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("files", this.resource).get("exclude"); }
public get searchExclude(): vscode.WorkspaceConfiguration { return vscode.workspace.getConfiguration("search", this.resource).get("exclude"); }
public get settingsEditor(): string { return vscode.workspace.getConfiguration("workbench.settings").get<string>("editor"); }
public set filesAssociations(value: any) {
vscode.workspace.getConfiguration("files", null).update("associations", value, vscode.ConfigurationTarget.Workspace);
@@ -0,0 +1,223 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as path from 'path';
import * as fs from 'fs';
import * as vscode from 'vscode';
import * as util from '../common';
import * as config from './configurations';
// TODO: share ElementId between SettingsPanel and SettingsApp. Investigate why SettingsApp cannot import/export
const elementId: { [key: string]: string } = {
activeConfig: "activeConfig",
compilerPath: "compilerPath",
intelliSenseMode: "intelliSenseMode",
includePath: "includePath",
defines: "defines",
cStandard: "cStandard",
cppStandard: "cppStandard"
};
export class SettingsPanel {
private configValues: config.Configuration;
private isIntelliSenseModeDefined: boolean = false;
private settingsPanelActivated = new vscode.EventEmitter<void>();
private configValuesChanged = new vscode.EventEmitter<void>();
private panel: vscode.WebviewPanel;
private disposable: vscode.Disposable = undefined;
private disposablesPanel: vscode.Disposable = undefined;
private static readonly viewType: string = 'settingsPanel';
private static readonly title: string = 'C/C++ Configurations';
constructor() {
this.configValues = { name: undefined };
this.disposable = vscode.Disposable.from(
this.settingsPanelActivated,
this.configValuesChanged
);
}
public createOrShow(activeConfiguration: config.Configuration, errors: config.ConfigurationErrors): void {
const column: vscode.ViewColumn = vscode.window.activeTextEditor
? vscode.window.activeTextEditor.viewColumn
: undefined;
// Show existing panel
if (this.panel) {
this.panel.reveal(column, false);
return;
}
// Create new panel
this.panel = vscode.window.createWebviewPanel(
SettingsPanel.viewType,
SettingsPanel.title,
column || vscode.ViewColumn.One,
{
enableCommandUris: true,
enableScripts: true,
// Restrict the webview to only loading content from these directories
localResourceRoots: [
vscode.Uri.file(util.extensionPath),
vscode.Uri.file(path.join(util.extensionPath, 'ui')),
vscode.Uri.file(path.join(util.extensionPath, 'out', 'ui'))]
}
);
this.panel.iconPath = vscode.Uri.file(util.getExtensionFilePath("LanguageCCPP_color_128x.png"));
this.disposablesPanel = vscode.Disposable.from(
this.panel,
this.panel.onDidDispose(this.onPanelDisposed, this),
this.panel.onDidChangeViewState(this.onViewStateChanged, this),
this.panel.webview.onDidReceiveMessage(this.onMessageReceived, this),
vscode.window.onDidChangeWindowState(this.onWindowStateChanged, this)
);
this.panel.webview.html = this.getHtml();
this.updateWebview(activeConfiguration, errors);
}
public get SettingsPanelActivated(): vscode.Event<void> {
return this.settingsPanelActivated.event;
}
public get ConfigValuesChanged(): vscode.Event<void> {
return this.configValuesChanged.event;
}
public getLastValuesFromConfigUI(): config.Configuration {
return this.configValues;
}
public updateConfigUI(configuration: config.Configuration, errors: config.ConfigurationErrors): void {
if (this.panel) {
this.updateWebview(configuration, errors);
}
}
public updateErrors(errors: config.ConfigurationErrors): void {
if (this.panel) {
this.panel.webview.postMessage({ command: 'updateErrors', errors: errors});
}
}
public dispose(): void {
// Clean up resources
this.panel.dispose();
if (this.disposable) {
this.disposable.dispose();
}
if (this.disposablesPanel) {
this.disposablesPanel.dispose();
}
}
private onPanelDisposed(): void {
if (this.disposablesPanel) {
this.disposablesPanel.dispose();
this.panel = undefined;
}
}
private updateWebview(configuration: config.Configuration, errors: config.ConfigurationErrors): void {
this.configValues = Object.assign({}, configuration); // Copy configuration values
this.isIntelliSenseModeDefined = (this.configValues.intelliSenseMode !== undefined);
if (this.panel) {
// Send a message to the webview to update the values and errors
this.panel.webview.postMessage({ command: 'updateConfig', config: this.configValues});
this.panel.webview.postMessage({ command: 'updateErrors', errors: errors});
}
}
private onViewStateChanged(e: vscode.WebviewPanelOnDidChangeViewStateEvent): void {
if (e.webviewPanel.active) {
this.settingsPanelActivated.fire();
}
}
private onWindowStateChanged(e: vscode.WindowState): void {
if (e.focused) {
this.settingsPanelActivated.fire();
}
}
private onMessageReceived(message: any): void {
if (message === null) {
return;
}
switch (message.command) {
case 'change':
this.updateConfig(message);
}
}
private updateConfig(message: any): void {
let entries: string[];
switch (message.key) {
case elementId.activeConfig:
this.configValues.name = message.value;
break;
case elementId.compilerPath:
this.configValues.compilerPath = message.value;
break;
case elementId.includePath:
entries = message.value.split("\n");
this.configValues.includePath = entries.filter(e => e);
break;
case elementId.defines:
entries = message.value.split("\n");
this.configValues.defines = entries.filter(e => e);
break;
case elementId.intelliSenseMode:
if (message.value !== "${default}" || this.isIntelliSenseModeDefined) {
this.configValues.intelliSenseMode = message.value;
} else {
this.configValues.intelliSenseMode = undefined;
}
break;
case elementId.cStandard:
this.configValues.cStandard = message.value;
break;
case elementId.cppStandard:
this.configValues.cppStandard = message.value;
break;
}
this.configValuesChanged.fire();
}
private getHtml(): string {
let content: string | undefined;
content = fs.readFileSync(util.getExtensionFilePath("ui/settings.html")).toString();
content = content.replace(
/{{root}}/g,
vscode.Uri.file(util.extensionPath)
.with({ scheme: 'vscode-resource' })
.toString());
content = content.replace(
/{{nonce}}/g,
this.getNonce());
return content;
}
private getNonce(): string {
let nonce: string;
const possible: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i: number = 0; i < 32; i++) {
nonce += possible.charAt(Math.floor(Math.random() * possible.length));
}
return nonce;
}
}
+2 -1
View File
@@ -171,7 +171,8 @@ export class UI {
for (let i: number = 0; i < configurationNames.length; i++) {
items.push({ label: configurationNames[i], description: "", index: i });
}
items.push({ label: "Edit Configurations...", description: "", index: configurationNames.length });
items.push({ label: "Edit Configurations (UI)", description: "", index: configurationNames.length });
items.push({ label: "Edit Configurations (JSON)", description: "", index: configurationNames.length + 1 });
return vscode.window.showQuickPick(items, options)
.then(selection => (selection) ? selection.index : -1);
+12 -6
View File
@@ -6,6 +6,7 @@
import * as vscode from 'vscode';
import * as LanguageServer from './LanguageServer/extension';
import * as util from './common';
class TemporaryCommandRegistrar {
// Used to save/re-execute commands used before the extension has activated (e.g. delayed by dependency downloading).
@@ -15,14 +16,16 @@ class TemporaryCommandRegistrar {
private isActivationReady: boolean = false;
private commandsToRegister: string[] = [
"C_Cpp.ConfigurationEdit",
"C_Cpp.ConfigurationEditJSON",
"C_Cpp.ConfigurationEditUI",
"C_Cpp.ConfigurationSelect",
"C_Cpp.ConfigurationProviderSelect",
"C_Cpp.SwitchHeaderSource",
"C_Cpp.Navigate",
"C_Cpp.GoToDeclaration",
"C_Cpp.PeekDeclaration",
"C_Cpp.ToggleErrorSquiggles",
"C_Cpp.EnableErrorSquiggles",
"C_Cpp.DisableErrorSquiggles",
"C_Cpp.ToggleIncludeFallback",
"C_Cpp.ToggleDimInactiveRegions",
"C_Cpp.ShowReleaseNotes",
@@ -30,7 +33,8 @@ class TemporaryCommandRegistrar {
"C_Cpp.PauseParsing",
"C_Cpp.ResumeParsing",
"C_Cpp.ShowParsingCommands",
"C_Cpp.TakeSurvey"
"C_Cpp.TakeSurvey",
"C_Cpp.LogDiagnostics"
];
constructor() {
@@ -38,9 +42,11 @@ class TemporaryCommandRegistrar {
this.delayedCommandsToExecute = new Set<string>();
// Add temp commands that invoke the real commands after download/install is complete (preventing an error message)
this.commandsToRegister.forEach(command => {
this.registerTempCommand(command);
});
if (util.extensionContext) {
this.commandsToRegister.forEach(command => {
this.registerTempCommand(command);
});
}
}
public registerTempCommand(command: string): void {
+55 -20
View File
@@ -17,11 +17,19 @@ import * as assert from 'assert';
import * as https from 'https';
import { ClientRequest, OutgoingHttpHeaders } from 'http';
import { getBuildTasks } from './LanguageServer/extension';
import { OtherSettings } from './LanguageServer/settings';
export let extensionPath: string;
export let extensionContext: vscode.ExtensionContext;
export function setExtensionContext(context: vscode.ExtensionContext): void {
extensionContext = context;
extensionPath = extensionContext.extensionPath;
}
export function setExtensionPath(path: string): void {
extensionPath = path;
}
export const failedToParseTasksJson: string = "Failed to parse tasks.json, possibly due to comments or trailing commas.";
// Use this package.json to read values
export const packageJson: any = vscode.extensions.getExtension("ms-vscode.cpptools").packageJSON;
@@ -47,11 +55,13 @@ export function getRawTasksJson(): Promise<any> {
if (!exists) {
return resolve({});
}
const fileContents: Buffer = fs.readFileSync(path);
let fileContents: string = fs.readFileSync(path).toString();
fileContents = fileContents.replace(/^\s*\/\/.*$/gm, ""); // Remove start of line // comments.
let rawTasks: any = {};
try {
rawTasks = JSON.parse(fileContents.toString());
rawTasks = JSON.parse(fileContents);
} catch (error) {
return reject(new Error(failedToParseTasksJson));
}
resolve(rawTasks);
});
@@ -73,16 +83,10 @@ export async function ensureBuildTaskExists(taskName: string): Promise<void> {
return;
}
const buildTasks: vscode.Task[] = await getBuildTasks();
const buildTasks: vscode.Task[] = await getBuildTasks(false);
selectedTask = buildTasks.find(task => task.name === taskName);
console.assert(selectedTask);
let definition: vscode.TaskDefinition = selectedTask.definition as vscode.TaskDefinition;
if (definition && definition.compilerPath) {
// TODO: add desired properties to empty object, don't delete.
delete definition.compilerPath;
}
rawTasksJson.version = "2.0.0";
if (!rawTasksJson.tasks.find(task => { return task.label === selectedTask.definition.label; })) {
@@ -90,7 +94,8 @@ export async function ensureBuildTaskExists(taskName: string): Promise<void> {
}
// TODO: It's dangerous to overwrite this file. We could be wiping out comments.
await writeFileText(getTasksJsonPath(), JSON.stringify(rawTasksJson, null, 2));
let settings: OtherSettings = new OtherSettings();
await writeFileText(getTasksJsonPath(), JSON.stringify(rawTasksJson, null, settings.editorTabSize));
}
export function fileIsCOrCppSource(file: string): boolean {
@@ -106,7 +111,7 @@ export function stringifyPackageJson(packageJson: string): string {
}
export function getExtensionFilePath(extensionfile: string): string {
return path.resolve(extensionContext.extensionPath, extensionfile);
return path.resolve(extensionPath, extensionfile);
}
export function getPackageJsonPath(): string {
@@ -151,8 +156,8 @@ export function getVcpkgRoot(): string {
* For the purposes of this function, a header file has no extension, or an extension that begins with the letter 'h'.
* @param document The document to check.
*/
export function isHeader(document: vscode.TextDocument): boolean {
let ext: string = path.extname(document.uri.fsPath);
export function isHeader(uri: vscode.Uri): boolean {
let ext: string = path.extname(uri.fsPath);
return !ext || ext.startsWith(".h") || ext.startsWith(".H");
}
@@ -195,15 +200,15 @@ let installProgressStr: string = "CPP." + packageJson.version + ".Progress";
let intelliSenseProgressStr: string = "CPP." + packageJson.version + ".IntelliSenseProgress";
export function getProgress(): number {
return extensionContext.globalState.get<number>(installProgressStr, -1);
return extensionContext ? extensionContext.globalState.get<number>(installProgressStr, -1) : -1;
}
export function getIntelliSenseProgress(): number {
return extensionContext.globalState.get<number>(intelliSenseProgressStr, -1);
return extensionContext ? extensionContext.globalState.get<number>(intelliSenseProgressStr, -1) : -1;
}
export function setProgress(progress: number): void {
if (getProgress() < progress) {
if (extensionContext && getProgress() < progress) {
extensionContext.globalState.update(installProgressStr, progress);
let telemetryProperties: { [key: string]: string } = {};
let progressName: string;
@@ -220,7 +225,7 @@ export function setProgress(progress: number): void {
}
export function setIntelliSenseProgress(progress: number): void {
if (getIntelliSenseProgress() < progress) {
if (extensionContext && getIntelliSenseProgress() < progress) {
extensionContext.globalState.update(intelliSenseProgressStr, progress);
let telemetryProperties: { [key: string]: string } = {};
let progressName: string;
@@ -421,7 +426,7 @@ export function touchInstallLockFile(): Promise<void> {
export function touchExtensionFolder(): Promise<void> {
return new Promise<void>((resolve, reject) => {
fs.utimes(path.resolve(extensionContext.extensionPath, ".."), new Date(Date.now()), new Date(Date.now()), (err) => {
fs.utimes(path.resolve(extensionPath, ".."), new Date(Date.now()), new Date(Date.now()), (err) => {
if (err) {
reject(err);
}
@@ -769,7 +774,6 @@ export function extractCompilerPathAndArgs(inputCompilerPath: string): CompilerP
let additionalArgs: string[];
let isWindows: boolean = os.platform() === 'win32';
if (compilerPath) {
compilerPath = compilerPath.trim();
if (compilerPath.startsWith("\"")) {
let endQuote: number = compilerPath.substr(1).search("\"") + 1;
if (endQuote !== -1) {
@@ -801,4 +805,35 @@ export function extractCompilerPathAndArgs(inputCompilerPath: string): CompilerP
}
}
return { compilerPath, additionalArgs };
}
}
export function escapeForSquiggles(s: string): string {
// Replace all \<escape character> with \\<character>, except for \"
// Otherwise, the JSON.parse result will have the \<escape character> missing.
let newResults: string = "";
let lastWasBackslash: Boolean = false;
let lastBackslashWasEscaped: Boolean = false;
for (let i: number = 0; i < s.length; i++) {
if (s[i] === '\\') {
if (lastWasBackslash) {
newResults += "\\";
lastBackslashWasEscaped = !lastBackslashWasEscaped;
} else {
lastBackslashWasEscaped = false;
}
newResults += "\\";
lastWasBackslash = true;
} else {
if (lastWasBackslash && (lastBackslashWasEscaped || (s[i] !== '"'))) {
newResults += "\\";
}
lastWasBackslash = false;
lastBackslashWasEscaped = false;
newResults += s[i];
}
}
if (lastWasBackslash) {
newResults += "\\";
}
return newResults;
}
+10
View File
@@ -3,8 +3,14 @@
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
export enum InstallationType {
Online,
Offline
}
export class InstallationInformation {
stage: string;
type: InstallationType;
hasError: boolean;
telemetryProperties: { [key: string]: string };
@@ -25,4 +31,8 @@ export function getInstallationInformation(): InstallationInformation {
export function setInstallationStage(stage: string): void {
getInstallationInformation().stage = stage;
}
export function setInstallationType(type: InstallationType): void {
getInstallationInformation().type = type;
}
+14 -6
View File
@@ -18,19 +18,19 @@ import { getTemporaryCommandRegistrarInstance, initializeTemporaryCommandRegistr
import { PlatformInformation } from './platform';
import { PackageManager, PackageManagerError, IPackage } from './packageManager';
import { PersistentState } from './LanguageServer/persistentState';
import { getInstallationInformation, InstallationInformation, setInstallationStage } from './installationInformation';
import { getInstallationInformation, InstallationInformation, setInstallationStage, setInstallationType, InstallationType } from './installationInformation';
import { Logger, getOutputChannelLogger, showOutputChannel } from './logger';
import { CppTools1 } from './cppTools1';
const releaseNotesVersion: number = 4;
const releaseNotesVersion: number = 5;
const cppTools: CppTools1 = new CppTools1();
let languageServiceDisabled: boolean = false;
let reloadMessageShown: boolean = false;
let disposables: vscode.Disposable[] = [];
export async function activate(context: vscode.ExtensionContext): Promise<CppToolsApi & CppToolsExtension> {
initializeTemporaryCommandRegistrar();
util.setExtensionContext(context);
initializeTemporaryCommandRegistrar();
Telemetry.activate();
util.setProgress(0);
@@ -87,6 +87,7 @@ async function processRuntimeDependencies(): Promise<void> {
async function offlineInstallation(): Promise<void> {
setInstallationStage('getPlatformInfo');
setInstallationType(InstallationType.Offline);
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
setInstallationStage('makeBinariesExecutable');
@@ -107,6 +108,7 @@ async function offlineInstallation(): Promise<void> {
async function onlineInstallation(): Promise<void> {
setInstallationStage('getPlatformInfo');
setInstallationType(InstallationType.Online);
const info: PlatformInformation = await PlatformInformation.GetPlatformInformation();
await downloadAndInstallPackages(info);
@@ -234,6 +236,7 @@ function sendTelemetry(info: PlatformInformation): boolean {
const success: boolean = !installBlob.hasError;
installBlob.telemetryProperties['success'] = success.toString();
installBlob.telemetryProperties['type'] = installBlob.type === InstallationType.Online ? "online" : "offline";
if (info.distribution) {
installBlob.telemetryProperties['linuxDistroName'] = info.distribution.name;
@@ -244,7 +247,9 @@ function sendTelemetry(info: PlatformInformation): boolean {
util.setProgress(util.getProgressInstallSuccess());
let versionShown: PersistentState<number> = new PersistentState<number>("CPP.ReleaseNotesVersion", -1);
if (versionShown.Value < releaseNotesVersion) {
util.showReleaseNotes();
if (versionShown.Value !== versionShown.DefaultValue) {
util.showReleaseNotes();
}
versionShown.Value = releaseNotesVersion;
}
}
@@ -330,14 +335,16 @@ function rewriteManifest(): Promise<void> {
"onCommand:extension.pickNativeProcess",
"onCommand:extension.pickRemoteNativeProcess",
"onCommand:C_Cpp.BuildAndDebugActiveFile",
"onCommand:C_Cpp.ConfigurationEdit",
"onCommand:C_Cpp.ConfigurationEditJSON",
"onCommand:C_Cpp.ConfigurationEditUI",
"onCommand:C_Cpp.ConfigurationSelect",
"onCommand:C_Cpp.ConfigurationProviderSelect",
"onCommand:C_Cpp.SwitchHeaderSource",
"onCommand:C_Cpp.Navigate",
"onCommand:C_Cpp.GoToDeclaration",
"onCommand:C_Cpp.PeekDeclaration",
"onCommand:C_Cpp.ToggleErrorSquiggles",
"onCommand:C_Cpp.EnableErrorSquiggles",
"onCommand:C_Cpp.DisableErrorSquiggles",
"onCommand:C_Cpp.ToggleIncludeFallback",
"onCommand:C_Cpp.ToggleDimInactiveRegions",
"onCommand:C_Cpp.ShowReleaseNotes",
@@ -346,6 +353,7 @@ function rewriteManifest(): Promise<void> {
"onCommand:C_Cpp.ResumeParsing",
"onCommand:C_Cpp.ShowParsingCommands",
"onCommand:C_Cpp.TakeSurvey",
"onCommand:C_Cpp.LogDiagnostics",
"onDebug",
"workspaceContains:/.vscode/c_cpp_properties.json"
];
+1 -1
View File
@@ -39,7 +39,7 @@ export class PlatformInformation {
public static GetUnknownArchitecture(): string { return "Unknown"; }
private static GetWindowsArchitecture(): Promise<string> {
return util.execChildProcess('wmic os get osarchitecture', util.extensionContext.extensionPath)
return util.execChildProcess('wmic os get osarchitecture', util.extensionPath)
.then((architecture) => {
if (architecture) {
let archArray: string[] = architecture.split(os.EOL);
+7 -5
View File
@@ -30,23 +30,25 @@ export function deactivate(): void {
}
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }): void {
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
if (telemetryReporter) {
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
telemetryReporter.sendTelemetryEvent(eventNamePrefix + eventName, properties);
}
}
export function logLanguageServerEvent(eventName: string, properties?: { [key: string]: string }, metrics?: { [key: string]: number }): void {
const eventNamePrefix: string = "C_Cpp/LanguageServer/";
if (telemetryReporter) {
const eventNamePrefix: string = "C_Cpp/LanguageServer/";
telemetryReporter.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics);
}
}
function createReporter(): TelemetryReporter {
let packageInfo: IPackageInfo = getPackageInfo();
if (packageInfo && packageInfo.aiKey) {
return new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
if (util.extensionContext) {
let packageInfo: IPackageInfo = getPackageInfo();
if (packageInfo && packageInfo.aiKey) {
return new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
}
}
return null;
}
+17
View File
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "out",
"lib": [
"es6", "dom"
],
"sourceMap": true,
"rootDir": ".",
"removeComments": true,
"noImplicitUseStrict": true
},
"include": [
"test/**/*.ts"
]
}
@@ -18,7 +18,7 @@ suite(`Debug Integration Test: `, function(): void {
}
});
test("Starting (gdb) Launch from the workspace root should create an Active Debug Session", async function() {
test("Starting (gdb) Launch from the workspace root should create an Active Debug Session", async () => {
// If it is failing on startDebugging. Investigate the SimpleCppProject's tasks.json or launch.json.
await vscode.debug.startDebugging(vscode.workspace.workspaceFolders[0], "(gdb) Launch");
@@ -3,7 +3,6 @@
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as fs from "fs";
import * as path from 'path';
@@ -21,23 +20,23 @@ import { subscribeToAllLoggers } from "../../../src/logger";
// 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');
import testRunner = require('vscode/lib/testrunner');
// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in *.test.ts (suite, test, etc.)
useColors: true, // colored output from test results
fullTrace: true,
fullStackTrace: true,
timeout: 60000
});
const logFolder = path.join( __dirname, ".logs")
const logFolder: string = path.join( __dirname, ".logs");
if (!fs.existsSync(logFolder)) {
fs.mkdirSync(logFolder);
}
const logFilePath = path.join(logFolder, "integrationTests.log");
const logFilePath: string = path.join(logFolder, "integrationTests.log");
subscribeToAllLoggers(message => fs.appendFileSync(logFilePath, message));
module.exports = testRunner;
@@ -10,12 +10,16 @@ import * as util from '../../../src/common';
import * as api from 'vscode-cpptools';
import * as apit from 'vscode-cpptools/out/testApi';
import * as config from '../../../src/LanguageServer/configurations';
import { CppSettings } from '../../../src/LanguageServer/settings';
import { getActiveClient } from '../../../src/LanguageServer/extension';
import { initializeTemporaryCommandRegistrar } from '../../../src/commands';
const defaultTimeout: number = 60000;
suite("multiline comment setting tests", function(): void {
suiteSetup(async function(): Promise<void> {
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
let extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
util.setExtensionPath(extension.extensionPath);
initializeTemporaryCommandRegistrar();
if (!extension.isActive) {
await extension.activate();
}
@@ -187,7 +191,7 @@ suite("extensibility tests v2", function(): void {
resolve();
}
}));
setTimeout(() => { reject(new Error("timeout")); }, 2500);
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
});
disposables.push(testHook);
@@ -262,7 +266,7 @@ suite("extensibility tests v1", function(): void {
resolve();
}
}));
setTimeout(() => { reject(new Error("timeout")); }, 2500);
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
});
disposables.push(testHook);
@@ -334,7 +338,7 @@ suite("extensibility tests v0", function(): void {
resolve();
}
}));
setTimeout(() => { reject(new Error("timeout")); }, 2500);
setTimeout(() => { reject(new Error("timeout")); }, defaultTimeout);
});
disposables.push(testHook);
@@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Environment, ParsedEnvironmentFile } from '../../src/Debugger/ParsedEnvironmentFile'
import * as assert from 'assert';
// Because the environment variable is set as an array, the index does not matter.
function AssertEnvironmentEqual(env: Environment[], name: string, value: string) {
let found: boolean = false;
for (let e of env)
{
if (e.name == name)
{
assert(e.value == value, `Checking if ${e.value} == ${value}`);
found = true;
break;
}
}
assert(found, `${name} was not found in env.`)
}
suite("ParsedEnvironmentFile", () => {
test("Add single variable", () => {
const content = `MyName=VALUE`;
const fakeConfig : Environment[] = [];
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
AssertEnvironmentEqual(result.Env, "MyName", "VALUE");
});
test("Handle quoted values", () => {
const content = `MyName="VALUE"`;
const fakeConfig : Environment[] = [];
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
AssertEnvironmentEqual(result.Env, "MyName", "VALUE");
});
test("Handle BOM", () => {
const content = "\uFEFFMyName=VALUE";
const fakeConfig : Environment[] = [];
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
AssertEnvironmentEqual(result.Env, "MyName", "VALUE");
});
test("Add multiple variables", () => {
const content = `
MyName1=Value1
MyName2=Value2
`;
const fakeConfig : Environment[] = [];
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
});
test("Update variable", () => {
const content = `
MyName1=Value1
MyName2=Value2
`;
const initialEnv : Environment[] = [];
initialEnv.push({name : "MyName1", value: "Value7"});
initialEnv.push({name : "ThisShouldNotChange", value : "StillHere"});
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", initialEnv);
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
AssertEnvironmentEqual(result.Env, "ThisShouldNotChange", "StillHere");
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
});
test("Handle comments", () => {
const content = `# This is an environment file
MyName1=Value1
# This is a comment in the middle of the file
MyName2=Value2
`;
const fakeConfig : Environment[] = [];
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`);
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
});
test("Handle invalid lines", () => {
const content = `
This_Line_Is_Wrong
MyName1=Value1
MyName2=Value2
`;
const fakeConfig : Environment[] = [];
const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]);
assert(result.Warning.startsWith("Ignoring non-parseable lines in envFile TestEnvFileName"), 'Checking if warning exists');
AssertEnvironmentEqual(result.Env, "MyName1", "Value1");
AssertEnvironmentEqual(result.Env, "MyName2", "Value2");
});
});
+20 -2
View File
@@ -4,7 +4,7 @@
* ------------------------------------------------------------------------------------------ */
import * as assert from "assert";
import { resolveVariables } from "../../src/common";
import { resolveVariables, escapeForSquiggles } from "../../src/common";
suite("Common Utility validation", () => {
suite("resolveVariables", () => {
@@ -198,6 +198,25 @@ suite("Common Utility validation", () => {
.shouldLookupSymbol("Root");
});
test("escapeForSquiggles:", () => {
let testEscapeForSquigglesScenario: any = (input: string, expectedOutput: string) => {
let result: string = escapeForSquiggles(input);
if (result !== expectedOutput) {
throw new Error(`escapeForSquiggles failure: for \"${input}\", \"${result}\" !== \"${expectedOutput}\"`);
}
};
testEscapeForSquigglesScenario("\\", "\\\\"); // single backslash
testEscapeForSquigglesScenario("\\\"", "\\\""); // escaped quote
testEscapeForSquigglesScenario("\\\t", "\\\\\t"); // escaped non-quote
testEscapeForSquigglesScenario("\\\\\"", "\\\\\\\\\""); // escaped backslash, unescaped quote
testEscapeForSquigglesScenario("\\\\\t", "\\\\\\\\\t"); // escaped backslash, unescaped non-quote
testEscapeForSquigglesScenario("\\t", "\\\\t"); // escaped non-quote
testEscapeForSquigglesScenario("\\\\\\t", "\\\\\\\\\\\\t"); // escaped backslash, unescaped non-quote
testEscapeForSquigglesScenario("\"\"", "\"\""); // empty quoted string
testEscapeForSquigglesScenario("\"\\\\\"", "\"\\\\\\\\\""); // quoted string containing escaped backslash
});
interface ResolveTestFlowEnvironment {
withEnvironment(additionalEnvironment: {[key: string]: string | string[]}): ResolveTestFlowAssert;
shouldLookupSymbol: (key: string) => void;
@@ -229,6 +248,5 @@ suite("Common Utility validation", () => {
}
};
}
});
});
+10
View File
@@ -429,6 +429,11 @@
},
"default": []
},
"envFile": {
"type": "string",
"description": "Absolute path to a file containing environment variable definitions. These file has key value pairs sepearted by an equals sign per line. E.g. KEY=VALUE",
"default": "${workspaceFolder}/.env"
},
"symbolSearchPath": {
"type": "string",
"description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".",
@@ -461,6 +466,11 @@
"<source-path>": "<target-path>"
}
},
"enableDebugHeap": {
"type": "boolean",
"description": "If false, the process will be launched with debug heap disabled. This sets the environment variable '_NO_DEBUG_HEAP' to '1'.",
"default": false
},
"logging": {
"type": "object",
"description": "Optional flags to determine what types of messages should be logged to the Debug Console.",
@@ -10,9 +10,17 @@
*/
const fs = require("fs");
const os = require("os");
const cp = require("child_process");
const path = require("path");
let compile = function(tsPath) {
const folderName = path.dirname(tsPath);
console.log(">> tsc " + tsPath + " --outDir out/" + folderName);
cp.execSync("tsc " + tsPath + " --outDir out/" + folderName, {stdio:[0, 1, 2]});
};
if (!process.env.CPPTOOLS_DEV && fs.existsSync('./node_modules')) {
console.warn("WARNING: Skipping npm install since it appears to have been executed already.");
} else {
@@ -20,13 +28,17 @@ if (!process.env.CPPTOOLS_DEV && fs.existsSync('./node_modules')) {
cp.execSync("npm install", { stdio: [0, 1, 2] });
}
// Compile the TypeScript code
console.log(">> tsc -p ./");
cp.execSync("tsc -p ./", {stdio:[0, 1, 2]});
const tscCompileListStr = fs.readFileSync("./tscCompileList.txt").toString();
tscCompileListStr.split(/\r?\n/).forEach(filePath => {
if (!filePath.startsWith("#") && /\S/.test(filePath)) {
compile(filePath);
}
});
// If the required debugger file doesn't exist, make sure it is copied.
if (process.env.CPPTOOLS_DEV || !fs.existsSync('./debugAdapters/bin/cppdbg.ad7Engine.json')) {
const copyDebuggerDependenciesJSFile = './out/src/Support/copyDebuggerDependencies.js';
const copyDebuggerDependenciesJSFile = './out/tools/copyDebuggerDependencies.js';
// Required for nightly builds. Nightly builds do not enable CPPTOOLS_DEV.
console.log(">> node " + copyDebuggerDependenciesJSFile);
+13
View File
@@ -0,0 +1,13 @@
# This file is consumed in tools\prepublish.js
# '#' at the start of the line is treated as a comment and is ignored.
# whitespace empty lines are also ignores.
#
# This file is to be used if you do not wish to webpack a .ts file
# If you do not want it to be webpacked:
# 1. Please make sure it is not in the src directory
# 2. Add it to the list below
# 3. If you created a new folder, please make sure it is added to the .vscodeignore
tools/GenerateOptionsSchema.ts
tools/copyDebuggerDependencies.ts
ui/settings.ts
+5 -4
View File
@@ -4,15 +4,16 @@
"target": "es6",
"outDir": "out",
"lib": [
"es6"
"es6", "dom"
],
"sourceMap": true,
"rootDir": ".",
"removeComments": true,
"noImplicitUseStrict": true
},
"exclude": [
"node_modules",
"server"
"include": [
"src/**/*.ts",
"./node_modules/vscode/vscode.d.ts",
"./node_modules/vscode/lib/*",
]
}
+441
View File
@@ -0,0 +1,441 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="style-src 'unsafe-inline'; img-src vscode-resource:; script-src 'nonce-{{nonce}}';">
<style type="text/css">
@media (max-width: 1140px) {
#sidebar {
display: none;
}
#main {
max-width: 800px;
padding: 0px 20px;
margin: auto;
}
}
.page-margins {
vertical-align: top;
padding-top: 40px;
padding-bottom: 10px
}
.sidebar {
width: 290px;
position: fixed;
z-index: 1;
left: 45px;
overflow-x: hidden;
}
.error {
color: var(--vscode-inputValidation-errorForeground);
background: var(--vscode-inputValidation-errorBackground);
border: solid 1px var(--vscode-inputValidation-errorBorder);
white-space: pre-wrap;
visibility: hidden;
display: block;
padding: 1px 4px 4px 4px;
}
.main {
max-width: 800px;
margin-left: 320px;
padding: 0px 30px;
}
.main-title {
font-weight: 500;
font-size: 22px;
padding-bottom: 6px;
color: var(--vscode-foreground);
}
.section {
padding-bottom: 35px;
}
.section-title {
font-weight: 500;
font-size: 14px;
padding-bottom: 4px;
color: var(--vscode-foreground);
}
.section-text {
font-size: 14px;
padding-bottom: 8px;
color: var(--vscode-foreground);
}
.section-note {
font-size: 14px;
font-style: italic;
padding-bottom: 2px;
color: var(--vscode-foreground);
}
.codeblock {
vertical-align: middle;
padding: 2px 8px;
margin-top: 8px;
display: inline-block;
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
border-radius: 5px;
}
body {
line-height: 19px
}
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: 1px;
border-bottom: 1px solid;
}
h1 {
padding-bottom: .3em;
}
h1,
h2,
h3 {
font-weight: 400
}
a:hover {
text-decoration: underline
}
input {
height: 17px;
padding: 6px;
border: solid 1px;
font-size: 13px;
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
color: var(--vscode-settings-textInputForeground);
background: var(--vscode-settings-textInputBackground);
border: 1px solid var(--vscode-settings-textInputBorder);
}
textarea {
white-space: nowrap;
padding: 4px, 4px;
font-size: 13px;
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
color: var(--vscode-settings-textInputForeground);
background: var(--vscode-settings-textInputBackground);
border: 1px solid var(--vscode-settings-textInputBorder);
}
select {
width: 300px;
height: 27px;
font-size: 13px;
font-family:sans-serif;
color: var(--vscode-settings-dropdownForeground);
background: var(--vscode-settings-dropdownBackground);
border: 1px solid var(--vscode-settings-dropdownBorder);
}
blockquote {
margin: 0 7px 0 5px;
padding: 0 16px 0 10px;
border-left: 5px solid;
}
code {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
line-height: 19px
}
.mac code {
line-height: 18px
}
code > div {
padding: 16px;
border-radius: 3px;
overflow: auto
}
.monaco-tokenized-source {
white-space: pre
}
/** Theming */
.vscode-light {
color: #1e1e1e
}
.vscode-dark {
color: #ddd
}
.vscode-high-contrast {
color: #fff
}
.vscode-light code {
color: #a31515
}
.vscode-dark code {
color: #d7ba7d
}
.vscode-light code > div {
background-color: rgba(220, 220, 220, .4)
}
.vscode-dark code > div {
background-color: rgba(10, 10, 10, .4)
}
.vscode-light .input-disabled {
background-color:rgba(255, 255, 255, 0.4);
color: rgb(138, 138, 138);
border: solid 1px rgb(201, 198, 198);
}
.vscode-dark .input-disabled {
background-color: rgba(255, 255, 255, 0.1);
color: rgb(167, 167, 167);
}
.vscode-high-contrast .input-disabled {
background-color: transparent;
color: #fff;
border: solid 1px rgb(255, 255, 255);
}
.vscode-high-contrast code > div {
background-color: #000
}
.vscode-high-contrast h1 {
border-color: #000
}
.vscode-light table > thead > tr > th {
border-color: rgba(0, 0, 0, .69)
}
.vscode-dark table > thead > tr > th {
border-color: rgba(255, 255, 255, .69)
}
.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
border-color: rgba(0, 0, 0, .18)
}
.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
border-color: rgba(255, 255, 255, 0.18)
}
.vscode-light blockquote,
.vscode-dark blockquote {
background: rgba(127, 127, 127, .1);
border-color: rgba(0, 122, 204, .5)
}
.vscode-high-contrast blockquote {
background: transparent;
border-color: #fff
}
.vscode-light div.codeblock {
background-color: rgba(0, 0, 0, 0.048)
}
.vscode-dark div.codeblock {
background-color: rgba(255, 255, 255, 0.1)
}
.vscode-high-contrast div.codeblock {
background-color: rgba(255, 255, 255, 0.15)
}
.footer {
padding: 25px;
text-align: center
}
.vscode-light a {
color: #4080D0
}
.vscode-dark a {
color: #a2c1e8
}
</style>
</head>
<body class="page-margins">
<!-- sidebar -->
<div id="sidebar" class="sidebar">
<div style="height: 90px; display: block">
<table>
<td>
<img src="{{root}}/LanguageCCPP_color_128x.png" height="76" width="76" alt="Microsoft C/C++ Extension" title="Microsoft C/C++ Extension" style="padding-right: 10px">
</td>
<td>
<div style="font-size: 20px; font-weight: 400; line-height: 24px">Microsoft<br>C/C++ Extension</div>
</td>
</table>
</div>
<hr>
<div style="height: 30px; display: block"></div>
<div style="padding-right: 10px; color: var(--vscode-foreground);">
Open this editor by using the command:<br>
<code>C/C++: Edit configurations (UI)</code>
<div style="height: 30px; display: block"></div>
Switch to the <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a> file by clicking on the file link or using the command:<br>
<code>C/C++: Edit configurations (JSON)</code>
</div>
</div> <!-- sidebar end -->
<!-- main -->
<div id="main" class="main">
<!-- title -->
<div style=" height: 90px; display: inline-block;">
<div class="main-title">IntelliSense Configurations</div>
<div style="color: var(--vscode-foreground);">
Use this editor to edit basic IntelliSense settings defined in the underlying <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a> file.
Changes made in this editor only apply to the active configuration. To modify other configurations <a href="command:C_Cpp.ConfigurationSelect" title="Change the active configuration">change the active configuration</a>.
To edit multiple configurations at once, or additional settings not shown here, go to <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a>.
</div>
</div>
<hr>
<div style="height: 30px; display: block"></div>
<!-- sections -->
<div class="section">
<div class="section-title">Configuration name</div>
<div class="section-text">
A friendly name that identifies a configuration. <code>Mac</code>, <code>Linux</code>, and <code>Win32</code> are special identifiers for configurations that will be auto-selected on those platforms, but the name of the identifier can be anything.
To edit the name of the current active configuration, go to the <a href="command:C_Cpp.ConfigurationEditJSON" title="Edit configurations in JSON file">c_cpp_properties.json</a> file and edit the <code>name</code> property.
</div>
<div><input class="input-disabled" type="text" id=activeConfig style="width: 290px" disabled>
<a style="padding-left: 6px;" href="command:C_Cpp.ConfigurationSelect" title="Change the active configuration">Change the active configuration</a>
</div>
</div>
<div class="section">
<div class="section-title">Compiler path</div>
<div class="section-text">
The full path of the compiler being used to build, e.g. <code>/usr/bin/gcc</code>, to enable more accurate IntelliSense.
Args can be added to modify the includes/defines used, e.g. <code>-nostdinc++</code>, <code>-m32</code>, etc., but paths with spaces must be surrounded by double quotes <code>"</code> if args are used.
</div>
<div>
<input id="compilerPath" style="width: 798px"></input>
<div id="compilerPathInvalid" class="error" style="width: 800px"></div>
</div>
</div>
<div class="section">
<div class="section-title">IntelliSense mode</div>
<div class="section-text">
The IntelliSense mode used by the IntelliSense engine. The <code>${default}</code> mode will choose the default for that platform.
Windows defaults to <code>msvc-x64</code>, Linux defaults to <code>gcc-x64</code>, and Mac defaults to <code>clang-x64</code>.
Select a specific IntelliSense mode to override the <code>${default}</code> mode.
</div>
<div>
<select id="intelliSenseMode">
<option value="${default}">${default}</option>
<option value="msvc-x64">msvc-x64</option>
<option value="gcc-x64">gcc-x64</option>
<option value="clang-x64">clang-x64</option>
</select>
</div>
<div id="intelliSenseModeInvalid" class="error" style="width: 290px"></div>
</div>
<div class="section">
<div class="section-title">Include path</div>
<div class="section-text">
A list of paths for the IntelliSense engine to use while searching for included headers. If a path ends with <code>/**</code> the IntelliSense engine will do a recursive search for headers starting from that directory.
</div>
<div>
<div class="section-note">One include path per line.</div>
<textarea id="includePath" rows="4" cols="93" style="width: 800px"></textarea>
<div id="includePathInvalid" class="error" style="margin-top: -4px; width: 794px"></div>
</div>
</div>
<div class="section">
<div class="section-title">Defines</div>
<div class="section-text">
A list of preprocessor definitions for the IntelliSense engine to use while parsing files. Optionally, use <code>=</code> to set a value, e.g. <code>VERSION=1</code>.
</div>
<div>
<div class="section-note">One definition per line.</div>
<textarea id="defines" rows="4" cols="39"></textarea>
</div>
</div>
<div class="section">
<div class="section-title">C Standard</div>
<div class="section-text">The version of the C language standard to use for IntelliSense.</div>
<div>
<select id="cStandard">
<option value="c11">c11</option>
<option value="c99">c99</option>
<option value="c89">c89</option>
</select>
</div>
</div>
<div class="section">
<div class="section-title">C++ Standard</div>
<div class="section-text">The version of the C++ language standard to use for IntelliSense.</div>
<div>
<select id="cppStandard">
<option value="c++17">c++17</option>
<option value="c++14">c++14</option>
<option value="c++11">c++11</option>
<option value="c++03">c++03</option>
<option value="c++98">c++98</option>
</select>
</div> <!-- sections end -->
</div>
</div> <!-- main end -->
<script nonce="{{nonce}}" src="{{root}}/out/ui/settings.js"></script>
</body>
</html>
+120
View File
@@ -0,0 +1,120 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
const elementId: { [key: string]: string } = {
activeConfig: "activeConfig",
compilerPath: "compilerPath",
intelliSenseMode: "intelliSenseMode",
includePath: "includePath",
defines: "defines",
cStandard: "cStandard",
cppStandard: "cppStandard",
compilerPathInvalid: "compilerPathInvalid",
intelliSenseModeInvalid: "intelliSenseModeInvalid",
includePathInvalid: "includePathInvalid"
};
interface VsCodeApi {
postMessage(msg: {}): void;
setState(state: {}): void;
getState(): {};
}
declare function acquireVsCodeApi(): VsCodeApi;
class SettingsApp {
private readonly vsCodeApi: VsCodeApi;
private updating: boolean = false;
constructor() {
this.vsCodeApi = acquireVsCodeApi();
window.addEventListener('message', this.onMessageReceived.bind(this));
document.getElementById(elementId.activeConfig).addEventListener("change", this.onChanged.bind(this, elementId.activeConfig));
document.getElementById(elementId.compilerPath).addEventListener("change", this.onChanged.bind(this, elementId.compilerPath));
document.getElementById(elementId.intelliSenseMode).addEventListener("change", this.onChanged.bind(this, elementId.intelliSenseMode));
document.getElementById(elementId.includePath).addEventListener("change", this.onChanged.bind(this, elementId.includePath));
document.getElementById(elementId.defines).addEventListener("change", this.onChanged.bind(this, elementId.defines));
document.getElementById(elementId.cStandard).addEventListener("change", this.onChanged.bind(this, elementId.cStandard));
document.getElementById(elementId.cppStandard).addEventListener("change", this.onChanged.bind(this, elementId.cppStandard));
}
private onChanged(id: string): void {
if (this.updating) {
return;
}
const x: HTMLInputElement = <HTMLInputElement>document.getElementById(id);
this.vsCodeApi.postMessage({
command: "change",
key: id,
value: x.value
});
}
private onMessageReceived(e: MessageEvent): void {
const message: any = e.data; // The json data that the extension sent
switch (message.command) {
case 'updateConfig':
this.updateConfig(message.config);
break;
case 'updateErrors':
this.updateErrors(message.errors);
break;
}
}
private updateConfig(config: any): void {
this.updating = true;
try {
(<HTMLInputElement>document.getElementById(elementId.activeConfig)).value = config.name;
(<HTMLInputElement>document.getElementById(elementId.compilerPath)).value = config.compilerPath ? config.compilerPath : "";
(<HTMLInputElement>document.getElementById(elementId.intelliSenseMode)).value = config.intelliSenseMode ? config.intelliSenseMode : "${default}";
(<HTMLInputElement>document.getElementById(elementId.includePath)).value =
(config.includePath && config.includePath.length > 0) ? config.includePath.join("\n") : "";
(<HTMLInputElement>document.getElementById(elementId.defines)).value =
(config.defines && config.defines.length > 0 ) ? config.defines.join("\n") : "";
(<HTMLInputElement>document.getElementById(elementId.cStandard)).value = config.cStandard;
(<HTMLInputElement>document.getElementById(elementId.cppStandard)).value = config.cppStandard;
} finally {
this.updating = false;
}
}
private updateErrors(errors: any): void {
this.updating = true;
try {
this.showErrorWithInfo(elementId.intelliSenseModeInvalid,
errors.intelliSenseMode ? true : false,
errors.intelliSenseMode);
this.showErrorWithInfo(elementId.compilerPathInvalid,
errors.compilerPath ? true : false,
errors.compilerPath);
this.showErrorWithInfo(elementId.includePathInvalid,
errors.includePath ? true : false,
errors.includePath);
} finally {
this.updating = false;
}
}
private showErrorWithInfo(elementID: string, show: boolean, errorInfo: string): void {
document.getElementById(elementID).style.visibility = show ? "visible" : "hidden";
document.getElementById(elementID).innerHTML = errorInfo ? errorInfo : "";
}
}
let app: SettingsApp = new SettingsApp();
+41
View File
@@ -0,0 +1,41 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const path = require('path');
/**@type {import('webpack').Configuration}*/
const config = {
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
entry: './src/main.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
libraryTarget: "commonjs2",
devtoolModuleFilenameTemplate: "../[resource-path]",
},
devtool: 'source-map',
externals: {
vscode: "commonjs vscode" // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
},
resolve: { // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js']
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [{
loader: 'ts-loader'
}]
}]
},
}
module.exports = config;
+1 -1
View File
@@ -1,4 +1,4 @@
name: $(Date:yyyyMMdd).$(Rev:.r)
name: $(Date:yyyyMMdd).$(Rev:r)
pr:
- 'master'
jobs:
+20
View File
@@ -194,3 +194,23 @@ _Note: core dump debugging is not supported with MinGw._
* #### `sourceFileMap`
This allows mapping of the compile time paths for source to local source locations. It is an object of key/value pairs and will resolve the first string-matched path. (example: `"sourceFileMap": { "/mnt/c": "c:\\" }` will map any path returned by the debugger that begins with `/mnt/c` and convert it to `c:\\`. You can have multiple mappings in the object but they will be handled in the order provided.)
## Environment variable definitions file
An environment variable definitions file is a simple text file containing key-value pairs in the form of `environment_variable=value`, with `#` used for comments. Multiline values are not supported.
The `cppvsdbg` debugger configuration also contains an `envFile` property that allows you to easily set variables for debugging purposes.
For example:
**project.env file**
```bash
# project.env
# Example environment with key as 'MYENVRIONMENTPATH' and value as C:\\Users\\USERNAME\\Project
MYENVRIONMENTPATH=C:\\Users\\USERNAME\\Project
# Variables with spaces
SPACED_OUT_PATH="C:\\This Has Spaces\\Project"
```