From ded26d66b031f2e7cff4d5d951ee1d38524e9518 Mon Sep 17 00:00:00 2001 From: Griffin Downs <35574547+grdowns@users.noreply.github.com> Date: Thu, 3 May 2018 12:47:45 -0700 Subject: [PATCH 01/21] Move settings update into updateToVersion4 function (#1916) --- .../src/LanguageServer/configurations.ts | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 14a240baa..8f685641e 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -10,7 +10,7 @@ import * as vscode from 'vscode'; import * as util from '../common'; import { PersistentFolderState } from './persistentState'; import { CppSettings } from './settings'; -const configVersion: number = 3; +const configVersion: number = 4; // No properties are set in the config since we want to apply vscode settings first (if applicable). // That code won't trigger if another value is already set. @@ -527,31 +527,7 @@ export class CppProperties { // the system includes were available. this.configurationIncomplete = false; - // Update intelliSenseMode, compilerPath, cStandard, and cppStandard with the defaults if they're missing. - // If VS Code settings exist for these properties, don't add them to c_cpp_properties.json let dirty: boolean = false; - let settings: CppSettings = new CppSettings(this.rootUri); - for (let i: number = 0; i < this.configurationJson.configurations.length; i++) { - let config: Configuration = this.configurationJson.configurations[i]; - if (config.intelliSenseMode === undefined && !settings.defaultIntelliSenseMode) { - dirty = true; - config.intelliSenseMode = this.getIntelliSenseModeForPlatform(config.name); - } - // Don't set the default if compileCommands exist, until it is fixed to have the correct value. - if (config.compilerPath === undefined && this.defaultCompilerPath && !config.compileCommands && !settings.defaultCompilerPath) { - config.compilerPath = this.defaultCompilerPath; - dirty = true; - } - if (!config.cStandard && this.defaultCStandard && !settings.defaultCStandard) { - config.cStandard = this.defaultCStandard; - dirty = true; - } - if (!config.cppStandard && this.defaultCppStandard && !settings.defaultCppStandard) { - config.cppStandard = this.defaultCppStandard; - dirty = true; - } - } - if (this.configurationJson.version !== configVersion) { dirty = true; if (this.configurationJson.version === undefined) { @@ -560,6 +536,10 @@ export class CppProperties { if (this.configurationJson.version === 2) { this.updateToVersion3(); + } + + if (this.configurationJson.version === 3) { + this.updateToVersion4(); } else { this.configurationJson.version = configVersion; vscode.window.showErrorMessage('Unknown version number found in c_cpp_properties.json. Some features may not work as expected.'); @@ -611,6 +591,30 @@ export class CppProperties { } } + private updateToVersion4(): void { + this.configurationJson.version = 4; + // Update intelliSenseMode, compilerPath, cStandard, and cppStandard with the defaults if they're missing. + // If VS Code settings exist for these properties, don't add them to c_cpp_properties.json + let settings: CppSettings = new CppSettings(this.rootUri); + for (let i: number = 0; i < this.configurationJson.configurations.length; i++) { + let config: Configuration = this.configurationJson.configurations[i]; + + if (config.intelliSenseMode === undefined && !settings.defaultIntelliSenseMode) { + config.intelliSenseMode = this.getIntelliSenseModeForPlatform(config.name); + } + // Don't set the default if compileCommands exist, until it is fixed to have the correct value. + if (config.compilerPath === undefined && this.defaultCompilerPath && !config.compileCommands && !settings.defaultCompilerPath) { + config.compilerPath = this.defaultCompilerPath; + } + if (!config.cStandard && this.defaultCStandard && !settings.defaultCStandard) { + config.cStandard = this.defaultCStandard; + } + if (!config.cppStandard && this.defaultCppStandard && !settings.defaultCppStandard) { + config.cppStandard = this.defaultCppStandard; + } + } + } + public checkCppProperties(): void { // Check for change properties in case of file watcher failure. let propertiesFile: string = path.join(this.configFolder, "c_cpp_properties.json"); From 264ed5eb239ecdee2d325a76de8a0978815b9a3c Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Thu, 3 May 2018 16:21:52 -0700 Subject: [PATCH 02/21] trim the path before checking if it exists (#1924) --- Extension/src/LanguageServer/configurations.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 8f685641e..18e7805a9 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -238,8 +238,9 @@ export class CppProperties { // Check for vcpkg instance and include relevent paths if found. if (await util.checkFileExists(util.getVcpkgPathDescriptorFile())) { let vcpkgRoot: string = await util.readFileText(util.getVcpkgPathDescriptorFile()); + vcpkgRoot = vcpkgRoot.trim(); if (await util.checkDirectoryExists(vcpkgRoot)) { - let vcpkgInstalledPath: string = path.join(vcpkgRoot.trim(), "/installed"); + let vcpkgInstalledPath: string = path.join(vcpkgRoot, "/installed"); let list: string[] = await util.readDir(vcpkgInstalledPath); if (list !== undefined) { // For every *directory* in the list (non-recursive). Each directory is basically a platform. From d6aa178cac8bc23f6bd7a8a89c41589e289c4e9b Mon Sep 17 00:00:00 2001 From: Sean McManus Date: Thu, 3 May 2018 16:57:38 -0700 Subject: [PATCH 03/21] Fix issues introduced with VS Code 1.23.0. (#1925) --- Extension/package.json | 2 +- Extension/src/Debugger/extension.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Extension/package.json b/Extension/package.json index 4a3e3d278..3bfd9cf9c 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -32,7 +32,7 @@ "multi-root ready" ], "categories": [ - "Languages", + "Programming Languages", "Debuggers", "Formatters", "Linters", diff --git a/Extension/src/Debugger/extension.ts b/Extension/src/Debugger/extension.ts index 2534ec657..9438b6a3a 100644 --- a/Extension/src/Debugger/extension.ts +++ b/Extension/src/Debugger/extension.ts @@ -34,6 +34,7 @@ export function initialize(): void { configurationProvider.getConfigurationSnippets(); const launchJsonDocumentSelector: vscode.DocumentSelector = [{ + scheme: 'file', language: 'jsonc', pattern: '**/launch.json' }]; From 8deee74b6810f25fda902b4a9c8b3711f173ddce Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Fri, 4 May 2018 16:19:53 -0700 Subject: [PATCH 04/21] Adding OptionsSchema generation (#1937) * Adding OptionsSchema generation This is to prevent repetitive fields from being copy and pasted improperly. * Move tslint to be after compile * Address PR issues --- .travis.yml | 2 +- Extension/.vscodeignore | 1 + Extension/gulpfile.js | 5 + Extension/package.json | 17 +- Extension/tools/GenerateOptionsSchema.ts | 133 ++++++ Extension/tools/OptionsSchema.json | 546 +++++++++++++++++++++++ Extension/tools/README.md | 14 + 7 files changed, 711 insertions(+), 7 deletions(-) create mode 100644 Extension/tools/GenerateOptionsSchema.ts create mode 100644 Extension/tools/OptionsSchema.json create mode 100644 Extension/tools/README.md diff --git a/.travis.yml b/.travis.yml index fd0f8db13..a304992e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,8 +31,8 @@ script: # Build and then run tests - cd Extension - npm install - - npm run tslint - npm run compile + - npm run tslint # pr-check needs to run before test. test modifies package.json. - npm run pr-check - npm run test diff --git a/Extension/.vscodeignore b/Extension/.vscodeignore index 4e6245b7e..0f221495f 100644 --- a/Extension/.vscodeignore +++ b/Extension/.vscodeignore @@ -11,4 +11,5 @@ CMakeLists.txt debugAdapters/install.lock* out/src/Debugger/copyScript.js tools/** +out/tools/** notices/** \ No newline at end of file diff --git a/Extension/gulpfile.js b/Extension/gulpfile.js index 6bce74739..ff7c2ba17 100644 --- a/Extension/gulpfile.js +++ b/Extension/gulpfile.js @@ -10,6 +10,7 @@ const env = require('gulp-env') const tslint = require('gulp-tslint'); const mocha = require('gulp-mocha'); const fs = require('fs'); +const optionsSchemaGenerator = require('./out/tools/GenerateOptionsSchema'); gulp.task('allTests', () => { gulp.start('unitTests'); @@ -82,4 +83,8 @@ gulp.task('pr-check', () => { console.log('Please make sure to not check in package.json that has been rewritten by the extension activation. If you intended to have changes in package.json, please only check-in your changes. If you did not, please run `git checkout -- package.json`.'); process.exit(1); } +}); + +gulp.task('generateOptionsSchema', () => { + optionsSchemaGenerator.GenerateOptionsSchema(); }); \ No newline at end of file diff --git a/Extension/package.json b/Extension/package.json index 3bfd9cf9c..55780d27d 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -533,6 +533,7 @@ }, "configurationAttributes": { "launch": { + "type": "object", "required": [ "program" ], @@ -719,8 +720,8 @@ } }, "logging": { - "type": "object", "description": "Optional flags to determine what types of messages should be logged to the Debug Console.", + "type": "object", "default": {}, "properties": { "exceptions": { @@ -759,10 +760,10 @@ "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the MI-enabled debugger backend executable (such as gdb).", "type": "object", "default": { - "pipeCwd": "${workspaceRoot}", + "pipeCwd": "/usr/bin", "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", "pipeArgs": [], - "debuggerPath": "enter the path for the debugger on the target machine, for example /usr/bin/gdb" + "debuggerPath": "The full path to the debugger on the target machine, for example /usr/bin/gdb." }, "properties": { "pipeCwd": { @@ -801,6 +802,7 @@ } }, "attach": { + "type": "object", "required": [ "program", "processId" @@ -883,8 +885,8 @@ } }, "logging": { - "type": "object", "description": "Optional flags to determine what types of messages should be logged to the Debug Console.", + "type": "object", "default": {}, "properties": { "exceptions": { @@ -923,10 +925,10 @@ "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the MI-enabled debugger backend executable (such as gdb).", "type": "object", "default": { - "pipeCwd": "${workspaceRoot}", + "pipeCwd": "/usr/bin", "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", "pipeArgs": [], - "debuggerPath": "enter the path for the debugger on the target machine, for example /usr/bin/gdb" + "debuggerPath": "The full path to the debugger on the target machine, for example /usr/bin/gdb." }, "properties": { "pipeCwd": { @@ -1007,6 +1009,7 @@ }, "configurationAttributes": { "launch": { + "type": "object", "required": [ "program", "cwd" @@ -1109,6 +1112,7 @@ } }, "attach": { + "type": "object", "required": [ "processId" ], @@ -1272,6 +1276,7 @@ }, "scripts": { "compile": "npm run vscode:prepublish", + "generateOptionsSchema": "gulp generateOptionsSchema", "integrationTests": "gulp integrationTests", "postinstall": "node ./node_modules/vscode/bin/install", "pretest": "tsc -p ./", diff --git a/Extension/tools/GenerateOptionsSchema.ts b/Extension/tools/GenerateOptionsSchema.ts new file mode 100644 index 000000000..0d1c5103f --- /dev/null +++ b/Extension/tools/GenerateOptionsSchema.ts @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; +import * as os from 'os'; + +function AppendFieldsToObject(reference: any, obj: any) { + + // Make sure it is an object type + if (typeof obj == 'object') { + for (let referenceKey in reference) { + // If key exists in original object and is an object. + if (obj.hasOwnProperty(referenceKey)) { + obj[referenceKey] = AppendFieldsToObject(reference[referenceKey], obj[referenceKey]); + } else { + // Does not exist in current object context + obj[referenceKey] = reference[referenceKey]; + } + } + } + + return obj; +} + +// Combines two object's fields, giving the parentDefault a higher precedence. +function MergeDefaults(parentDefault: any, childDefault: any) { + let newDefault: any = {}; + + for (let attrname in childDefault) { + newDefault[attrname] = childDefault[attrname]; + } + + for (let attrname in parentDefault) { + newDefault[attrname] = parentDefault[attrname]; + } + + return newDefault; +} + +function UpdateDefaults(object: any, defaults: any) { + if (defaults != null) { + for (let key in object) { + if (object[key].hasOwnProperty('type') && object[key].type === 'object' && object[key].properties !== null) { + object[key].properties = UpdateDefaults(object[key].properties, MergeDefaults(defaults, object[key].default)); + } else if (key in defaults) { + object[key].default = defaults[key]; + } + } + } + + return object; +} + +function RefReplace(definitions: any, ref: any): any { +// $ref is formatted as "#/definitions/ObjectName" + let referenceStringArray: string[] = ref['$ref'].split('/'); + + // Getting "ObjectName" + let referenceName: string = referenceStringArray[referenceStringArray.length - 1]; + + // Make sure reference has replaced its own $ref fields and hope there are no recursive references. + definitions[referenceName] = ReplaceReferences(definitions, definitions[referenceName]); + + // Retrieve ObjectName from definitions. (TODO: Does not retrieve inner objects) + // Need to deep copy, there are no functions in these objects. + let reference: any = JSON.parse(JSON.stringify(definitions[referenceName])); + + ref = AppendFieldsToObject(reference, ref); + + // Remove $ref field + delete ref['$ref']; + + return ref; +} + +function ReplaceReferences(definitions: any, objects: any) { + for (let key in objects) { + if (objects[key].hasOwnProperty('$ref')) { + objects[key] = RefReplace(definitions, objects[key]); + } + + // Recursively replace references if this object has properties. + if (objects[key].hasOwnProperty('type') && objects[key].type === 'object' && objects[key].properties !== null) { + objects[key].properties = ReplaceReferences(definitions, objects[key].properties); + objects[key].properties = UpdateDefaults(objects[key].properties, objects[key].default); + } + + // Recursively replace references if the array has objects in items. + if (objects[key].hasOwnProperty('type') && objects[key].type === "array" && objects[key].items != null && objects[key].items.hasOwnProperty('$ref')) { + objects[key].items = RefReplace(definitions, objects[key].items); + } + } + + return objects; +} + +function MergeReferences(baseDefinitions: any, additionalDefinitions: any) : void { + for (let key in additionalDefinitions) { + if (baseDefinitions[key]) { + throw `Error: '${key}' defined in multiple schema files.`; + } + baseDefinitions[key] = additionalDefinitions[key]; + } +} + +export function GenerateOptionsSchema() { + let packageJSON: any = JSON.parse(fs.readFileSync('package.json').toString()); + let schemaJSON: any = JSON.parse(fs.readFileSync('tools/OptionsSchema.json').toString()); + + schemaJSON.definitions = ReplaceReferences(schemaJSON.definitions, schemaJSON.definitions); + + // Hard Code adding in configurationAttributes launch and attach. + // cppdbg + packageJSON.contributes.debuggers[0].configurationAttributes.launch = schemaJSON.definitions.CppdbgLaunchOptions; + packageJSON.contributes.debuggers[0].configurationAttributes.attach = schemaJSON.definitions.CppdbgAttachOptions; + + // cppvsdbg + packageJSON.contributes.debuggers[1].configurationAttributes.launch = schemaJSON.definitions.CppvsdbgLaunchOptions; + packageJSON.contributes.debuggers[1].configurationAttributes.attach = schemaJSON.definitions.CppvsdbgAttachOptions; + + let content = JSON.stringify(packageJSON, null, 2); + if (os.platform() === 'win32') { + content = content.replace(/\n/gm, "\r\n"); + } + + // We use '\u200b' (unicode zero-length space character) to break VS Code's URL detection regex for URLs that are examples. This process will + // convert that from the readable espace sequence, to just an invisible character. Convert it back to the visible espace sequence. + content = content.replace(/\u200b/gm, "\\u200b"); + + fs.writeFileSync('package.json', content); +} \ No newline at end of file diff --git a/Extension/tools/OptionsSchema.json b/Extension/tools/OptionsSchema.json new file mode 100644 index 000000000..84acb7e32 --- /dev/null +++ b/Extension/tools/OptionsSchema.json @@ -0,0 +1,546 @@ +{ + "_comment": "See README.md for information about this file", + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "VS Code launch/attach options", + "description": "A json schema for the VS Code attach and launch options", + "type": "object", + "definitions": { + "PipeTransport": { + "type": "object", + "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the MI-enabled debugger backend executable (such as gdb).", + "default": { + "pipeCwd": "/usr/bin", + "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", + "pipeArgs": [], + "debuggerPath": "The full path to the debugger on the target machine, for example /usr/bin/gdb." + }, + "properties": { + "pipeCwd": { + "type": "string", + "description": "The fully qualified path to the working directory for the pipe program.", + "default": "/usr/bin" + }, + "pipeProgram": { + "type": "string", + "description": "The fully qualified pipe command to execute.", + "default": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'" + }, + "pipeArgs": { + "type": "array", + "description": "Command line arguments passed to the pipe program to configure the connection.", + "items": { + "type": "string" + }, + "default": [] + }, + "debuggerPath": { + "type": "string", + "description": "The full path to the debugger on the target machine, for example /usr/bin/gdb.", + "default": "The full path to the debugger on the target machine, for example /usr/bin/gdb." + }, + "pipeEnv": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Environment variables passed to the pipe program.", + "default": {} + } + } + }, + "Logging": { + "type": "object", + "default": {}, + "description": "Optional flags to determine what types of messages should be logged to the Debug Console.", + "properties": { + "exceptions": { + "type": "boolean", + "description": "Optional flag to determine whether exception messages should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "moduleLoad": { + "type": "boolean", + "description": "Optional flag to determine whether module load events should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "programOutput": { + "type": "boolean", + "description": "Optional flag to determine whether program output should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "engineLogging": { + "type": "boolean", + "description": "Optional flag to determine whether diagnostic engine logs should be logged to the Debug Console. Defaults to false.", + "default": false + }, + "trace": { + "type": "boolean", + "description": "Optional flag to determine whether diagnostic adapter command tracing should be logged to the Debug Console. Defaults to false.", + "default": false + }, + "traceResponse": { + "type": "boolean", + "description": "Optional flag to determine whether diagnostic adapter command and response tracing should be logged to the Debug Console. Defaults to false.", + "default": false + } + } + }, + "SetupCommandsConfiguration": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "The debugger command to execute.", + "default": "" + }, + "description": { + "type": "string", + "description": "Optional description for the command.", + "default": "" + }, + "ignoreFailures": { + "type": "boolean", + "description": "If true, failures from the command should be ignored. Default value is false.", + "default": false + } + } + }, + "KeyValuePair": { + "type": "object", + "properties": { + "name": "string", + "value": "string" + } + }, + "CppdbgLaunchOptions": { + "type": "object", + "required": [ + "program" + ], + "properties": { + "program": { + "type": "string", + "description": "Full path to program executable.", + "default": "${workspaceRoot}/a.out" + }, + "args": { + "type": "array", + "description": "Command line arguments passed to the program.", + "items": { + "type": "string" + }, + "default": [] + }, + "type": { + "type": "string", + "description": "The type of the engine. Must be \"cppdbg\".", + "default": "cppdbg" + }, + "targetArchitecture": { + "type": "string", + "description": "The architecture of the debuggee. This will automatically be detected unless this parameter is set. Allowed values are x86, arm, arm64, mips, x64, amd64, x86_64.", + "default": "x64" + }, + "cwd": { + "type": "string", + "description": "The working directory of the target", + "default": "." + }, + "setupCommands": { + "type": "array", + "description": "One or more GDB/LLDB commands to execute in order to setup the underlying debugger. Example: \"setupCommands\": [ { \"text\": \"-enable-pretty-printing\", \"description\": \"Enable GDB pretty printing\", \"ignoreFailures\": true }].", + "items": { + "$ref": "#/definitions/SetupCommandsConfiguration" + }, + "default": [] + }, + "customLaunchSetupCommands": { + "type": "array", + "description": "If provided, this replaces the default commands used to launch a target with some other commands. For example, this can be \"-target-attach\" in order to attach to a target process. An empty command list replaces the launch commands with nothing, which can be useful if the debugger is being provided launch options as command line options. Example: \"customLaunchSetupCommands\": [ { \"text\": \"target-run\", \"description\": \"run target\", \"ignoreFailures\": false }].", + "items": { + "$ref": "#/definitions/SetupCommandsConfiguration" + }, + "default": [] + }, + "launchCompleteCommand": { + "enum": [ + "exec-run", + "exec-continue", + "None" + ], + "description": "The command to execute after the debugger is fully setup in order to cause the target process to run. Allowed values are \"exec-run\", \"exec-continue\", \"None\". The default value is \"exec-run\".", + "default": "exec-run" + }, + "visualizerFile": { + "type": "string", + "description": ".natvis file to be used when debugging this process. This option is not compatible with GDB pretty printing. Please also see \"showDisplayString\" if using this setting.", + "default": "" + }, + "showDisplayString": { + "type": "boolean", + "description": "When a visualizerFile is specified, showDisplayString will enable the display string. Turning this option on can cause slower performance during debugging.", + "default": true + }, + "environment": { + "type": "array", + "description": "Environment variables to add to the environment for the program. Example: [ { \"name\": \"squid\", \"value\": \"clam\" } ].", + "items": { + "$ref": "#/definitions/KeyValuePair" + }, + "default": [] + }, + "additionalSOLibSearchPath": { + "type": "string", + "description": "Semicolon separated list of directories to use to search for .so files. Example: \"c:\\dir1;c:\\dir2\".", + "default": "" + }, + "MIMode": { + "type": "string", + "description": "Indicates the console debugger that the MIDebugEngine will connect to. Allowed values are \"gdb\" \"lldb\".", + "default": "gdb" + }, + "miDebuggerPath": { + "type": "string", + "description": "The path to the mi debugger (such as gdb). When unspecified, it will search path first for the debugger.", + "default": "/usr/bin/gdb" + }, + "miDebuggerServerAddress": { + "type": "string", + "description": "Network address of the MI Debugger Server to connect to (example: localhost:1234).", + "default": "serveraddress:port" + }, + "stopAtEntry": { + "type": "boolean", + "description": "Optional parameter. If true, the debugger should stop at the entrypoint of the target. If processId is passed, has no effect.", + "default": false + }, + "debugServerPath": { + "type": "string", + "description": "Optional full path to debug server to launch. Defaults to null.", + "default": "" + }, + "debugServerArgs": { + "type": "string", + "description": "Optional debug server args. Defaults to null.", + "default": "" + }, + "serverStarted": { + "type": "string", + "description": "Optional server-started pattern to look for in the debug server output. Defaults to null.", + "default": "" + }, + "filterStdout": { + "type": "boolean", + "description": "Search stdout stream for server-started pattern and log stdout to debug output. Defaults to true.", + "default": true + }, + "filterStderr": { + "type": "boolean", + "description": "Search stderr stream for server-started pattern and log stderr to debug output. Defaults to false.", + "default": false + }, + "serverLaunchTimeout": { + "type": "integer", + "description": "Optional time, in milliseconds, for the debugger to wait for the debugServer to start up. Default is 10000.", + "default": "10000" + }, + "coreDumpPath": { + "type": "string", + "description": "Optional full path to a core dump file for the specified program. Defaults to null.", + "default": "" + }, + "externalConsole": { + "type": "boolean", + "description": "If true, a console is launched for the debuggee. If false, no console is launched. Note this option is ignored in some cases for technical reasons.", + "default": false + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine. Example: '{ \"/original/source/path\":\"/current/source/path\" }'", + "default": { + "": "" + } + }, + "logging": { + "$ref": "#/definitions/Logging", + "description": "Optional flags to determine what types of messages should be logged to the Debug Console." + }, + "pipeTransport": { + "$ref": "#/definitions/PipeTransport", + "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the MI-enabled debugger backend executable (such as gdb)." + } + } + }, + "CppdbgAttachOptions": { + "type": "object", + "required": [ + "program", + "processId" + ], + "properties": { + "program": { + "type": "string", + "description": "Full path to program executable.", + "default": "${workspaceRoot}/a.out" + }, + "type": { + "type": "string", + "description": "The type of the engine. Must be \"cppdbg\".", + "default": "cppdbg" + }, + "targetArchitecture": { + "type": "string", + "description": "The architecture of the debuggee. This will automatically be detected unless this parameter is set. Allowed values are x86, arm, arm64, mips, x64, amd64, x86_64.", + "default": "x64" + }, + "visualizerFile": { + "type": "string", + "description": ".natvis file to be used when debugging this process. This option is not compatible with GDB pretty printing. Please also see \"showDisplayString\" if using this setting.", + "default": "" + }, + "showDisplayString": { + "type": "boolean", + "description": "When a visualizerFile is specified, showDisplayString will enable the display string. Turning this option on can cause slower performance during debugging.", + "default": true + }, + "additionalSOLibSearchPath": { + "type": "string", + "description": "Semicolon separated list of directories to use to search for .so files. Example: \"c:\\dir1;c:\\dir2\".", + "default": "" + }, + "MIMode": { + "type": "string", + "description": "Indicates the console debugger that the MIDebugEngine will connect to. Allowed values are \"gdb\" \"lldb\".", + "default": "gdb" + }, + "miDebuggerPath": { + "type": "string", + "description": "The path to the mi debugger (such as gdb). When unspecified, it will search path first for the debugger.", + "default": "/usr/bin/gdb" + }, + "miDebuggerServerAddress": { + "type": "string", + "description": "Network address of the MI Debugger Server to connect to (example: localhost:1234).", + "default": "serveraddress:port" + }, + "processId": { + "anyOf": [ + { + "type": "string", + "description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.", + "default": "${command:pickProcess}" + }, + { + "type": "integer", + "description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.", + "default": 0 + } + ] + }, + "filterStdout": { + "type": "boolean", + "description": "Search stdout stream for server-started pattern and log stdout to debug output. Defaults to true.", + "default": true + }, + "filterStderr": { + "type": "boolean", + "description": "Search stderr stream for server-started pattern and log stderr to debug output. Defaults to false.", + "default": false + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine. Example: '{ \"/original/source/path\":\"/current/source/path\" }'", + "default": { + "": "" + } + }, + "logging": { + "$ref": "#/definitions/Logging", + "description": "Optional flags to determine what types of messages should be logged to the Debug Console." + }, + "pipeTransport": { + "$ref": "#/definitions/PipeTransport", + "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the MI-enabled debugger backend executable (such as gdb)." + }, + "setupCommands": { + "type": "array", + "description": "One or more GDB/LLDB commands to execute in order to setup the underlying debugger. Example: \"setupCommands\": [ { \"text\": \"-enable-pretty-printing\", \"description\": \"Enable GDB pretty printing\", \"ignoreFailures\": true }].", + "items": { + "$ref": "#/definitions/SetupCommandsConfiguration" + }, + "default": [] + } + } + }, + "CppvsdbgLaunchOptions": { + "type": "object", + "required": [ + "program", + "cwd" + ], + "properties": { + "program": { + "type": "string", + "description": "Full path to program executable.", + "default": "${workspaceRoot}/program.exe" + }, + "args": { + "type": "array", + "description": "Command line arguments passed to the program.", + "items": { + "type": "string" + }, + "default": [] + }, + "type": { + "type": "string", + "description": "The type of the engine. Must be \"cppvsdbg\".", + "default": "cppvsdbg" + }, + "cwd": { + "type": "string", + "description": "The working directory of the target.", + "default": "${workspaceRoot}" + }, + "environment": { + "type": "array", + "description": "Environment variables to add to the environment for the program. Example: [ { \"name\": \"squid\", \"value\": \"clam\" } ].", + "items": { + "$ref": "#/definitions/KeyValuePair" + }, + "default": [] + }, + "symbolSearchPath": { + "type": "string", + "description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".", + "default": "" + }, + "stopAtEntry": { + "type": "boolean", + "description": "Optional parameter. If true, the debugger should stop at the entrypoint of the target. If processId is passed, has no effect.", + "default": false + }, + "dumpPath": { + "type": "string", + "description": "Optional full path to a dump file for the specified program. Example: \"c:\\temp\\app.dmp\". Defaults to null.", + "default": "" + }, + "visualizerFile": { + "type": "string", + "description": ".natvis file to be used when debugging this process.", + "default": "" + }, + "externalConsole": { + "type": "boolean", + "description": "If true, a console is launched for the debuggee. If false, no console is launched.", + "default": false + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine. Example: '{ \"/original/source/path\":\"/current/source/path\" }'", + "default": { + "": "" + } + }, + "logging": { + "type": "object", + "description": "Optional flags to determine what types of messages should be logged to the Debug Console.", + "default": {}, + "properties": { + "exceptions": { + "type": "boolean", + "description": "Optional flag to determine whether exception messages should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "moduleLoad": { + "type": "boolean", + "description": "Optional flag to determine whether module load events should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "programOutput": { + "type": "boolean", + "description": "Optional flag to determine whether program output should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "engineLogging": { + "type": "boolean", + "description": "Optional flag to determine whether diagnostic debug engine messages should be logged to the Debug Console. Defaults to false.", + "default": false + } + } + } + } + }, + "CppvsdbgAttachOptions": { + "type": "object", + "required": [ + "processId" + ], + "properties": { + "type": { + "type": "string", + "description": "The type of the engine. Must be \"cppvsdbg\".", + "default": "cppvsdbg" + }, + "symbolSearchPath": { + "type": "string", + "description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".", + "default": "" + }, + "processId": { + "anyOf": [ + { + "type": "string", + "description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.", + "default": "${command:pickProcess}" + }, + { + "type": "integer", + "description": "Optional process id to attach the debugger to. Use \"${command:pickProcesss}\" to get a list of local running processes to attach to. Note that some platforms require administrator privileges in order to attach to a process.", + "default": 0 + } + ] + }, + "visualizerFile": { + "type": "string", + "description": ".natvis file to be used when debugging this process.", + "default": "" + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine. Example: '{ \"/original/source/path\":\"/current/source/path\" }'", + "default": { + "": "" + } + }, + "logging": { + "type": "object", + "description": "Optional flags to determine what types of messages should be logged to the Debug Console.", + "default": {}, + "properties": { + "exceptions": { + "type": "boolean", + "description": "Optional flag to determine whether exception messages should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "moduleLoad": { + "type": "boolean", + "description": "Optional flag to determine whether module load events should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "programOutput": { + "type": "boolean", + "description": "Optional flag to determine whether program output should be logged to the Debug Console. Defaults to true.", + "default": true + }, + "trace": { + "type": "boolean", + "description": "Optional flag to determine whether diagnostic adapter command tracing should be logged to the Debug Console. Defaults to false.", + "default": false + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Extension/tools/README.md b/Extension/tools/README.md new file mode 100644 index 000000000..60afe527b --- /dev/null +++ b/Extension/tools/README.md @@ -0,0 +1,14 @@ +# OptionsSchema +OptionsSchema.json defines the type for Launch/Attach options. + +# GenerateOptionsSchema +If there are any modifications to the OptionsSchema.json file. Please run `npm run generateOptionsSchema` at the repo root. +This will call GenerateOptionsSchema and update the package.json file. + +### Important notes: + +1. Any manual changes to package.json's object.contributes.debuggers[0].configurationAttributes (cppdbg) or object.contributes.debuggers[0].configurationAttributes (cppvsdbg) will be +replaced by this generator. + +If there is any other type of options added in the future, you will need to modify the GenerateOptionsSchema function +to have it appear in package.json. It only adds launch and attach. From 58cfb5ee104d4ea0e5ebcc971955dc47bcbfef06 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 4 May 2018 20:18:42 -0700 Subject: [PATCH 05/21] add support for custom variables (#1921) * add support for custom variables * support for string[] variables * rename "variables" to "env" --- Extension/c_cpp_properties.schema.json | 23 +++++++++++++++++++ .../src/LanguageServer/configurations.ts | 18 ++++++++++++--- Extension/src/common.ts | 18 +++++++++++++-- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Extension/c_cpp_properties.schema.json b/Extension/c_cpp_properties.schema.json index d4aac1e68..8e7e85590 100644 --- a/Extension/c_cpp_properties.schema.json +++ b/Extension/c_cpp_properties.schema.json @@ -107,6 +107,26 @@ } } }, + "env": { + "type": "object", + "description": "Custom variables that can be resused anywhere in this file using the ${variable} or ${env:variable} syntax.", + "patternProperties": { + "(?!^workspaceFolder$)(?!^workspaceRoot$)(?!^default$)(^.+$)": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "additionalProperties": false + }, "version": { "type": "integer", "description": "Version of the configuration file. This property is managed by the extension. Please do not change it." @@ -116,6 +136,9 @@ "configurations": { "$ref": "#/definitions/configurations" }, + "env": { + "$ref": "#/definitions/env" + }, "version": { "$ref": "#/definitions/version" } diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 18e7805a9..ed88c44bd 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -34,6 +34,7 @@ function getDefaultCppProperties(): ConfigurationJson { interface ConfigurationJson { configurations: Configuration[]; + env?: {[key: string]: string | string[]}; version: number; } @@ -336,7 +337,11 @@ export class CppProperties { let result: string[] = []; entries.forEach(entry => { if (entry === "${default}") { - result = result.concat(defaultValue); + // package.json default values for string[] properties is null. + // If no default is set, return an empty array instead of an array with `null` in it. + if (defaultValue !== null) { + result = result.concat(defaultValue); + } } else { result.push(entry); } @@ -348,7 +353,7 @@ export class CppProperties { let result: string[] = []; if (paths) { paths.forEach(entry => { - let entries: string[] = util.resolveVariables(entry).split(";").filter(e => e); + let entries: string[] = util.resolveVariables(entry, this.configurationJson.env).split(";").filter(e => e); entries = this.resolveDefaults(entries, defaultValue); result = result.concat(entries); }); @@ -363,7 +368,7 @@ export class CppProperties { if (typeof input === "boolean") { return input; } - return util.resolveVariables(input); + return util.resolveVariables(input, this.configurationJson.env); } private updateConfiguration(property: string[], defaultValue: string[]): string[]; @@ -524,6 +529,13 @@ export class CppProperties { this.currentConfigurationIndex.Value = this.getConfigIndexForPlatform(newJson); } + // Remove disallowed variable overrides + if (this.configurationJson.env) { + delete this.configurationJson.env['workspaceRoot']; + delete this.configurationJson.env['workspaceFolder']; + delete this.configurationJson.env['default']; + } + // Warning: There is a chance that this is incorrect in the event that the c_cpp_properties.json file was created before // the system includes were available. this.configurationIncomplete = false; diff --git a/Extension/src/common.ts b/Extension/src/common.ts index ed72015d5..17c26781e 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -143,10 +143,13 @@ export function showReleaseNotes(): void { vscode.commands.executeCommand('vscode.previewHtml', vscode.Uri.file(getExtensionFilePath("ReleaseNotes.html")), vscode.ViewColumn.One, "C/C++ Extension Release Notes"); } -export function resolveVariables(input: string): string { +export function resolveVariables(input: string, additionalEnvironment: {[key: string]: string | string[]}): string { if (!input) { return ""; } + if (!additionalEnvironment) { + additionalEnvironment = {}; + } // Replace environment and configuration variables. let regexp: RegExp = /\$\{((env|config)(.|:))?(.*?)\}/g; @@ -158,7 +161,18 @@ export function resolveVariables(input: string): string { } let newValue: string = undefined; switch (varType) { - case "env": { newValue = process.env[name]; break; } + case "env": { + let v: string | string[] = additionalEnvironment[name]; + if (typeof v === "string") { + newValue = v; + } else if (input === match && v instanceof Array) { + newValue = v.join(";"); + } + if (!newValue) { + newValue = process.env[name]; + } + break; + } case "config": { let config: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(); let keys: string[] = name.split('.'); From 2ded5b241eca9b91dfdbfbfed0a6c3c73064e606 Mon Sep 17 00:00:00 2001 From: jogo- Date: Mon, 7 May 2018 19:40:56 +0200 Subject: [PATCH 06/21] Fix typo in c_cpp_properties.schema.json (#1945) --- Extension/c_cpp_properties.schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/c_cpp_properties.schema.json b/Extension/c_cpp_properties.schema.json index 8e7e85590..07c00780b 100644 --- a/Extension/c_cpp_properties.schema.json +++ b/Extension/c_cpp_properties.schema.json @@ -109,7 +109,7 @@ }, "env": { "type": "object", - "description": "Custom variables that can be resused anywhere in this file using the ${variable} or ${env:variable} syntax.", + "description": "Custom variables that can be reused anywhere in this file using the ${variable} or ${env:variable} syntax.", "patternProperties": { "(?!^workspaceFolder$)(?!^workspaceRoot$)(?!^default$)(^.+$)": { "oneOf": [ @@ -147,4 +147,4 @@ "configurations", "version" ] -} \ No newline at end of file +} From 842856f08a9e64811cc2c66f7c58f20acc6833a9 Mon Sep 17 00:00:00 2001 From: jogo- Date: Mon, 7 May 2018 19:41:38 +0200 Subject: [PATCH 07/21] Fix typo in README.md (#1944) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5505d99c0..1dd48337a 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ You can learn how to use the extension at [VS Code for C/C++](https://code.visua If you clone this repository, you can also try out our [Code Samples](Code%20Samples). -If you have any questions, check out our our [**Documentation**](Documentation) folder. If you do not find your answer there, feel free to ask it in our [issues page](https://github.com/Microsoft/vscode-cpptools/issues). +If you have any questions, check out our [**Documentation**](Documentation) folder. If you do not find your answer there, feel free to ask it in our [issues page](https://github.com/Microsoft/vscode-cpptools/issues). ### Contribution From ff31eef0a2bb58463f9c746981f7901c4cca7ea4 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Mon, 7 May 2018 11:22:12 -0700 Subject: [PATCH 08/21] Extension Development Improvements (#1941) 1. Updated tasks.json to 2.0 2. Added tslint problem matcher - Weird issue that problem does not disappear when resolved. 3. Adding tslint for class and function names. - class must be in PascalCase - funcitons must be in camelCase 4. Addressing vulnerability warning - https://github.com/Microsoft/vscode/issues/49146 --- Extension/.vscode/launch.json | 4 +- Extension/.vscode/tasks.json | 86 ++- Extension/gulpfile.js | 1 + Extension/package-lock.json | 631 ++++++++--------------- Extension/package.json | 9 +- Extension/src/Debugger/configurations.ts | 32 +- Extension/src/abTesting.ts | 2 +- Extension/src/common.ts | 2 +- Extension/src/packageManager.ts | 2 +- Extension/tools/GenerateOptionsSchema.ts | 48 +- Extension/tslint.json | 11 +- 11 files changed, 326 insertions(+), 502 deletions(-) diff --git a/Extension/.vscode/launch.json b/Extension/.vscode/launch.json index 296a4b657..838793545 100644 --- a/Extension/.vscode/launch.json +++ b/Extension/.vscode/launch.json @@ -15,7 +15,7 @@ "outFiles": [ "${workspaceFolder}/out/**/*.js" ], - "preLaunchTask": "npm" + "preLaunchTask": "compile", }, { "name": "Launch Tests", @@ -31,7 +31,7 @@ "outFiles": [ "${workspaceFolder}/out/test/**/*.js" ], - "preLaunchTask": "npm" + "preLaunchTask": "compile" }, { "name": "Node Attach", diff --git a/Extension/.vscode/tasks.json b/Extension/.vscode/tasks.json index d31b15910..bcf550385 100644 --- a/Extension/.vscode/tasks.json +++ b/Extension/.vscode/tasks.json @@ -1,30 +1,60 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -// A task runner that calls a custom npm script that compiles the extension. { - "version": "0.1.0", - - // we want to run npm - "command": "npm", - - // the command is a shell script - "isShellCommand": true, - - // show the output window only if unrecognized errors occur. - "showOutput": "silent", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // The tsc compiler is started in watching mode - "isWatching": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch" + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "TypeScript Compile", + "identifier": "compile", + "group": { + "kind": "build", + "isDefault": true + }, + "isBackground": true, + "type": "shell", + "presentation": { + "echo": true, + "reveal": "silent", + "focus": false, + "panel": "shared" + }, + "command": "npm", + "args": [ + "run", + "compile", + "--loglevel", + "silent" + ], + "problemMatcher": "$tsc-watch" + }, + { + "label": "TypeScript Lint", + "identifier": "tslint", + "group": "build", + "isBackground": false, + "type": "shell", + "command": "npm", + "args": [ + "run", + "tslint" + ], + "problemMatcher": { + "fileLocation": "absolute", + "source": "tslint", + "pattern": [ + { + "regexp": "(ERROR:) ([a-zA-Z/:\\-\\.]*)\\[(\\d+), (\\d+)\\]: (.*)", + "severity": 1, + "file": 2, + "line": 3, + "column": 4, + "message": 5 + } + ] + }, + "dependsOn": [ + "compile" + ] + } + ] } \ No newline at end of file diff --git a/Extension/gulpfile.js b/Extension/gulpfile.js index ff7c2ba17..6372e5f53 100644 --- a/Extension/gulpfile.js +++ b/Extension/gulpfile.js @@ -52,6 +52,7 @@ gulp.task('integrationTests', () => { /// Misc Tasks const allTypeScript = [ 'src/**/*.ts', + 'tools/**/*.ts', '!**/*.d.ts', '!**/typings**' ]; diff --git a/Extension/package-lock.json b/Extension/package-lock.json index 944e1ba45..2d4c5472c 100644 --- a/Extension/package-lock.json +++ b/Extension/package-lock.json @@ -34,7 +34,7 @@ "dev": true, "requires": { "co": "4.6.0", - "fast-deep-equal": "1.0.0", + "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", "json-schema-traverse": "0.3.1" } @@ -174,9 +174,9 @@ "dev": true }, "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, "assign-symbols": { @@ -198,15 +198,15 @@ "dev": true }, "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", "dev": true }, "babel-code-frame": { @@ -295,12 +295,12 @@ } }, "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "4.2.1" } }, "brace-expansion": { @@ -334,6 +334,12 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -366,9 +372,9 @@ } }, "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "chalk": { @@ -505,14 +511,46 @@ "dev": true }, "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { "inherits": "2.0.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } } }, "co": { @@ -553,9 +591,9 @@ "dev": true }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { "delayed-stream": "1.0.0" @@ -620,12 +658,23 @@ } }, "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "dev": true, "requires": { - "boom": "2.10.1" + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + } } }, "dargs": { @@ -641,14 +690,6 @@ "dev": true, "requires": { "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "dateformat": { @@ -785,12 +826,12 @@ } }, "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "inherits": "2.0.3", "readable-stream": "2.3.3", "stream-shift": "1.0.0" @@ -807,9 +848,9 @@ } }, "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "1.4.0" @@ -842,7 +883,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -947,9 +988,9 @@ } }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -1258,14 +1299,14 @@ "dev": true }, "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.18" } }, "fragment-cache": { @@ -1310,21 +1351,6 @@ "globule": "0.1.0" } }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -1344,14 +1370,6 @@ "dev": true, "requires": { "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "glob": { @@ -1850,23 +1868,23 @@ "through2": "2.0.3" } }, - "gulp-remote-src": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz", - "integrity": "sha1-VyjP1kNDPdSEXd7wlp8PlxoqtKE=", + "gulp-remote-src-vscode": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.0.tgz", + "integrity": "sha512-/9vtSk9eI9DEWCqzGieglPqmx0WUQ9pwPHyHFpKmfxqdgqGJC2l0vFMdYs54hLdDsMDEZFLDL2J4ikjc4hQ5HQ==", "dev": true, "requires": { "event-stream": "3.3.4", "node.extend": "1.1.6", - "request": "2.79.0", + "request": "2.85.0", "through2": "2.0.3", - "vinyl": "2.0.2" + "vinyl": "2.1.0" }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", "dev": true }, "clone-stats": { @@ -1875,45 +1893,16 @@ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", "dev": true }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "3.1.0" - } - }, "vinyl": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", - "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "2.1.1", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", - "is-stream": "1.1.0", + "cloneable-readable": "1.1.2", "remove-trailing-separator": "1.1.0", "replace-ext": "1.0.0" } @@ -1934,9 +1923,9 @@ }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "replace-ext": { @@ -1951,7 +1940,7 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -2129,7 +2118,7 @@ "clone": "2.1.1", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", + "cloneable-readable": "1.1.2", "remove-trailing-separator": "1.1.0", "replace-ext": "1.0.0" } @@ -2152,36 +2141,13 @@ "dev": true }, "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.17.1", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "has-ansi": { @@ -2269,15 +2235,15 @@ } }, "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" } }, "he": { @@ -2287,9 +2253,9 @@ "dev": true }, "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", "dev": true }, "homedir-polyfill": { @@ -2311,14 +2277,14 @@ } }, "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "0.2.0", + "assert-plus": "1.0.0", "jsprim": "1.4.1", - "sshpk": "1.13.1" + "sshpk": "1.14.1" } }, "https-proxy-agent": { @@ -2479,18 +2445,6 @@ "is-extglob": "2.1.1" } }, - "is-my-json-valid": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", - "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -2575,12 +2529,6 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -2707,12 +2655,6 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2723,14 +2665,6 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "kind-of": { @@ -3017,18 +2951,18 @@ } }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", "dev": true }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" } }, "minimatch": { @@ -3567,21 +3501,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, "plugin-error": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", @@ -3632,15 +3551,15 @@ "dev": true }, "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, "querystringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", + "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", "dev": true }, "queue": { @@ -3771,156 +3690,33 @@ "dev": true }, "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "dev": true, "requires": { "aws-sign2": "0.7.0", - "aws4": "1.6.0", + "aws4": "1.7.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.1", + "form-data": "2.3.2", "har-validator": "5.0.3", "hawk": "6.0.2", "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", "performance-now": "2.1.0", - "qs": "6.5.1", + "qs": "6.5.2", "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", - "uuid": "3.1.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, - "requires": { - "boom": "5.2.0" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - } - } - }, - "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" - } - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.0", - "sntp": "2.1.0" - } - }, - "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" - } - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.2.0" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } + "uuid": "3.2.1" } }, "requires-port": { @@ -4178,12 +3974,12 @@ } }, "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "4.2.1" } }, "source-map": { @@ -4206,11 +4002,12 @@ } }, "source-map-support": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", - "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.5.tgz", + "integrity": "sha512-mR7/Nd5l1z6g99010shcXJiNEaf3fEtmLhRB/sBcQVJGodcHCULPp2y4Sfa43Kv2zq7T+Izmfp/WHCR6dYkQCA==", "dev": true, "requires": { + "buffer-from": "1.0.0", "source-map": "0.6.1" } }, @@ -4266,9 +4063,9 @@ } }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, "requires": { "asn1": "0.2.3", @@ -4279,14 +4076,6 @@ "getpass": "0.1.7", "jsbn": "0.1.1", "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "stat-mode": { @@ -4686,9 +4475,9 @@ } }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { "punycode": "1.4.1" @@ -4755,10 +4544,13 @@ } }, "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } }, "tweetnacl": { "version": "0.14.5", @@ -4883,12 +4675,12 @@ "dev": true }, "url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", + "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", "dev": true, "requires": { - "querystringify": "1.0.0", + "querystringify": "2.0.0", "requires-port": "1.0.0" } }, @@ -4990,9 +4782,9 @@ "dev": true }, "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, "v8flags": { @@ -5019,14 +4811,6 @@ "assert-plus": "1.0.0", "core-util-is": "1.0.2", "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "vinyl": { @@ -5045,7 +4829,7 @@ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "dev": true, "requires": { - "duplexify": "3.5.1", + "duplexify": "3.6.0", "glob-stream": "5.3.5", "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", @@ -5065,9 +4849,9 @@ }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "replace-ext": { @@ -5082,7 +4866,7 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -5099,25 +4883,34 @@ "vinyl": "0.4.6" } }, + "vrsource-tslint-rules": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/vrsource-tslint-rules/-/vrsource-tslint-rules-5.8.2.tgz", + "integrity": "sha512-wr69FB/S6P8GT+rO/OocCr3biFaX4lT/JH1IZGqd7Jy4A3WaPUs0Jn4ELmTEpbFtYMWTawFACMQh1AyT7YewRQ==", + "dev": true, + "requires": { + "tslint": "5.8.0" + } + }, "vscode": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.14.tgz", - "integrity": "sha512-acfn3fzGtTm7UjChAN7/YjsC0qIyJeuSrJwvm6qb7tLN6Geq1FmCz1JnBOc3kaY+HCLjQBAfwG/CsgnasOdXMw==", + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.17.tgz", + "integrity": "sha512-yNMyrgEua2qyW7+trNNYhA6PeldRrBcwtLtlazkdtzcmkHMKECM/08bPF8HF2ZFuwHgD+8FQsdqd/DvJYQYjJg==", "dev": true, "requires": { "glob": "7.1.2", "gulp-chmod": "2.0.0", "gulp-filter": "5.1.0", "gulp-gunzip": "1.0.0", - "gulp-remote-src": "0.4.3", + "gulp-remote-src-vscode": "0.5.0", "gulp-symdest": "1.1.0", "gulp-untar": "0.0.6", "gulp-vinyl-zip": "2.1.0", "mocha": "4.1.0", - "request": "2.83.0", + "request": "2.85.0", "semver": "5.4.1", - "source-map-support": "0.5.0", - "url-parse": "1.2.0", + "source-map-support": "0.5.5", + "url-parse": "1.4.0", "vinyl-source-stream": "1.1.2" } }, @@ -5148,17 +4941,17 @@ "integrity": "sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o=" }, "vscode-languageclient": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.4.5.tgz", - "integrity": "sha1-YjAHKrB3IIXQm0j5m3nnxCHd+7c=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz", + "integrity": "sha512-GTQ+hSq/o4c/y6GYmyP9XNrVoIu0NFZ67KltSkqN+tO0eUNDIlrVNX+3DJzzyLhSsrctuGzuYWm3t87mNAcBmQ==", "requires": { - "vscode-languageserver-protocol": "3.5.0" + "vscode-languageserver-protocol": "3.5.1" } }, "vscode-languageserver-protocol": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz", - "integrity": "sha1-Bnxcvidwl5U5jRGWksl+u6FFIgk=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz", + "integrity": "sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==", "requires": { "vscode-jsonrpc": "3.5.0", "vscode-languageserver-types": "3.5.0" diff --git a/Extension/package.json b/Extension/package.json index 55780d27d..79ec1dd8e 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -1290,16 +1290,17 @@ "devDependencies": { "@types/mocha": "^2.2.43", "@types/node": "^8.0.46", + "gulp": "3.9.1", "gulp-env": "0.4.0", "gulp-mocha": "5.0.0", "gulp-tslint": "8.1.2", - "gulp": "3.9.1", "mocha": "^4.0.1", + "tslint": "5.8.0", "tslint-microsoft-contrib": "5.0.1", "tslint-no-unused-expression-chai": "0.0.3", - "tslint": "5.8.0", "typescript": "^2.5.3", - "vscode": "^1.1.14" + "vrsource-tslint-rules": "^5.8.2", + "vscode": "^1.1.17" }, "dependencies": { "http-proxy-agent": "~2.0.0", @@ -1479,4 +1480,4 @@ "binaries": [] } ] -} \ No newline at end of file +} diff --git a/Extension/src/Debugger/configurations.ts b/Extension/src/Debugger/configurations.ts index 6a5e5322a..26096af20 100644 --- a/Extension/src/Debugger/configurations.ts +++ b/Extension/src/Debugger/configurations.ts @@ -31,7 +31,7 @@ function formatString(format: string, args: string[]): string { return format; } -function CreateLaunchString(name: string, type: string, executable: string): string { +function createLaunchString(name: string, type: string, executable: string): string { return `"name": "${name}", "type": "${type}", "request": "launch", @@ -44,7 +44,7 @@ function CreateLaunchString(name: string, type: string, executable: string): str `; } -function CreateAttachString(name: string, type: string, executable: string): string { +function createAttachString(name: string, type: string, executable: string): string { return formatString(` "name": "${name}", "type": "${type}", @@ -53,7 +53,7 @@ function CreateAttachString(name: string, type: string, executable: string): str `, [type === "cppdbg" ? `${os.EOL}"program": "${"enter program name, for example $\{workspaceFolder\}/" + executable}",` : ""]); } -function CreateRemoteAttachString(name: string, type: string, executable: string): string { +function createRemoteAttachString(name: string, type: string, executable: string): string { return ` "name": "${name}", "type": "${type}", @@ -63,7 +63,7 @@ function CreateRemoteAttachString(name: string, type: string, executable: string `; } - function CreatePipeTransportString(pipeProgram: string, debuggerProgram: string, pipeArgs: string[] = []): string { + function createPipeTransportString(pipeProgram: string, debuggerProgram: string, pipeArgs: string[] = []): string { return ` "pipeTransport": { \t"debuggerPath": "/usr/bin/${debuggerProgram}", @@ -106,7 +106,7 @@ export class MIConfigurations extends Configuration { let name: string = `(${this.MIMode}) Launch`; let body: string = formatString(`{ -\t${indentJsonString(CreateLaunchString(name, this.miDebugger, this.executable))}, +\t${indentJsonString(createLaunchString(name, this.miDebugger, this.executable))}, \t"MIMode": "${this.MIMode}"{0}{1} }`, [this.miDebugger === "cppdbg" && os.platform() === "win32" ? `,${os.EOL}\t"miDebuggerPath": "/path/to/gdb"` : "", this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]); @@ -124,7 +124,7 @@ this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalPrope let name: string = `(${this.MIMode}) Attach`; let body: string = formatString(`{ -\t${indentJsonString(CreateAttachString(name, this.miDebugger, this.executable))}, +\t${indentJsonString(createAttachString(name, this.miDebugger, this.executable))}, \t"MIMode": "${this.MIMode}"{0}{1} }`, [this.miDebugger === "cppdbg" && os.platform() === "win32" ? `,${os.EOL}\t"miDebuggerPath": "/path/to/gdb"` : "", this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]); @@ -146,8 +146,8 @@ export class PipeTransportConfigurations extends Configuration { let body: string = formatString(` { -\t${indentJsonString(CreateLaunchString(name, this.miDebugger, this.executable))}, -\t${indentJsonString(CreatePipeTransportString(this.pipeProgram, this.MIMode))}, +\t${indentJsonString(createLaunchString(name, this.miDebugger, this.executable))}, +\t${indentJsonString(createPipeTransportString(this.pipeProgram, this.MIMode))}, \t"MIMode": "${this.MIMode}"{0} }`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]); @@ -165,8 +165,8 @@ export class PipeTransportConfigurations extends Configuration { let body: string = formatString(` { -\t${indentJsonString(CreateRemoteAttachString(name, this.miDebugger, this.executable))}, -\t${indentJsonString(CreatePipeTransportString(this.pipeProgram, this.MIMode))}, +\t${indentJsonString(createRemoteAttachString(name, this.miDebugger, this.executable))}, +\t${indentJsonString(createPipeTransportString(this.pipeProgram, this.MIMode))}, \t"MIMode": "${this.MIMode}"{0} }`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]); return { @@ -186,7 +186,7 @@ export class WindowsConfigurations extends Configuration { let body: string = ` { -\t${indentJsonString(CreateLaunchString(name, this.windowsDebugger, this.executable))} +\t${indentJsonString(createLaunchString(name, this.windowsDebugger, this.executable))} }`; return { @@ -204,7 +204,7 @@ export class WindowsConfigurations extends Configuration { let body: string = ` { -\t${indentJsonString(CreateAttachString(name, this.windowsDebugger, this.executable))} +\t${indentJsonString(createAttachString(name, this.windowsDebugger, this.executable))} }`; return { @@ -226,8 +226,8 @@ export class WSLConfigurations extends Configuration { let body: string = formatString(` { -\t${indentJsonString(CreateLaunchString(name, this.miDebugger, this.executable))}, -\t${indentJsonString(CreatePipeTransportString(this.bashPipeProgram, this.MIMode, ["-c"]))}{0} +\t${indentJsonString(createLaunchString(name, this.miDebugger, this.executable))}, +\t${indentJsonString(createPipeTransportString(this.bashPipeProgram, this.MIMode, ["-c"]))}{0} }`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]); return { @@ -243,8 +243,8 @@ export class WSLConfigurations extends Configuration { let body: string = formatString(` { -\t${indentJsonString(CreateRemoteAttachString(name, this.miDebugger, this.executable))}, -\t${indentJsonString(CreatePipeTransportString(this.bashPipeProgram, this.MIMode, ["-c"]))}{0} +\t${indentJsonString(createRemoteAttachString(name, this.miDebugger, this.executable))}, +\t${indentJsonString(createPipeTransportString(this.bashPipeProgram, this.MIMode, ["-c"]))}{0} }`, [this.additionalProperties ? `,${os.EOL}\t${indentJsonString(this.additionalProperties)}` : ""]); return { diff --git a/Extension/src/abTesting.ts b/Extension/src/abTesting.ts index e688aa580..31b94c2bf 100644 --- a/Extension/src/abTesting.ts +++ b/Extension/src/abTesting.ts @@ -35,7 +35,7 @@ function downloadCpptoolsJson(urlString): Promise { let request: ClientRequest = https.request({ host: parsedUrl.host, path: parsedUrl.path, - agent: util.GetHttpsProxyAgent(), + agent: util.getHttpsProxyAgent(), rejectUnauthorized: vscode.workspace.getConfiguration().get("http.proxyStrictSSL", true) }, (response) => { if (response.statusCode === 301 || response.statusCode === 302) { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index 17c26781e..89bd3c6d4 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -220,7 +220,7 @@ export function getDebugAdaptersPath(file: string): string { return path.resolve(getExtensionFilePath("debugAdapters"), file); } -export function GetHttpsProxyAgent(): HttpsProxyAgent { +export function getHttpsProxyAgent(): HttpsProxyAgent { let proxy: string = vscode.workspace.getConfiguration().get('http.proxy'); if (!proxy) { proxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy; diff --git a/Extension/src/packageManager.ts b/Extension/src/packageManager.ts index 1ee9ae564..d4cde1117 100644 --- a/Extension/src/packageManager.ts +++ b/Extension/src/packageManager.ts @@ -223,7 +223,7 @@ export class PackageManager { let options: https.RequestOptions = { host: parsedUrl.host, path: parsedUrl.path, - agent: util.GetHttpsProxyAgent(), + agent: util.getHttpsProxyAgent(), rejectUnauthorized: proxyStrictSSL }; diff --git a/Extension/tools/GenerateOptionsSchema.ts b/Extension/tools/GenerateOptionsSchema.ts index 0d1c5103f..ebf5180b4 100644 --- a/Extension/tools/GenerateOptionsSchema.ts +++ b/Extension/tools/GenerateOptionsSchema.ts @@ -6,14 +6,13 @@ import * as fs from 'fs'; import * as os from 'os'; -function AppendFieldsToObject(reference: any, obj: any) { - +function appendFieldsToObject(reference: any, obj: any): any { // Make sure it is an object type - if (typeof obj == 'object') { + if (typeof obj === 'object') { for (let referenceKey in reference) { // If key exists in original object and is an object. if (obj.hasOwnProperty(referenceKey)) { - obj[referenceKey] = AppendFieldsToObject(reference[referenceKey], obj[referenceKey]); + obj[referenceKey] = appendFieldsToObject(reference[referenceKey], obj[referenceKey]); } else { // Does not exist in current object context obj[referenceKey] = reference[referenceKey]; @@ -25,7 +24,7 @@ function AppendFieldsToObject(reference: any, obj: any) { } // Combines two object's fields, giving the parentDefault a higher precedence. -function MergeDefaults(parentDefault: any, childDefault: any) { +function mergeDefaults(parentDefault: any, childDefault: any): any { let newDefault: any = {}; for (let attrname in childDefault) { @@ -39,11 +38,11 @@ function MergeDefaults(parentDefault: any, childDefault: any) { return newDefault; } -function UpdateDefaults(object: any, defaults: any) { - if (defaults != null) { +function updateDefaults(object: any, defaults: any): any { + if (defaults !== null) { for (let key in object) { if (object[key].hasOwnProperty('type') && object[key].type === 'object' && object[key].properties !== null) { - object[key].properties = UpdateDefaults(object[key].properties, MergeDefaults(defaults, object[key].default)); + object[key].properties = updateDefaults(object[key].properties, mergeDefaults(defaults, object[key].default)); } else if (key in defaults) { object[key].default = defaults[key]; } @@ -53,7 +52,7 @@ function UpdateDefaults(object: any, defaults: any) { return object; } -function RefReplace(definitions: any, ref: any): any { +function refReplace(definitions: any, ref: any): any { // $ref is formatted as "#/definitions/ObjectName" let referenceStringArray: string[] = ref['$ref'].split('/'); @@ -61,13 +60,13 @@ function RefReplace(definitions: any, ref: any): any { let referenceName: string = referenceStringArray[referenceStringArray.length - 1]; // Make sure reference has replaced its own $ref fields and hope there are no recursive references. - definitions[referenceName] = ReplaceReferences(definitions, definitions[referenceName]); + definitions[referenceName] = replaceReferences(definitions, definitions[referenceName]); // Retrieve ObjectName from definitions. (TODO: Does not retrieve inner objects) // Need to deep copy, there are no functions in these objects. let reference: any = JSON.parse(JSON.stringify(definitions[referenceName])); - ref = AppendFieldsToObject(reference, ref); + ref = appendFieldsToObject(reference, ref); // Remove $ref field delete ref['$ref']; @@ -75,41 +74,32 @@ function RefReplace(definitions: any, ref: any): any { return ref; } -function ReplaceReferences(definitions: any, objects: any) { +function replaceReferences(definitions: any, objects: any): any { for (let key in objects) { if (objects[key].hasOwnProperty('$ref')) { - objects[key] = RefReplace(definitions, objects[key]); + objects[key] = refReplace(definitions, objects[key]); } // Recursively replace references if this object has properties. if (objects[key].hasOwnProperty('type') && objects[key].type === 'object' && objects[key].properties !== null) { - objects[key].properties = ReplaceReferences(definitions, objects[key].properties); - objects[key].properties = UpdateDefaults(objects[key].properties, objects[key].default); + objects[key].properties = replaceReferences(definitions, objects[key].properties); + objects[key].properties = updateDefaults(objects[key].properties, objects[key].default); } // Recursively replace references if the array has objects in items. - if (objects[key].hasOwnProperty('type') && objects[key].type === "array" && objects[key].items != null && objects[key].items.hasOwnProperty('$ref')) { - objects[key].items = RefReplace(definitions, objects[key].items); + if (objects[key].hasOwnProperty('type') && objects[key].type === "array" && objects[key].items !== null && objects[key].items.hasOwnProperty('$ref')) { + objects[key].items = refReplace(definitions, objects[key].items); } } return objects; } -function MergeReferences(baseDefinitions: any, additionalDefinitions: any) : void { - for (let key in additionalDefinitions) { - if (baseDefinitions[key]) { - throw `Error: '${key}' defined in multiple schema files.`; - } - baseDefinitions[key] = additionalDefinitions[key]; - } -} - -export function GenerateOptionsSchema() { +export function generateOptionsSchema(): void { let packageJSON: any = JSON.parse(fs.readFileSync('package.json').toString()); let schemaJSON: any = JSON.parse(fs.readFileSync('tools/OptionsSchema.json').toString()); - schemaJSON.definitions = ReplaceReferences(schemaJSON.definitions, schemaJSON.definitions); + schemaJSON.definitions = replaceReferences(schemaJSON.definitions, schemaJSON.definitions); // Hard Code adding in configurationAttributes launch and attach. // cppdbg @@ -120,7 +110,7 @@ export function GenerateOptionsSchema() { packageJSON.contributes.debuggers[1].configurationAttributes.launch = schemaJSON.definitions.CppvsdbgLaunchOptions; packageJSON.contributes.debuggers[1].configurationAttributes.attach = schemaJSON.definitions.CppvsdbgAttachOptions; - let content = JSON.stringify(packageJSON, null, 2); + let content: string = JSON.stringify(packageJSON, null, 2); if (os.platform() === 'win32') { content = content.replace(/\n/gm, "\r\n"); } diff --git a/Extension/tslint.json b/Extension/tslint.json index 999c3c3a0..d63a7cb89 100644 --- a/Extension/tslint.json +++ b/Extension/tslint.json @@ -1,6 +1,11 @@ { "rules": { "curly": true, + "ext-variable-name": [ + true, + ["class", "pascal"], + ["function", "camel"] + ], "file-header": [true, ".*"], "indent": [true, "spaces", 4], "new-parens": true, @@ -18,5 +23,9 @@ "typedef": [true, "variable-declaration", "call-signature"], "whitespace": [true, "check-branch", "check-operator", "check-separator", "check-preblock", "check-type"] }, - "rulesDirectory": ["node_modules/tslint-microsoft-contrib", "node_modules/tslint-no-unused-expression-chai/rules"] + "rulesDirectory": [ + "node_modules/tslint-microsoft-contrib", + "node_modules/tslint-no-unused-expression-chai/rules", + "node_modules/vrsource-tslint-rules/rules" + ] } From 7ea61221bcf74932597c7f1c916c21412c649ba8 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Mon, 7 May 2018 13:44:53 -0700 Subject: [PATCH 09/21] update release notes and don't enable recursive includes by default in new folders (#1948) * update release notes and don't enable recursive includes by default in new folders. * changelog bug --- Extension/CHANGELOG.md | 2 +- Extension/ReleaseNotes.html | 9 ++++++--- Extension/src/LanguageServer/configurations.ts | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 5befac5b4..04c4482a3 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -4,7 +4,7 @@ * Auto-complete for headers after typing `#include`. [#802](https://github.com/Microsoft/vscode-cpptools/issues/802) * Add support for recursive `includePath`, e.g. `${workspaceFolder}/**`. [#897](https://github.com/Microsoft/vscode-cpptools/issues/897) * Configuration improvements. [#1338](https://github.com/Microsoft/vscode-cpptools/issues/1338) - * Potentially addresses: [#368](https://github.com/Microsoft/vscode-cpptools/issues/368), [#410](https://github.com/Microsoft/vscode-cpptools/issues/410), [#1229](https://github.com/Microsoft/vscode-cpptools/issues/1229), [#1270](https://github.com/Microsoft/vscode-cpptools/issues/), [#1404](https://github.com/Microsoft/vscode-cpptools/issues/1404) + * Potentially addresses: [#368](https://github.com/Microsoft/vscode-cpptools/issues/368), [#410](https://github.com/Microsoft/vscode-cpptools/issues/410), [#1229](https://github.com/Microsoft/vscode-cpptools/issues/1229), [#1270](https://github.com/Microsoft/vscode-cpptools/issues/1270), [#1404](https://github.com/Microsoft/vscode-cpptools/issues/1404) * Add support for querying system includes/defines from WSL and Cygwin compilers. [#1845](https://github.com/Microsoft/vscode-cpptools/issues/1845), [#1736](https://github.com/Microsoft/vscode-cpptools/issues/1736) * Fix IntelliSense for WSL projects in Windows builds 17110 and greater. [#1694](https://github.com/Microsoft/vscode-cpptools/issues/1694) * Add snippets. [PR #1823](https://github.com/Microsoft/vscode-cpptools/pull/1823) diff --git a/Extension/ReleaseNotes.html b/Extension/ReleaseNotes.html index 38987ff5f..a21a15a9d 100644 --- a/Extension/ReleaseNotes.html +++ b/Extension/ReleaseNotes.html @@ -205,8 +205,11 @@

Microsoft C/C++ Extension for VS Code

-

March 2018 Update

-
Thank you for installing the C/C++ extension. In the March update, we finished our implementation of autocomplete for the default IntelliSense engine. We also added additional configuration settings for forced include files, specifying your compiler path and language standard to improve IntelliSense accuracy.
+

April 2018 Update

+
Thank you for installing the C/C++ extension. In the April update, we added autocomplete suggestions for #include statements.
+
+ We also added settings for configuration defaults and made some changes to improve the automatic configuration experience. If you set the "compilerPath" + property in c_cpp_properties.json, you no longer need to add system includes and defines to "includePath" or "defines"

Additional features and bug fixes are detailed in the full release notes.
@@ -231,9 +234,9 @@

Getting Started

diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index ed88c44bd..c0de15ac6 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -206,7 +206,7 @@ export class CppProperties { if (!settings.defaultIncludePath) { // We don't add system includes to the includePath anymore. The language server has this information. - configuration.includePath = ["${workspaceFolder}/**"].concat(this.vcpkgIncludes); + configuration.includePath = ["${workspaceFolder}"].concat(this.vcpkgIncludes); } if (!settings.defaultBrowsePath) { // We don't add system includes to the includePath anymore. The language server has this information. From ba65c4877cc84e4d8f89624de05dabd5bf07109b Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Tue, 8 May 2018 15:01:15 -0700 Subject: [PATCH 10/21] documentation updates for 0.17.0 (#1952) * documentation updates for 0.17.0 * updates to logging docs * PR feedback --- .../Archive/Enabling logging.md | 14 ++ Documentation/LanguageServer/Archive/MinGW.md | 76 ++++++++++ .../Archive/Windows Subsystem for Linux.md | 139 ++++++++++++++++++ .../Customizing Default Settings.md | 99 +++++++++++++ .../LanguageServer/Enabling logging.md | 16 +- Documentation/LanguageServer/FAQ.md | 16 +- Documentation/LanguageServer/MinGW.md | 125 +++------------- .../Windows Subsystem for Linux.md | 130 +++------------- .../LanguageServer/c_cpp_properties.json.md | 6 +- 9 files changed, 387 insertions(+), 234 deletions(-) create mode 100644 Documentation/LanguageServer/Archive/Enabling logging.md create mode 100644 Documentation/LanguageServer/Archive/MinGW.md create mode 100644 Documentation/LanguageServer/Archive/Windows Subsystem for Linux.md create mode 100644 Documentation/LanguageServer/Customizing Default Settings.md diff --git a/Documentation/LanguageServer/Archive/Enabling logging.md b/Documentation/LanguageServer/Archive/Enabling logging.md new file mode 100644 index 000000000..dd3faf1d1 --- /dev/null +++ b/Documentation/LanguageServer/Archive/Enabling logging.md @@ -0,0 +1,14 @@ +#### Old information (it still works, but is no longer recommended): + +Logging is controlled by environment variables and is disabled by default. To enable logging, launch VS Code from an environment that contains the following variables: + +``` +VSCODE_CPP_LOGDIR=c:\path\to\logfolder +VSCODE_CPP_LOGFILE_LEVEL=5 +``` + +When you open your folder in VS Code, we will create a **vscode.cpp.log.\.txt** file for each extension process launched (\ = process id). + +The log file level is a number that determines how much detail we'll log. Level 5 is generally detailed enough to give us information about what is going on in your session. We don't recommend you set this higher than 7 since the log quickly becomes cluttered with information that doesn't really help us diagnose your issues and actually makes it harder for us to spot problems. It may also slow down the extension considerably and make it harder for you to reproduce your problem. + +**Don't forget to remove the environment variables when you are finished providing us with the logs.** You wouldn't want the extension to needlessly spend CPU time and disk space writing data you don't need into log files. diff --git a/Documentation/LanguageServer/Archive/MinGW.md b/Documentation/LanguageServer/Archive/MinGW.md new file mode 100644 index 000000000..e7759aa9e --- /dev/null +++ b/Documentation/LanguageServer/Archive/MinGW.md @@ -0,0 +1,76 @@ +## Extension version 0.16.1 and earlier: + +For developers using MinGW on Windows, we recommend you start with the following **c_cpp_properties.json** template. Select "C/Cpp: Edit Configurations" from the command palette to create this file if you haven't already. + +In earlier versions of the extension, the `includePath` and a some system defines need to be set in order for IntelliSense to work properly. Note that you may have to change the MinGW version number to match what you have installed. Eg. `C:/MinGW/lib/gcc/mingw32/5.3.0/` instead of `C:/MinGW/lib/gcc/mingw32/6.3.0/`. + +```json +{ + "configurations": [ + { + "name": "MinGW", + "intelliSenseMode": "clang-x64", + "includePath": [ + "${workspaceRoot}", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++/mingw32", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++/backward", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include", + "C:/MinGW/include", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed" + ], + "defines": [ + "_DEBUG", + "__GNUC__=6", + "__cdecl=__attribute__((__cdecl__))" + ], + "browse": { + "path": [ + "C:/MinGW/lib/gcc/mingw32/6.3.0/include", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed", + "C:/MinGW/include/*", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + } + ] +} +``` + +The `includePath` above includes the system header paths that gcc uses in version 6.3.0 for C++ projects and matches the output of `"gcc -v -E -x c++ nul"`. The `intelliSenseMode` should be set to **"clang-x64"** to get MinGW projects to work properly with IntelliSense. The `__GNUC__=#` define should match the major version of the toolchain in your installation (6 in this example). + +For C projects, simply remove the C++ lines: + +```json +{ + "configurations": [ + { + "name": "MinGW", + "intelliSenseMode": "clang-x64", + "includePath": [ + "${workspaceRoot}", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include", + "C:/MinGW/include", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed" + ], + "defines": [ + "_DEBUG", + "__GNUC__=6", + "__cdecl=__attribute__((__cdecl__))" + ], + "browse": { + "path": [ + "C:/MinGW/lib/gcc/mingw32/6.3.0/include", + "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed", + "C:/MinGW/include/*", + "${workspaceRoot}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } + } + ] +} +``` diff --git a/Documentation/LanguageServer/Archive/Windows Subsystem for Linux.md b/Documentation/LanguageServer/Archive/Windows Subsystem for Linux.md new file mode 100644 index 000000000..e69453532 --- /dev/null +++ b/Documentation/LanguageServer/Archive/Windows Subsystem for Linux.md @@ -0,0 +1,139 @@ +# Windows Subsystem for Linux + +To use the Windows Subsystem for Linux with this extension you need to add a configuration to your **c_cpp_properties.json** file which adds the necessary header paths from within the WSL filesystem to the `includePath`. + +Select "C/Cpp: Edit Configurations" from the command palette to create the **c_cpp_properties.json** file if you haven't already. + +## Release + +For developers using Ubuntu with the current version of WSL released with the Fall Creators Update, you can add the following configuration template to your **c_cpp_properties.json** file. + +```json +{ + "name": "WSL", + "intelliSenseMode": "clang-x64", + "includePath": [ + "${workspaceRoot}", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu/c++/5", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5/backward", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include" + ], + "defines": [ + "__linux__", + "__x86_64__" + ], + "browse": { + "path": [ + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu/c++/5", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/*" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } +} +``` + +The `includePath` above includes the system header paths that gcc uses for C++ projects and matches the output of `gcc -v -E -x c++ - < /dev/null`. The intelliSenseMode should be set to **"clang-x64"** to get WSL projects to work properly with IntelliSense. + +Note that `${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/` is the path to the root of the Ubuntu filesystem. This will be different if you are using a different distro. You can discover the paths to your distro's filesystem by using this handy PowerShell command: + +```Powershell +PS R:\> ($(get-appxpackage).PackageFamilyName | findstr /i 'SUSE Ubuntu') -replace '^', "$`{localappdata`}/Packages/" + +${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc +${localappdata}/Packages/46932SUSE.openSUSELeap42.2_022rs5jcyhyac +${localappdata}/Packages/46932SUSE.SUSELinuxEnterpriseServer12SP2_022rs5jcyhyac +``` + +For C projects, simply remove the C++ lines: + +```json +{ + "name": "WSL", + "intelliSenseMode": "clang-x64", + "includePath": [ + "${workspaceRoot}", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include" + ], + "defines": [ + "__linux__", + "__x86_64__" + ], + "browse": { + "path": [ + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", + "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/*" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } +} +``` + +### Beta + +For developers using Bash on Ubuntu on Windows with the beta version of WSL from before the Fall Creators Update, you can add the following configuration template to your **c_cpp_properties.json** file. + +```json +{ + "name": "WSL (Beta)", + "intelliSenseMode": "clang-x64", + "includePath": [ + "${workspaceRoot}", + "${localappdata}/lxss/rootfs/usr/include/c++/5", + "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5", + "${localappdata}/lxss/rootfs/usr/include/c++/5/backward", + "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", + "${localappdata}/lxss/rootfs/usr/local/include", + "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", + "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu", + "${localappdata}/lxss/rootfs/usr/include" + ], + "defines": [ + "__linux__", + "__x86_64__" + ], + "browse": { + "path": [ + "${localappdata}/lxss/rootfs/usr/include/c++/5", + "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5", + "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", + "${localappdata}/lxss/rootfs/usr/local/include", + "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", + "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu", + "${localappdata}/lxss/rootfs/usr/include/*" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + } +} +``` + +The `includePath` above includes the system header paths that gcc uses for C++ projects and matches the output of `gcc -v -E -x c++ - < /dev/null`. The intelliSenseMode should be set to **"clang-x64"** to get WSL projects to work properly with IntelliSense. + +Note that `${localappdata}/lxss/rootfs/` is the path to the root of the filesystem for Bash on Ubuntu on Windows. + +For C projects, simply remove the C++ lines as in the previous example. + +--- + +With these configurations, you should be all set up to use the new IntelliSense engine for linting, memberlist autocomplete, and quick info (tooltips). Add `"C_Cpp.intelliSenseEngine": "Default"` to your **settings.json** file to try out the new IntelliSense engine. + +And remember to [heed the warnings of the Windows team about not creating or editing Linux files from a Windows app](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)! diff --git a/Documentation/LanguageServer/Customizing Default Settings.md b/Documentation/LanguageServer/Customizing Default Settings.md new file mode 100644 index 000000000..325fca22f --- /dev/null +++ b/Documentation/LanguageServer/Customizing Default Settings.md @@ -0,0 +1,99 @@ +# Customizing Default Settings + +In version 0.17.0 we introduced new settings that allow you to override the extension's default values for properties set in **c_cpp_properties.json**. + +## New VS Code settings + +The following `C_Cpp.default.*` settings map to each of the properties in a configuration block of **c_cpp_properties.json**. Namely: + +``` +C_Cpp.default.includePath : string[] +C_Cpp.default.defines : string[] +C_Cpp.default.compileCommands : string +C_Cpp.default.macFrameworkPath : string[] +C_Cpp.default.forcedIncludes : string[] +C_Cpp.default.intelliSenseMode : string +C_Cpp.default.compilerPath : string +C_Cpp.default.cStandard : c89 | c99 | c11 +C_Cpp.default.cppStandard : c++98 | c++03 | c++11 | c++14 | c++17 +C_Cpp.default.browse.path : string[] +C_Cpp.default.browse.databaseFilename : string +C_Cpp.default.browse.limitSymbolsToIncludedHeaders : boolean +``` + +These settings have all of the benefits of VS Code settings, meaning that they can have default, "User", "Workspace", and "Folder" values. So you can set a global value for `C_Cpp.default.cppStandard` in your "User" settings and have it apply to all of the folders you open. If any one folder needs a different value, you can override the value by adding a "Folder" or "Workspace" value. + +This property of VS Code settings allows you to configure each of your workspaces independently - making the **c_cpp_properties.json** file optional. + +## Updated **c_cpp_properties.json** syntax + +A special variable has been added to the accepted syntax of **c_cpp_properties.json** that will instruct the extension to insert the value from the VS Code settings mentioned above. If you set the value of any setting in **c_cpp_properties.json** to "${default}" it will instruct the extension to read the VS Code default setting for that property and insert it. For example: + +``` +"configurations": [ + { + "name": "Win32", + "includePath": [ + "additional/paths", + "${default}" + ], + "defines": [ + "${default}", + ], + "macFrameworkPath": [ + "${default}", + "additional/paths" + ], + "forceInclude": [ + "${default}", + "additional/paths" + ], + "compileCommands": "${default}", + "browse": { + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "${default}", + "path": [ + "${default}", + "additional/paths" + ] + }, + "intelliSenseMode": "${default}", + "cStandard": "${default}", + "cppStandard": "${default}", + "compilerPath": "${default}" + } +], +``` + +Take note that for the properties that accept string[], the syntax proposed above allows you to augment the VS Code setting with additional values, thus allowing you to have common paths listed in the VS Code settings and configuration-specific settings in **c_cpp_properties.json**. + +If a property is missing from **c_cpp_properties.json**, the extension will use the value in the VS Code setting. If a developer assigns values to all of the settings that apply for a given folder, then **c_cpp_properties.json** could be removed from the .vscode folder as it will no longer be needed. + +### System includes + +A new setting will be added that allows you specify the system include path separate from the folder's include path. If this setting has a value, then the system include path the extension gets from the compiler specified in the `compilerPath` setting will not be added to the path array that the extension uses for IntelliSense. We may want to provide a VS Code command to populate this value from the compiler's default for users who are interested in using it in case they want to make some modifications to the defaults. + +``` +C_Cpp.default.systemIncludePath : string[] +``` + +### Include Path Resolution Strategies + +The extension determines the includePath to send to the IntelliSense engine in the following manner: + +1. If `compileCommands` has a valid value and the file open in the editor is in the database, use the compile command in the database entry to determine the include path and defines. + * The system include path and defines are determined using the following logic (in order): + 1. If `systemIncludePath` has a value, use it (continue to the next step to seach for system defines). + 2. If `compilerPath` is valid, query it. + 3. Interpret the first argument in the command as the compiler and attempt to query it. + 4. If `compilerPath` is `""`, use an empty array for system include path and defines. + 5. If `compilerPath` is undefined, look for a compiler on the system and query it. + +2. If `compileCommands` is invalid or the current file is not listed in the database, use the `includePath` and `defines` properties in the configuration for IntelliSense. + * The system include path and defines are determined using the following logic (in order): + 1. If `systemIncludePath` has a value, use it (continue to the next step to seach for system defines). + 2. If `compilerPath` is valid, query it. + 3. If `compilerPath` is `""`, use an empty array for system include path and defines (they are assumed to be in the `includePath` and `defines` for the current config already). + 4. If `compilerPath` is undefined, look for a compiler on the system and query it. + +System includes should no longer be added to the `"includePath"` or `"browse.path"` variables. If the extension detects any system include paths in the `"includePath"` property it will silently remove them so that it can ensure system include paths are added last and in the correct order (this is especially important for GCC/Clang). In a future update we may add a notification message to the extension to remind developers to remove system include paths from their `"includePath"` and `'browse.path"` as they will be ignored. diff --git a/Documentation/LanguageServer/Enabling logging.md b/Documentation/LanguageServer/Enabling logging.md index 0daf6ba58..2f8f654dc 100644 --- a/Documentation/LanguageServer/Enabling logging.md +++ b/Documentation/LanguageServer/Enabling logging.md @@ -6,19 +6,7 @@ As of version 0.14.0 of the extension, logging information is now delivered dire ![image](https://user-images.githubusercontent.com/12818240/31898313-b32ff284-b7cd-11e7-97f5-89df93b5d9de.png) -#### Old information (it still works, but is no longer recommended): +VS Code organizes the logging from different extensions to improve readability so you must select the "C/C++" option in the log filter selector to see logging from the C/C++ extension: - -Logging is controlled by environment variables and is disabled by default. To enable logging, launch VS Code from an environment that contains the following variables: +![image](https://user-images.githubusercontent.com/12818240/39769357-d6673bea-52a0-11e8-86c6-3be91618e8fc.png) -``` -VSCODE_CPP_LOGDIR=c:\path\to\logfolder -VSCODE_CPP_LOGFILE_LEVEL=5 -``` - -When you open your folder in VS Code, we will create a **vscode.cpp.log.\.txt** file for each extension process launched (\ = process id). - -The log file level is a number that determines how much detail we'll log. Level 5 is generally detailed enough to give us information about what is going on in your session. We don't recommend you set this higher than 7 since the log quickly becomes cluttered with information that doesn't really help us diagnose your issues and actually makes it harder for us to spot problems. It may also slow down the extension considerably and make it harder for you to reproduce your problem. - -**Don't forget to remove the environment variables when you are finished providing us with the logs.** You wouldn't want the extension to needlessly spend CPU time and disk space writing data you don't need into log files. - diff --git a/Documentation/LanguageServer/FAQ.md b/Documentation/LanguageServer/FAQ.md index cfb1f37e5..bd16cbb40 100644 --- a/Documentation/LanguageServer/FAQ.md +++ b/Documentation/LanguageServer/FAQ.md @@ -3,6 +3,7 @@ * [How do I get IntelliSense to work correctly?](#how-do-i-get-intellisense-to-work-correctly) * [Why do I see red squiggles under Standard Library types?](#why-do-i-see-red-squiggles-under-standard-library-types) * [How do I get the new IntelliSense to work with MinGW on Windows?](#how-do-i-get-the-new-intellisense-to-work-with-mingw-on-windows) +* [How do I get the new IntelliSense to work with the Windows Subsystem for Linux?](#how-do-i-get-the-new-intellisense-to-work-with-the-windows-subsystem-for-linux) * [What is the difference between `"includePath"` and `"browse.path"` in **c_cpp_properties.json**?](#what-is-the-difference-between-includepath-and-browsepath-in-c_cpp_propertiesjson) * [How do I re-create the IntelliSense database?](#how-do-i-re-create-the-intellisense-database) @@ -27,11 +28,22 @@ If you want IntelliSense to operate on your files even when all #include directi ## Why do I see red squiggles under Standard Library types? -The most common reason for this is missing or sorted include paths. If you are using a compiler in the GCC family, the system includes that you add to your `"includePath"` in **c_cpp_properties.json** should match the output of the following command: `gcc -Wp,-v -E -xc -x c++ /dev/null` (replace 'gcc' with whichever compiler you are using). GCC and its relatives require the paths to be in a specific order too, so sorting the paths for aesthetics will likely result in incorrect IntelliSense results. +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. + +**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**. +* If you are using Clang for Windows, set `"intelliSenseMode": "msvc-x64"`, and `"compilerPath"` in **c_cpp_properties.json** to the path to your compiler. ## How do I get the new IntelliSense to work with MinGW on Windows? -Since MinGW is a relative of GCC, Microsoft mode compilation (which is the default on Windows) doesn't work very well with it. To use GCC/CLang mode, set the `"intelliSenseMode"` property in your **c_cpp_properties.json** file to `"clang-x64"`. An example **c_cpp_properties.json** [is shared here for your convenience](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/MinGW.md). +The page discussing configuration with MinGW is [here](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/MinGW.md). + +## How do I get the new IntelliSense to work with the Windows Subsystem for Linux? + +The page discussing configuration with WSL is [here](https://github.com/Microsoft/vscode-cpptools/blob/master/Documentation/LanguageServer/Windows%20Subsystem%20for%20Linux.md). ## What is the difference between `"includePath"` and `"browse.path"` in **c_cpp_properties.json**? diff --git a/Documentation/LanguageServer/MinGW.md b/Documentation/LanguageServer/MinGW.md index 483e7750d..41de4a0d9 100644 --- a/Documentation/LanguageServer/MinGW.md +++ b/Documentation/LanguageServer/MinGW.md @@ -1,113 +1,32 @@ -For developers using MinGW on Windows, we recommend you start with the following **c_cpp_properties.json** template. Select "C/Cpp: Edit Configurations" from the command palette to create this file if you haven't already. +# MinGW -## With extension version 0.16.1 and higher: +To use MinGW on Windows, we recommend you add the following configuration to your **c_cpp_properties.json** file. Select "C/Cpp: Edit Configurations" from the command palette to create this file if you haven't already. -Starting with version 0.16.1, if you set the `compilerPath` property and change `intelliSenseMode` to `clang-x64`, you no longer need to copy the system include path or defines to `includePath` and `defines` to enable IntelliSense to work properly. However, `browse.path` still needs to be updated manually to add the system include paths to enable code browsing for system headers. For example: +## Extension version 0.17.0 and higher: -```json -{ - "configurations": [ - { - "name": "MinGW", - "intelliSenseMode": "clang-x64", - "compilerPath": "C:/MinGW/bin/gcc.exe", - "includePath": [ - "${workspaceFolder}" - ], - "defines": [ - "_DEBUG" - ], - "browse": { - "path": [ - "C:/MinGW/lib/gcc/mingw32/6.3.0/include", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed", - "C:/MinGW/include/*", - "${workspaceFolder}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - }, - "cStandard": "c11", - "cppStandard": "c++17" - } - ], - "version": 3 -} -``` - -Note that the `browse.path` setting is not automatically updated at this time and you may have to change the MinGW version number to match what you have installed. If you are using a different MinGW distribution, the values for `compilerPath` and `browse.path` will likely be different than what is written here. - -## With extension version 0.16.0 and earlier: - -In earlier versions of the extension, the `includePath` and a some system defines need to be set in order for IntelliSense to work properly. Note that you may have to change the MinGW version number to match what you have installed. Eg. `C:/MinGW/lib/gcc/mingw32/5.3.0/` instead of `C:/MinGW/lib/gcc/mingw32/6.3.0/`. +When you set the `compilerPath` property and change `intelliSenseMode` to `clang-x64`, you no longer need to copy the system include path or defines to `includePath`, `browse.path`, or `defines` to enable IntelliSense to work properly. For example: ```json { - "configurations": [ - { - "name": "MinGW", - "intelliSenseMode": "clang-x64", - "includePath": [ - "${workspaceRoot}", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++/mingw32", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include/c++/backward", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include", - "C:/MinGW/include", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed" - ], - "defines": [ - "_DEBUG", - "__GNUC__=6", - "__cdecl=__attribute__((__cdecl__))" - ], - "browse": { - "path": [ - "C:/MinGW/lib/gcc/mingw32/6.3.0/include", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed", - "C:/MinGW/include/*", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - } - ] + "name": "MinGW", + "intelliSenseMode": "clang-x64", + "compilerPath": "C:/mingw64/bin/gcc.exe", + "includePath": [ + "${workspaceFolder}" + ], + "defines": [], + "browse": { + "path": [ + "${workspaceFolder}" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + }, + "cStandard": "c11", + "cppStandard": "c++17" } ``` -The `includePath` above includes the system header paths that gcc uses in version 6.3.0 for C++ projects and matches the output of `"gcc -v -E -x c++ nul"`. The `intelliSenseMode` should be set to **"clang-x64"** to get MinGW projects to work properly with IntelliSense. The `__GNUC__=#` define should match the major version of the toolchain in your installation (6 in this example). +## Extension version 0.16.1 and earlier: -For C projects, simply remove the C++ lines: - -```json -{ - "configurations": [ - { - "name": "MinGW", - "intelliSenseMode": "clang-x64", - "includePath": [ - "${workspaceRoot}", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include", - "C:/MinGW/include", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed" - ], - "defines": [ - "_DEBUG", - "__GNUC__=6", - "__cdecl=__attribute__((__cdecl__))" - ], - "browse": { - "path": [ - "C:/MinGW/lib/gcc/mingw32/6.3.0/include", - "C:/MinGW/lib/gcc/mingw32/6.3.0/include-fixed", - "C:/MinGW/include/*", - "${workspaceRoot}" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } - } - ] -} -``` +If you have an older version of the C/C++ extension installed, use [these instructions](Archive/MinGW.md) instead. diff --git a/Documentation/LanguageServer/Windows Subsystem for Linux.md b/Documentation/LanguageServer/Windows Subsystem for Linux.md index 334944dad..a28a01ca8 100644 --- a/Documentation/LanguageServer/Windows Subsystem for Linux.md +++ b/Documentation/LanguageServer/Windows Subsystem for Linux.md @@ -1,139 +1,43 @@ # Windows Subsystem for Linux +> **Note:** If you are on **build 17110 of Windows or higher**, you must use version 0.17.0 or higher for IntelliSense to work. The Windows team turned on case-sensitive folders for the WSL environment and the C/C++ extension doesn't support case-sensitive folders until version 0.17.0. + To use the Windows Subsystem for Linux with this extension you need to add a configuration to your **c_cpp_properties.json** file which adds the necessary header paths from within the WSL filesystem to the `includePath`. Select "C/Cpp: Edit Configurations" from the command palette to create the **c_cpp_properties.json** file if you haven't already. -## Release +## With extension version 0.17.0 and higher: -For developers using Ubuntu with the current version of WSL released with the Fall Creators Update, you can add the following configuration template to your **c_cpp_properties.json** file. +In **c_cpp_properties.json** you can directly address your WSL compiler and include paths by using *nix-style paths and we will do the conversion to Windows paths for you. If you have multiple distros installed, we disambiguate the `compilerPath` by picking the one marked as Default when you run `wslconfig.exe /l` in a CMD or PowerShell window. We continue to support Windows-style paths for these properties as outlined in the [archived instructions](Archive/Windows%20Subsystem%20for%20Linux.md) if you prefer to use those. ```json { "name": "WSL", "intelliSenseMode": "clang-x64", + "compilerPath": "/usr/bin/gcc", "includePath": [ - "${workspaceRoot}", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu/c++/5", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5/backward", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include" - ], - "defines": [ - "__linux__", - "__x86_64__" + "${workspaceFolder}", + "/mnt/c/libraries/lib1/include", + "C:/libraries/lib2/include" ], + "defines": [], "browse": { "path": [ - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/c++/5", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu/c++/5", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/*" + "${workspaceFolder}", + "/mnt/c/libraries" ], "limitSymbolsToIncludedHeaders": true, "databaseFilename": "" - } + }, + "cStandard": "c11", + "cppStandard": "c++17" } ``` -The `includePath` above includes the system header paths that gcc uses for C++ projects and matches the output of `gcc -v -E -x c++ - < /dev/null`. The intelliSenseMode should be set to **"clang-x64"** to get WSL projects to work properly with IntelliSense. - -Note that `${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/` is the path to the root of the Ubuntu filesystem. This will be different if you are using a different distro. You can discover the paths to your distro's filesystem by using this handy PowerShell command: - -```Powershell -PS R:\> ($(get-appxpackage).PackageFamilyName | findstr /i 'SUSE Ubuntu') -replace '^', "$`{localappdata`}/Packages/" - -${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc -${localappdata}/Packages/46932SUSE.openSUSELeap42.2_022rs5jcyhyac -${localappdata}/Packages/46932SUSE.SUSELinuxEnterpriseServer12SP2_022rs5jcyhyac -``` +## Earlier versions of the extension: -For C projects, simply remove the C++ lines: - -```json -{ - "name": "WSL", - "intelliSenseMode": "clang-x64", - "includePath": [ - "${workspaceRoot}", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include" - ], - "defines": [ - "__linux__", - "__x86_64__" - ], - "browse": { - "path": [ - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/local/include", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/x86_64-linux-gnu", - "${localappdata}/Packages/CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc/LocalState/rootfs/usr/include/*" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } -} -``` - -## Beta - -For developers using Bash on Ubuntu on Windows with the beta version of WSL from before the Fall Creators Update, you can add the following configuration template to your **c_cpp_properties.json** file. - -```json -{ - "name": "WSL (Beta)", - "intelliSenseMode": "clang-x64", - "includePath": [ - "${workspaceRoot}", - "${localappdata}/lxss/rootfs/usr/include/c++/5", - "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5", - "${localappdata}/lxss/rootfs/usr/include/c++/5/backward", - "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", - "${localappdata}/lxss/rootfs/usr/local/include", - "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", - "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu", - "${localappdata}/lxss/rootfs/usr/include" - ], - "defines": [ - "__linux__", - "__x86_64__" - ], - "browse": { - "path": [ - "${localappdata}/lxss/rootfs/usr/include/c++/5", - "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu/c++/5", - "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include", - "${localappdata}/lxss/rootfs/usr/local/include", - "${localappdata}/lxss/rootfs/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed", - "${localappdata}/lxss/rootfs/usr/include/x86_64-linux-gnu", - "${localappdata}/lxss/rootfs/usr/include/*" - ], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "" - } -} -``` - -The `includePath` above includes the system header paths that gcc uses for C++ projects and matches the output of `gcc -v -E -x c++ - < /dev/null`. The intelliSenseMode should be set to **"clang-x64"** to get WSL projects to work properly with IntelliSense. - -Note that `${localappdata}/lxss/rootfs/` is the path to the root of the filesystem for Bash on Ubuntu on Windows. - -For C projects, simply remove the C++ lines as in the previous example. +If you are on a build of Windows prior to 17110 and you have an older version of the C/C++ extension installed, use [these instructions](Archive/Windows%20Subsystem%20for%20Linux.md) instead. --- -With these configurations, you should be all set up to use the new IntelliSense engine for linting, memberlist autocomplete, and quick info (tooltips). Add `"C_Cpp.intelliSenseEngine": "Default"` to your **settings.json** file to try out the new IntelliSense engine. - -And remember to [heed the warnings of the Windows team about not creating or editing Linux files from a Windows app](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)! +Remember to [heed the warnings of the Windows team about not creating or editing Linux files from a Windows app](https://blogs.msdn.microsoft.com/commandline/2016/11/17/do-not-change-linux-files-using-windows-apps-and-tools/)! diff --git a/Documentation/LanguageServer/c_cpp_properties.json.md b/Documentation/LanguageServer/c_cpp_properties.json.md index 23a2848a3..ad6dc915e 100644 --- a/Documentation/LanguageServer/c_cpp_properties.json.md +++ b/Documentation/LanguageServer/c_cpp_properties.json.md @@ -1,5 +1,7 @@ # `c_cpp_properties.json` Reference Guide +> See also: [Customizing Default Settings](Customizing%20Default%20Settings.md) + ### Example ```json @@ -23,7 +25,7 @@ } } ], - "version": 3 + "version": 4 } ``` @@ -67,7 +69,7 @@ * #### `compileCommands` (optional) If `"C_Cpp.intelliSenseEngine"` is set to "Default" in your settings file, the includes and defines discovered in this file will be used instead of the values set for `includePath` and `defines`. If the compile commands database does not contain an entry for the translation unit that corresponds to the file you opened in the editor, then a warning message will appear and the extension will use the `includePath` and `defines` settings instead. - *For more information about the file format, see the [Clang documentation](https://clang.llvm.org/docs/JSONCompilationDatabase.html). Some build systems, such as CMake, [simplify generating this file](https://cmake.org/cmake/help/v3.5/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html).* + >For more information about the file format, see the [Clang documentation](https://clang.llvm.org/docs/JSONCompilationDatabase.html). Some build systems, such as CMake, [simplify generating this file](https://cmake.org/cmake/help/v3.5/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html). * #### `browse` The set of properties used when `"C_Cpp.intelliSenseEngine"` is set to `"Tag Parser"` (also referred to as "fuzzy" IntelliSense, or the "browse" engine). These properties are also used by the Go To Definition/Declaration features, or when the "Default" IntelliSense engine is unable to resolve the #includes in your source files. From 79871a658705f7f199d25c5559de6be603a242d3 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Tue, 8 May 2018 16:10:30 -0700 Subject: [PATCH 11/21] update c_cpp_properties.json reference --- .../LanguageServer/c_cpp_properties.json.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Documentation/LanguageServer/c_cpp_properties.json.md b/Documentation/LanguageServer/c_cpp_properties.json.md index ad6dc915e..814f2bb33 100644 --- a/Documentation/LanguageServer/c_cpp_properties.json.md +++ b/Documentation/LanguageServer/c_cpp_properties.json.md @@ -6,11 +6,18 @@ ```json { + "env" : { + "defaultIncludePath": [ + "${workspaceFolder}", + "${workspaceFolder}/include" + ], + "myCompilerPath": "/usr/local/bin/gcc-7" + }, "configurations": [ { "name": "Win32", "intelliSenseMode": "msvc-x64", - "includePath": [ "${workspaceFolder}" ], + "includePath": [ "${defaultIncludePath}", "/another/path" ], "macFrameworkPath": [ "/System/Library/Frameworks" ], "defines": [ "FOO", "BAR=100" ], "forcedInclude": [ "${workspaceFolder}/include/config.h" ], @@ -31,6 +38,9 @@ ## Top-level properties +* #### `env` + An array of user-defined variables that will be available for substitution in the configurations via the standard environment variable syntax: `${}` or `${env:}`. Strings and arrays of strings are accepted. + * #### `configurations` An array of configuration objects that provide the IntelliSense engine with information about your project and your preferences. By default, the extension creates 3 configurations for you, one each for Linux, Mac, and Windows, but it is not required to keep them all. You may also add additional configurations if necessary. From a190707f67712854df60df79369ef9806d38c8be Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Wed, 9 May 2018 15:11:29 -0700 Subject: [PATCH 12/21] update telemetry for settings changes (#1973) update telemetry for settings changes --- Extension/package.json | 5 +- Extension/src/LanguageServer/client.ts | 102 +--------- .../src/LanguageServer/configurations.ts | 2 + .../src/LanguageServer/settingsTracker.ts | 190 ++++++++++++++++++ 4 files changed, 200 insertions(+), 99 deletions(-) create mode 100644 Extension/src/LanguageServer/settingsTracker.ts diff --git a/Extension/package.json b/Extension/package.json index 79ec1dd8e..778e259fd 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -168,10 +168,11 @@ "None", "Error", "Warning", - "Information" + "Information", + "Debug" ], "default": "Error", - "description": "The verbosity of logging in the Output Panel. The order of levels from least verbose to most verbose is: None < Error < Warning < Information.", + "description": "The verbosity of logging in the Output Panel. The order of levels from least verbose to most verbose is: None < Error < Warning < Information < Debug.", "scope": "resource" }, "C_Cpp.autoAddFileAssociations": { diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 20ca0228f..624363413 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -22,6 +22,7 @@ import { DataBinding } from './dataBinding'; import minimatch = require("minimatch"); import * as logger from '../logger'; import { updateLanguageConfigurations } from './extension'; +import { SettingsTracker, getTracker } from './settingsTracker'; let ui: UI; @@ -115,97 +116,8 @@ const DebugProtocolNotification: NotificationType const DebugLogNotification: NotificationType = new NotificationType('cpptools/debugLog'); const InactiveRegionNotification: NotificationType = new NotificationType('cpptools/inactiveRegions'); -const maxSettingLengthForTelemetry: number = 50; -let previousCppSettings: { [key: string]: any } = {}; let failureMessageShown: boolean = false; -/** - * track settings changes for telemetry - */ -function collectSettingsForTelemetry(filter: (key: string, val: string, settings: vscode.WorkspaceConfiguration) => boolean, resource: vscode.Uri): { [key: string]: string } { - let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", resource); - let result: { [key: string]: string } = {}; - - for (let key in settings) { - if (settings.inspect(key).defaultValue === undefined) { - continue; // ignore methods and settings that don't exist - } - let val: any = settings.get(key); - if (val instanceof Object) { - val = JSON.stringify(val, null, 2); - } - - // Skip values that don't match the setting's enum. - let curSetting: any = util.packageJson.contributes.configuration.properties["C_Cpp." + key]; - if (curSetting) { - let curEnum: any[] = curSetting["enum"]; - if (curEnum && curEnum.indexOf(val) === -1) { - continue; - } - } - - if (filter(key, val, settings)) { - previousCppSettings[key] = val; - switch (key.toLowerCase()) { - case "clang_format_path": { - continue; - } - case "clang_format_style": - case "clang_format_fallbackstyle": { - let newKey: string = key + "2"; - if (val) { - switch (String(val).toLowerCase()) { - case "visual studio": - case "llvm": - case "google": - case "chromium": - case "mozilla": - case "webkit": - case "file": - case "none": { - result[newKey] = String(previousCppSettings[key]); - break; - } - default: { - result[newKey] = "..."; - break; - } - } - } else { - result[newKey] = "null"; - } - key = newKey; - break; - } - default: { - if (key.startsWith("default.")) { - continue; // Don't log c_cpp_properties.json defaults since they may contain PII. - } - result[key] = String(previousCppSettings[key]); - break; - } - } - if (result[key].length > maxSettingLengthForTelemetry) { - result[key] = result[key].substr(0, maxSettingLengthForTelemetry) + "..."; - } - } - } - - return result; -} - -function initializeSettingsCache(resource: vscode.Uri): void { - collectSettingsForTelemetry(() => true, resource); -} - -function getNonDefaultSettings(resource: vscode.Uri): { [key: string]: string } { - let filter: (key: string, val: string, settings: vscode.WorkspaceConfiguration) => boolean = (key: string, val: string, settings: vscode.WorkspaceConfiguration) => { - return val !== settings.inspect(key).defaultValue; - }; - initializeSettingsCache(resource); - return collectSettingsForTelemetry(filter, resource); -} - interface ClientModel { isTagParsing: DataBinding; isUpdatingIntelliSense: DataBinding; @@ -265,6 +177,7 @@ class DefaultClient implements Client { private crashTimes: number[] = []; private isSupported: boolean = true; private inactiveRegionsDecorations = new Map(); + private settingsTracker: SettingsTracker; // The "model" that is displayed via the UI (status bar). private model: ClientModel = { @@ -334,7 +247,8 @@ class DefaultClient implements Client { // Once this is set, we don't defer any more callbacks. this.languageClient = languageClient; - telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", getNonDefaultSettings(this.RootUri)); + this.settingsTracker = getTracker(this.RootUri); + telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings()); failureMessageShown = false; // Listen for messages from the language server. @@ -447,13 +361,7 @@ class DefaultClient implements Client { } public onDidChangeSettings(): void { - // This relies on getNonDefaultSettings being called first. - console.assert(Object.keys(previousCppSettings).length > 0); - - let filter: (key: string, val: string) => boolean = (key: string, val: string) => { - return !(key in previousCppSettings) || val !== previousCppSettings[key]; - }; - let changedSettings: { [key: string] : string} = collectSettingsForTelemetry(filter, this.RootUri); + let changedSettings: { [key: string] : string} = this.settingsTracker.getChangedSettings(); if (Object.keys(changedSettings).length > 0) { if (changedSettings["commentContinuationPatterns"]) { diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index c0de15ac6..0ae1b287e 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -8,6 +8,7 @@ import * as path from 'path'; import * as fs from "fs"; import * as vscode from 'vscode'; import * as util from '../common'; +import * as telemetry from '../telemetry'; import { PersistentFolderState } from './persistentState'; import { CppSettings } from './settings'; const configVersion: number = 4; @@ -313,6 +314,7 @@ export class CppProperties { public addToIncludePathCommand(path: string): void { this.handleConfigurationEditCommand((document: vscode.TextDocument) => { + telemetry.logLanguageServerEvent("addToIncludePath"); this.parsePropertiesFile(); // Clear out any modifications we may have made internally. let config: Configuration = this.configurationJson.configurations[this.CurrentConfiguration]; if (config.includePath === undefined) { diff --git a/Extension/src/LanguageServer/settingsTracker.ts b/Extension/src/LanguageServer/settingsTracker.ts new file mode 100644 index 000000000..1850efbe6 --- /dev/null +++ b/Extension/src/LanguageServer/settingsTracker.ts @@ -0,0 +1,190 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. + * See 'LICENSE' in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict'; + +import * as vscode from 'vscode'; +import * as util from '../common'; + +/** + * track settings changes for telemetry + */ +type FilterFunction = (key: string, val: string, settings: vscode.WorkspaceConfiguration) => boolean; +type KeyValuePair = { key: string; value: string }; + +const maxSettingLengthForTelemetry: number = 50; +let cache: SettingsTracker = undefined; + +export class SettingsTracker { + private previousCppSettings: { [key: string]: any } = {}; + private resource: vscode.Uri; + + constructor(resource: vscode.Uri) { + this.resource = resource; + this.collectSettings(() => true); + } + + public getUserModifiedSettings(): { [key: string]: string } { + let filter: FilterFunction = (key: string, val: string, settings: vscode.WorkspaceConfiguration) => { + return !this.areEqual(val, settings.inspect(key).defaultValue); + }; + return this.collectSettings(filter); + } + + public getChangedSettings(): { [key: string]: string } { + let filter: FilterFunction = (key: string, val: string) => { + return !(key in this.previousCppSettings) || !this.areEqual(val, this.previousCppSettings[key]); + }; + return this.collectSettings(filter); + } + + private collectSettings(filter: FilterFunction): { [key: string]: string } { + let settings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("C_Cpp", this.resource); + let result: { [key: string]: string } = {}; + + for (let key in settings) { + let val: any = this.getSetting(settings, key); + if (val === undefined) { + continue; + } + if (val instanceof Object && !(val instanceof Array)) { + for (let subKey in val) { + let newKey: string = key + "." + subKey; + let subVal: any = this.getSetting(settings, newKey); + if (subVal === undefined) { + continue; + } + let entry: KeyValuePair = this.filterAndSanitize(newKey, subVal, settings, filter); + if (entry && entry.key && entry.value) { + result[entry.key] = entry.value; + } + } + continue; + } + + let entry: KeyValuePair = this.filterAndSanitize(key, val, settings, filter); + if (entry && entry.key && entry.value) { + result[entry.key] = entry.value; + } + } + + return result; + } + + private getSetting(settings: vscode.WorkspaceConfiguration, key: string): any { + // Ignore methods and settings that don't exist + if (settings.inspect(key).defaultValue !== undefined) { + let val: any = settings.get(key); + if (val instanceof Object) { + return val; // It's a sub-section. + } + + // Only return values that match the setting's type and enum (if applicable). + let curSetting: any = util.packageJson.contributes.configuration.properties["C_Cpp." + key]; + if (curSetting) { + let type: string = this.typeMatch(val, curSetting["type"]); + if (type) { + if (type !== "string") { + return val; + } + let curEnum: any[] = curSetting["enum"]; + if (curEnum && curEnum.indexOf(val) === -1) { + return ""; + } + return val; + } + } + } + return undefined; + } + + private typeMatch(value: any, type?: string | string[]): string { + if (type) { + if (type instanceof Array) { + for (let i: number = 0; i < type.length; i++) { + let t: string = type[i]; + if (t) { + if (typeof value === t) { + return t; + } + if (t === "array" && value instanceof Array) { + return t; + } + if (t === "null" && value === null) { + return t; + } + } + } + } else if (typeof type === "string" && typeof value === type) { + return type; + } + } + return undefined; + } + + private filterAndSanitize(key: string, val: any, settings: vscode.WorkspaceConfiguration, filter: FilterFunction): KeyValuePair { + if (filter(key, val, settings)) { + let value: string; + this.previousCppSettings[key] = val; + switch (key) { + case "clang_format_style": + case "clang_format_fallbackStyle": { + let newKey: string = key + "2"; + if (val) { + switch (String(val).toLowerCase()) { + case "visual studio": + case "llvm": + case "google": + case "chromium": + case "mozilla": + case "webkit": + case "file": + case "none": { + value = String(this.previousCppSettings[key]); + break; + } + default: { + value = "..."; + break; + } + } + } else { + value = "null"; + } + key = newKey; + break; + } + case "commentContinuationPatterns": { + value = this.areEqual(val, settings.inspect(key).defaultValue) ? "" : "..."; // Track whether it's being used, but nothing specific about it. + break; + } + default: { + if (key === "clang_format_path" || key.startsWith("default.")) { + value = this.areEqual(val, settings.inspect(key).defaultValue) ? "" : "..."; // Track whether it's being used, but nothing specific about it. + } else { + value = String(this.previousCppSettings[key]); + } + } + } + if (value && value.length > maxSettingLengthForTelemetry) { + value = value.substr(0, maxSettingLengthForTelemetry) + "..."; + } + return {key: key, value: value}; + } + } + + private areEqual(value1: any, value2: any): boolean { + if (value1 instanceof Object && value2 instanceof Object) { + return JSON.stringify(value1) === JSON.stringify(value2); + } + return value1 === value2; + } +} + +export function getTracker(resource: vscode.Uri): SettingsTracker { + if (!cache) { + cache = new SettingsTracker(resource); + } + return cache; +} From 8f8ed52aae2ca10da8ce44f0224f222c06a0c2a6 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 11 May 2018 12:33:42 -0700 Subject: [PATCH 13/21] Fix the file watcher (#1983) --- Extension/src/LanguageServer/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 624363413..608f20121 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -450,7 +450,7 @@ class DefaultClient implements Client { if (this.rootFolder) { // WARNING: The default limit on Linux is 8k, so for big directories, this can cause file watching to fail. this.rootPathFileWatcher = vscode.workspace.createFileSystemWatcher( - path.join(this.RootPath, "*"), + "**/*", false /*ignoreCreateEvents*/, true /*ignoreChangeEvents*/, false /*ignoreDeleteEvents*/); From fbfb83ac3028f74db89610dcbc95805b28b4a5ec Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 11 May 2018 14:08:45 -0700 Subject: [PATCH 14/21] Update Enabling logging.md --- Documentation/LanguageServer/Archive/Enabling logging.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/LanguageServer/Archive/Enabling logging.md b/Documentation/LanguageServer/Archive/Enabling logging.md index dd3faf1d1..60b94d037 100644 --- a/Documentation/LanguageServer/Archive/Enabling logging.md +++ b/Documentation/LanguageServer/Archive/Enabling logging.md @@ -11,4 +11,6 @@ When you open your folder in VS Code, we will create a **vscode.cpp.log.\. The log file level is a number that determines how much detail we'll log. Level 5 is generally detailed enough to give us information about what is going on in your session. We don't recommend you set this higher than 7 since the log quickly becomes cluttered with information that doesn't really help us diagnose your issues and actually makes it harder for us to spot problems. It may also slow down the extension considerably and make it harder for you to reproduce your problem. +**Note:** You will likely need to reload the window or close VS Code to flush the contents of the log file since we do not flush the log after every call. If your log file seems to be empty, try reloading the window after you have followed the steps to reproduce your issue. + **Don't forget to remove the environment variables when you are finished providing us with the logs.** You wouldn't want the extension to needlessly spend CPU time and disk space writing data you don't need into log files. From 7f10e90a6f0728be48d6d8e13ca3d5172e34edd2 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 11 May 2018 16:38:30 -0700 Subject: [PATCH 15/21] update https-proxy-agent version (#1984) --- Extension/package-lock.json | 8 ++++---- Extension/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Extension/package-lock.json b/Extension/package-lock.json index 2d4c5472c..4e4562359 100644 --- a/Extension/package-lock.json +++ b/Extension/package-lock.json @@ -883,7 +883,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -2288,9 +2288,9 @@ } }, "https-proxy-agent": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz", - "integrity": "sha512-LK6tQUR/VOkTI6ygAfWUKKP95I+e6M1h7N3PncGu1CATHCnex+CAv9ttR0lbHu1Uk2PXm/WoAHFo6JCGwMjVMw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "requires": { "agent-base": "4.1.2", "debug": "3.1.0" diff --git a/Extension/package.json b/Extension/package.json index 778e259fd..dd174b029 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -1305,7 +1305,7 @@ }, "dependencies": { "http-proxy-agent": "~2.0.0", - "https-proxy-agent": "~2.1.0", + "https-proxy-agent": "~2.2.0", "jsonc-parser": "^1.0.0", "minimatch": "~3.0.4", "mkdirp": "~0.5.1", From d1e90b507f033a5a151f4dd185b6b3e7c32d79f6 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Mon, 14 May 2018 23:02:35 -0700 Subject: [PATCH 16/21] Remove outdated logic from getConfigIndexForPlatform (#1992) --- .../src/LanguageServer/configurations.ts | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 0ae1b287e..25a7bf901 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -267,17 +267,13 @@ export class CppProperties { } private getConfigIndexForPlatform(config: any): number { - if (this.configurationJson.configurations.length > 3) { - return this.configurationJson.configurations.length - 1; // Default to the last custom configuration. - } - let nodePlatform: NodeJS.Platform = process.platform; let plat: string; - if (nodePlatform === 'linux') { - plat = "Linux"; - } else if (nodePlatform === 'darwin') { + if (process.platform === 'darwin') { plat = "Mac"; - } else if (nodePlatform === 'win32') { + } else if (process.platform === 'win32') { plat = "Win32"; + } else { + plat = "Linux"; } for (let i: number = 0; i < this.configurationJson.configurations.length; i++) { if (config.configurations[i].name === plat) { @@ -293,14 +289,12 @@ export class CppProperties { return "clang-x64"; } else if (name === "Win32") { return "msvc-x64"; - } else { + } else if (process.platform === 'win32') { // Custom configs default to the OS's preference. - let nodePlatform: NodeJS.Platform = process.platform; - if (nodePlatform === 'linux' || nodePlatform === 'darwin') { - return "clang-x64"; - } + return "msvc-x64"; + } else { + return "clang-x64"; } - return "msvc-x64"; } private includePathConverted(): boolean { @@ -595,7 +589,7 @@ export class CppProperties { for (let i: number = 0; i < this.configurationJson.configurations.length; i++) { let config: Configuration = this.configurationJson.configurations[i]; // Look for Mac configs and extra configs on Mac systems - if (config.name === "Mac" || (process.platform === "darwin" && config.name !== "Win32" && config.name !== "Linux")) { + if (config.name === "Mac" || (process.platform === 'darwin' && config.name !== "Win32" && config.name !== "Linux")) { if (config.macFrameworkPath === undefined) { config.macFrameworkPath = [ "/System/Library/Frameworks", From 74b5867660c5b7c133c838d878b4e41438d773ad Mon Sep 17 00:00:00 2001 From: Sean McManus Date: Tue, 15 May 2018 15:48:06 -0700 Subject: [PATCH 17/21] Seanmcm/0 17 1 changelog (#1996) * Updates for 0.17.1. * Add C++17 fixes for msvc-x64. --- Extension/CHANGELOG.md | 10 ++++++++++ Extension/bin/msvc.32.intel.json | 6 +++--- Extension/bin/msvc.64.darwin.msvc.json | 6 +++--- Extension/bin/msvc.64.intel.json | 6 +++--- Extension/bin/msvc.64.linux.msvc.json | 6 +++--- Extension/package.json | 10 +++++----- Extension/src/LanguageServer/configurations.ts | 2 +- 7 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 04c4482a3..dca55bc14 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,5 +1,14 @@ # C/C++ for Visual Studio Code Change Log +## Version 0.17.1: May 15, 2018 +* Fix IntelliSense update slowness when using recursive includes. [#1949](https://github.com/Microsoft/vscode-cpptools/issues/1949) +* Fix code navigation failure after switching between WSL and non-WSL configs. [#1958](https://github.com/Microsoft/vscode-cpptools/issues/1958) +* Fix extension crash when the `includePath` is a file or the root drive. [#1979](https://github.com/Microsoft/vscode-cpptools/issues/1979), [#1965](https://github.com/Microsoft/vscode-cpptools/issues/1965) +* Fix IntelliSense crash in `have_member_access_from_class_scope`. [#1763](https://github.com/Microsoft/vscode-cpptools/issues/1763) +* Fix `#include` completion bugs. [#1959](https://github.com/Microsoft/vscode-cpptools/issues/1959), [#1970](https://github.com/Microsoft/vscode-cpptools/issues/1970) +* Add `Debug` value for `loggingLevel` (previously the hidden value `"6"`). +* Fix C++17 features not being fully enabled with msvc-x64 mode. [#1990](https://github.com/Microsoft/vscode-cpptools/issues/1990) + ## Version 0.17.0: May 7, 2018 * Auto-complete for headers after typing `#include`. [#802](https://github.com/Microsoft/vscode-cpptools/issues/802) * Add support for recursive `includePath`, e.g. `${workspaceFolder}/**`. [#897](https://github.com/Microsoft/vscode-cpptools/issues/897) @@ -9,6 +18,7 @@ * Fix IntelliSense for WSL projects in Windows builds 17110 and greater. [#1694](https://github.com/Microsoft/vscode-cpptools/issues/1694) * Add snippets. [PR #1823](https://github.com/Microsoft/vscode-cpptools/pull/1823) * Add support for vcpkg. [PR #1886](https://github.com/Microsoft/vscode-cpptools/pull/1886) +* Add support for custom variables in `c_cpp_properties.json` via `env`. [#1857](https://github.com/Microsoft/vscode-cpptools/issues/1857), [#368](https://github.com/Microsoft/vscode-cpptools/issues/368) * Stop automatically adding `/usr/include` to the `includePath`. [#1819](https://github.com/Microsoft/vscode-cpptools/issues/1819) * Fix wrong configuration being used if there are four or more. [#1599](https://github.com/Microsoft/vscode-cpptools/issues/1599) * Fix `c_cpp_properties.json` requiring write access. [#1790](https://github.com/Microsoft/vscode-cpptools/issues/1790) diff --git a/Extension/bin/msvc.32.intel.json b/Extension/bin/msvc.32.intel.json index 96173ff5f..3764ec4f3 100644 --- a/Extension/bin/msvc.32.intel.json +++ b/Extension/bin/msvc.32.intel.json @@ -4,11 +4,11 @@ "--microsoft", "--microsoft_bugs", "--microsoft_version", - "1900", + "1914", "--pack_alignment", "8", - "-D_MSC_VER=1900", - "-D_MSC_FULL_VER=190024210", + "-D_MSC_VER=1914", + "-D_MSC_FULL_VER=191426428", "-D_MSC_BUILD=0", "-D_M_IX86=600", "-D_M_IX86_FP=2" diff --git a/Extension/bin/msvc.64.darwin.msvc.json b/Extension/bin/msvc.64.darwin.msvc.json index fdd6bdc53..b5b6e703a 100644 --- a/Extension/bin/msvc.64.darwin.msvc.json +++ b/Extension/bin/msvc.64.darwin.msvc.json @@ -4,12 +4,12 @@ "--microsoft", "--microsoft_bugs", "--microsoft_version", - "1900", + "1914", "--pack_alignment", "8", "-D_CPPUNWIND=1", - "-D_MSC_VER=1900", - "-D_MSC_FULL_VER=190024210", + "-D_MSC_VER=1914", + "-D_MSC_FULL_VER=191426428", "-D_MSC_BUILD=0", "-D_M_X64=100", "-D_AMD64=100" diff --git a/Extension/bin/msvc.64.intel.json b/Extension/bin/msvc.64.intel.json index fdd6bdc53..b5b6e703a 100644 --- a/Extension/bin/msvc.64.intel.json +++ b/Extension/bin/msvc.64.intel.json @@ -4,12 +4,12 @@ "--microsoft", "--microsoft_bugs", "--microsoft_version", - "1900", + "1914", "--pack_alignment", "8", "-D_CPPUNWIND=1", - "-D_MSC_VER=1900", - "-D_MSC_FULL_VER=190024210", + "-D_MSC_VER=1914", + "-D_MSC_FULL_VER=191426428", "-D_MSC_BUILD=0", "-D_M_X64=100", "-D_AMD64=100" diff --git a/Extension/bin/msvc.64.linux.msvc.json b/Extension/bin/msvc.64.linux.msvc.json index fdd6bdc53..b5b6e703a 100644 --- a/Extension/bin/msvc.64.linux.msvc.json +++ b/Extension/bin/msvc.64.linux.msvc.json @@ -4,12 +4,12 @@ "--microsoft", "--microsoft_bugs", "--microsoft_version", - "1900", + "1914", "--pack_alignment", "8", "-D_CPPUNWIND=1", - "-D_MSC_VER=1900", - "-D_MSC_FULL_VER=190024210", + "-D_MSC_VER=1914", + "-D_MSC_FULL_VER=191426428", "-D_MSC_BUILD=0", "-D_M_X64=100", "-D_AMD64=100" diff --git a/Extension/package.json b/Extension/package.json index dd174b029..9a51a2241 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2,7 +2,7 @@ "name": "cpptools", "displayName": "C/C++", "description": "C/C++ IntelliSense, debugging, and code browsing.", - "version": "0.17.0-master", + "version": "0.17.1-master", "publisher": "ms-vscode", "preview": true, "icon": "LanguageCCPP_color_128x.png", @@ -1319,7 +1319,7 @@ "runtimeDependencies": [ { "description": "C/C++ language components (Linux / x86_64)", - "url": "https://go.microsoft.com/fwlink/?linkid=872599", + "url": "https://go.microsoft.com/fwlink/?linkid=874214", "platforms": [ "linux" ], @@ -1333,7 +1333,7 @@ }, { "description": "C/C++ language components (Linux / x86)", - "url": "https://go.microsoft.com/fwlink/?linkid=872600", + "url": "https://go.microsoft.com/fwlink/?linkid=874215", "platforms": [ "linux" ], @@ -1349,7 +1349,7 @@ }, { "description": "C/C++ language components (OS X)", - "url": "https://go.microsoft.com/fwlink/?linkid=872601", + "url": "https://go.microsoft.com/fwlink/?linkid=874216", "platforms": [ "darwin" ], @@ -1360,7 +1360,7 @@ }, { "description": "C/C++ language components (Windows)", - "url": "https://go.microsoft.com/fwlink/?linkid=872602", + "url": "https://go.microsoft.com/fwlink/?linkid=874217", "platforms": [ "win32" ], diff --git a/Extension/src/LanguageServer/configurations.ts b/Extension/src/LanguageServer/configurations.ts index 25a7bf901..25257f549 100644 --- a/Extension/src/LanguageServer/configurations.ts +++ b/Extension/src/LanguageServer/configurations.ts @@ -207,7 +207,7 @@ export class CppProperties { if (!settings.defaultIncludePath) { // We don't add system includes to the includePath anymore. The language server has this information. - configuration.includePath = ["${workspaceFolder}"].concat(this.vcpkgIncludes); + configuration.includePath = ["${workspaceFolder}/**"].concat(this.vcpkgIncludes); } if (!settings.defaultBrowsePath) { // We don't add system includes to the includePath anymore. The language server has this information. From c9473b21d463c4a6d8a1a6731192a6a80c0d6876 Mon Sep 17 00:00:00 2001 From: Sean McManus Date: Wed, 16 May 2018 19:57:30 -0700 Subject: [PATCH 18/21] Update changelog. (#2003) --- Extension/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index dca55bc14..b4eb3e306 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,6 +1,6 @@ # C/C++ for Visual Studio Code Change Log -## Version 0.17.1: May 15, 2018 +## Version 0.17.1: May 17, 2018 * Fix IntelliSense update slowness when using recursive includes. [#1949](https://github.com/Microsoft/vscode-cpptools/issues/1949) * Fix code navigation failure after switching between WSL and non-WSL configs. [#1958](https://github.com/Microsoft/vscode-cpptools/issues/1958) * Fix extension crash when the `includePath` is a file or the root drive. [#1979](https://github.com/Microsoft/vscode-cpptools/issues/1979), [#1965](https://github.com/Microsoft/vscode-cpptools/issues/1965) @@ -8,6 +8,7 @@ * Fix `#include` completion bugs. [#1959](https://github.com/Microsoft/vscode-cpptools/issues/1959), [#1970](https://github.com/Microsoft/vscode-cpptools/issues/1970) * Add `Debug` value for `loggingLevel` (previously the hidden value `"6"`). * Fix C++17 features not being fully enabled with msvc-x64 mode. [#1990](https://github.com/Microsoft/vscode-cpptools/issues/1990) +* Fix IntelliSense interprocess deadlocks. [#1407](https://github.com/Microsoft/vscode-cpptools/issues/1407), [#1777](https://github.com/Microsoft/vscode-cpptools/issues/1777) ## Version 0.17.0: May 7, 2018 * Auto-complete for headers after typing `#include`. [#802](https://github.com/Microsoft/vscode-cpptools/issues/802) From 01efb1a58467f1bdad85c95d36b0cd4c6d54a0b3 Mon Sep 17 00:00:00 2001 From: Sherry Shi Date: Fri, 18 May 2018 11:03:08 -0700 Subject: [PATCH 19/21] Allow other VS Code extensions to provide custom intellisense configurations. (#1804) --- Extension/src/LanguageServer/client.ts | 124 ++++++++++++++++-- Extension/src/LanguageServer/extension.ts | 52 +++++++- .../src/LanguageServer/protocolFilter.ts | 23 ++-- Extension/src/api.ts | 112 ++++++++++++++++ Extension/src/cppTools.ts | 18 +++ Extension/src/main.ts | 9 +- 6 files changed, 306 insertions(+), 32 deletions(-) create mode 100644 Extension/src/api.ts create mode 100644 Extension/src/cppTools.ts diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 608f20121..fc51309e5 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -22,6 +22,8 @@ import { DataBinding } from './dataBinding'; import minimatch = require("minimatch"); import * as logger from '../logger'; import { updateLanguageConfigurations } from './extension'; +import { CustomConfigurationProvider, SourceFileConfigurationItem } from '../api'; +import { CancellationTokenSource } from 'vscode'; import { SettingsTracker, getTracker } from './settingsTracker'; let ui: UI; @@ -86,6 +88,10 @@ interface DecorationRangesPair { ranges: vscode.Range[]; } +interface CustomConfigurationParams { + configurationItems: SourceFileConfigurationItem[]; +} + // Requests const NavigationListRequest: RequestType = new RequestType('cpptools/requestNavigationList'); const GoToDeclarationRequest: RequestType = new RequestType('cpptools/goToDeclaration'); @@ -105,6 +111,7 @@ const ChangeFolderSettingsNotification: NotificationType = new NotificationType('cpptools/didChangeCompileCommands'); const ChangeSelectedSettingNotification: NotificationType = new NotificationType('cpptools/didChangeSelectedSetting'); const IntervalTimerNotification: NotificationType = new NotificationType('cpptools/onIntervalTimer'); +const CustomConfigurationNotification: NotificationType = new NotificationType('cpptools/didChangeCustomConfiguration'); // Notifications from the server const ReloadWindowNotification: NotificationType = new NotificationType('cpptools/reloadWindow'); @@ -138,13 +145,19 @@ export interface Client { TrackedDocuments: Set; onDidChangeSettings(): void; onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void; + onDidChangeCustomConfigurations(provider: CustomConfigurationProvider): void; takeOwnership(document: vscode.TextDocument): void; + runBlockingTask(task: Thenable): Thenable; + runBlockingThenableWithTimeout(thenable: () => Thenable, ms: number, tokenSource?: CancellationTokenSource): Thenable; + requestWhenReady(request: () => Thenable): Thenable; + notifyWhenReady(notify: () => void): void; requestGoToDeclaration(): Thenable; requestSwitchHeaderSource(rootPath: string, fileName: string): Thenable; requestNavigationList(document: vscode.TextDocument): Thenable; activeDocumentChanged(document: vscode.TextDocument): void; activate(): void; selectionChanged(selection: vscode.Position): void; + sendCustomConfigurations(configs: SourceFileConfigurationItem[]): void; resetDatabase(): void; deactivate(): void; pauseParsing(): void; @@ -215,12 +228,14 @@ class DefaultClient implements Client { } /** - * All public methods on this class must be guarded by the "onReady" promise. Requests and notifications received before the client is - * ready are executed after this promise is resolved. + * All public methods on this class must be guarded by the "pendingTask" promise. Requests and notifications received before the task is + * complete are executed after this promise is resolved. * @see requestWhenReady(request) * @see notifyWhenReady(notify) */ - private onReadyPromise: Thenable; + + private pendingTask: Thenable; + private pendingRequests: number = 0; constructor(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder) { try { @@ -232,7 +247,7 @@ class DefaultClient implements Client { ui = getUI(); ui.bind(this); - this.onReadyPromise = languageClient.onReady().then(() => { + this.runBlockingTask(languageClient.onReady()).then(() => { this.configuration = new configs.CppProperties(this.RootUri); this.configuration.ConfigurationsChanged((e) => this.onConfigurationsChanged(e)); this.configuration.SelectionChanged((e) => this.onSelectedConfigurationChanged(e)); @@ -385,6 +400,23 @@ class DefaultClient implements Client { } } + public onDidChangeCustomConfigurations(provider: CustomConfigurationProvider): void { + let documentUris: vscode.Uri[] = []; + this.trackedDocuments.forEach(document => documentUris.push(document.uri)); + + let tokenSource: CancellationTokenSource = new CancellationTokenSource(); + + if (documentUris.length === 0) { + return; + } + + this.runBlockingThenableWithTimeout(() => { + return provider.provideConfigurations(documentUris, tokenSource.token); + }, 1000, tokenSource).then((configs: SourceFileConfigurationItem[]) => { + this.sendCustomConfigurations(configs); + }); + } + /** * Take ownership of a document that was previously serviced by another client. * This process involves sending a textDocument/didOpen message to the server so @@ -405,24 +437,75 @@ class DefaultClient implements Client { } /************************************************************************************* - * wait until the language client is ready for use before attempting to send messages + * wait until the all pendingTasks are complete (e.g. language client is ready for use) + * before attempting to send messages *************************************************************************************/ + public runBlockingTask(task: Thenable): Thenable { + if (this.pendingTask) { + return this.requestWhenReady(() => { return task; }); + } else { + this.pendingTask = task; + return task.then((result) => { + this.pendingTask = undefined; + return result; + }, (error) => { + this.pendingTask = undefined; + throw error; + }); + } + } - private requestWhenReady(request: () => Thenable): Thenable { - if (this.languageClient) { + public runBlockingThenableWithTimeout(thenable: () => Thenable, ms: number, tokenSource?: CancellationTokenSource): Thenable { + let timer: NodeJS.Timer; + // Create a promise that rejects in milliseconds + let timeout: Promise = new Promise((resolve, reject) => { + timer = setTimeout(() => { + clearTimeout(timer); + if (tokenSource) { + tokenSource.cancel(); + } + reject("Timed out in " + ms + "ms."); + }, ms); + }); + + // Returns a race between our timeout and the passed in promise + return this.runBlockingTask(Promise.race([thenable(), timeout]).then((result: any) => { + clearTimeout(timer); + return result; + }, (error: any) => { + throw error; + })); + } + + public requestWhenReady(request: () => Thenable): Thenable { + if (this.pendingTask === undefined) { return request(); - } else if (this.isSupported && this.onReadyPromise) { - return this.onReadyPromise.then(() => request()); + } else if (this.isSupported && this.pendingTask) { + this.pendingRequests++; + return this.pendingTask.then(() => { + this.pendingRequests--; + if (this.pendingRequests === 0) { + this.pendingTask = undefined; + } + return request(); + }); } else { - return Promise.reject("Unsupported client"); + return Promise.reject("Unsupported client"); } } - private notifyWhenReady(notify: () => void): void { - if (this.languageClient) { + public notifyWhenReady(notify: () => void): void { + if (this.pendingTask === undefined) { notify(); - } else if (this.isSupported && this.onReadyPromise) { - this.onReadyPromise.then(() => notify()); + } else if (this.isSupported && this.pendingTask) { + this.pendingRequests++; + this.pendingTask.then(() => { + this.pendingRequests--; + if (this.pendingRequests === 0) { + this.pendingTask = undefined; + } + notify(); + }); } } @@ -763,6 +846,13 @@ class DefaultClient implements Client { this.notifyWhenReady(() => this.languageClient.sendNotification(ChangeCompileCommandsNotification, params)); } + public sendCustomConfigurations(configs: SourceFileConfigurationItem[]): void { + let params: CustomConfigurationParams = { + configurationItems: configs + }; + this.notifyWhenReady(() => this.languageClient.sendNotification(CustomConfigurationNotification, params)); + } + /********************************************* * command handlers *********************************************/ @@ -853,7 +943,13 @@ class NullClient implements Client { TrackedDocuments = new Set(); onDidChangeSettings(): void {} onDidChangeVisibleTextEditors(editors: vscode.TextEditor[]): void {} + onDidChangeCustomConfigurations(provider: CustomConfigurationProvider): void {} takeOwnership(document: vscode.TextDocument): void {} + runBlockingTask(task: Thenable): Thenable { return; } + runBlockingThenableWithTimeout(thenable: () => Thenable, ms: number, tokenSource?: CancellationTokenSource): Thenable { return; } + requestWhenReady(request: () => Thenable): Thenable { return; } + notifyWhenReady(notify: () => void): void {} + sendCustomConfigurations(configs: SourceFileConfigurationItem[]): void {} requestGoToDeclaration(): Thenable { return Promise.resolve(); } requestSwitchHeaderSource(rootPath: string, fileName: string): Thenable { return Promise.resolve(""); } requestNavigationList(document: vscode.TextDocument): Thenable { return Promise.resolve(""); } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 6029c2dd5..8f1f36790 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -6,6 +6,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; +import { CancellationTokenSource } from "vscode-jsonrpc"; import * as fs from 'fs'; import * as util from '../common'; import * as telemetry from '../telemetry'; @@ -15,6 +16,7 @@ import { ClientCollection } from './clientCollection'; import { CppSettings } from './settings'; import { PersistentWorkspaceState } from './persistentState'; import { getLanguageConfig } from './languageConfig'; +import { CustomConfigurationProvider, SourceFileConfigurationItem } from '../api'; import * as os from 'os'; let prevCrashFile: string; @@ -27,6 +29,7 @@ let intervalTimer: NodeJS.Timer; let realActivationOccurred: boolean = false; let tempCommands: vscode.Disposable[] = []; let activatedPreviously: PersistentWorkspaceState; +let customConfigurationProviders: CustomConfigurationProvider[] = []; /** * activate: set up the extension for language services @@ -41,7 +44,7 @@ export function activate(activationEventOccurred: boolean): void { activatedPreviously.Value = false; realActivation(); } - + registerCommands(); tempCommands.push(vscode.workspace.onDidOpenTextDocument(d => onDidOpenTextDocument(d))); @@ -74,6 +77,37 @@ export function activate(activationEventOccurred: boolean): void { } } +export function registerCustomConfigurationProvider(provider: CustomConfigurationProvider): void { + customConfigurationProviders.push(provider); + + // Request for configurations from the provider only if realActivationOccurred. + // Otherwise, the request will be sent when realActivation is called. + if (realActivationOccurred) { + onDidChangeCustomConfiguration(provider); + } +} + +export async function provideCustomConfiguration(document: vscode.TextDocument, client: Client): Promise { + let tokenSource: CancellationTokenSource = new CancellationTokenSource(); + return client.runBlockingThenableWithTimeout(async () => { + // Loop through registered providers until one is able to service the current document + for (let i: number = 0; i < customConfigurationProviders.length; i++) { + if (await customConfigurationProviders[i].canProvideConfiguration(document.uri)) { + return customConfigurationProviders[i].provideConfigurations([document.uri]); + } + } + return Promise.reject("No providers found for " + document.uri); + }, 1000, tokenSource).then((configs: SourceFileConfigurationItem[]) => { + if (configs !== null && configs.length > 0) { + client.sendCustomConfigurations(configs); + } + }); +} + +export function onDidChangeCustomConfiguration(customConfigurationProvider: CustomConfigurationProvider): void { + clients.forEach((client: Client) => client.onDidChangeCustomConfigurations(customConfigurationProvider)); +} + function onDidOpenTextDocument(document: vscode.TextDocument): void { if (document.languageId === "c" || document.languageId === "cpp") { onActivationEvent(); @@ -108,6 +142,10 @@ function realActivation(): void { onDidChangeActiveTextEditor(vscode.window.activeTextEditor); } + // There may have already been registered CustomConfigurationProviders. + // Request for configurations from those providers. + customConfigurationProviders.forEach(provider => onDidChangeCustomConfiguration(provider)); + disposables.push(vscode.workspace.onDidChangeConfiguration(onDidChangeSettings)); disposables.push(vscode.workspace.onDidSaveTextDocument(onDidSaveTextDocument)); disposables.push(vscode.window.onDidChangeActiveTextEditor(onDidChangeActiveTextEditor)); @@ -172,7 +210,7 @@ function onDidChangeTextEditorSelection(event: vscode.TextEditorSelectionChangeE if (!event.textEditor || !vscode.window.activeTextEditor || event.textEditor.document.uri !== vscode.window.activeTextEditor.document.uri || (event.textEditor.document.languageId !== "cpp" && event.textEditor.document.languageId !== "c")) { return; - } + } if (activeDocument !== event.textEditor.document.uri.toString()) { // For some strange (buggy?) reason we don't reliably get onDidChangeActiveTextEditor callbacks. @@ -304,7 +342,7 @@ function selectClient(): Thenable { function onResetDatabase(): void { onActivationEvent(); /* need to notify the affected client(s) */ - selectClient().then(client => client.resetDatabase(), rejected => {}); + selectClient().then(client => client.resetDatabase(), rejected => { }); } function onSelectConfiguration(): void { @@ -323,7 +361,7 @@ function onEditConfiguration(): void { if (!isFolderOpen()) { vscode.window.showInformationMessage('Open a folder first to edit configurations'); } else { - selectClient().then(client => client.handleConfigurationEditCommand(), rejected => {}); + selectClient().then(client => client.handleConfigurationEditCommand(), rejected => { }); } } @@ -406,17 +444,17 @@ function onShowReleaseNotes(): void { function onPauseParsing(): void { onActivationEvent(); - selectClient().then(client => client.pauseParsing(), rejected => {}); + selectClient().then(client => client.pauseParsing(), rejected => { }); } function onResumeParsing(): void { onActivationEvent(); - selectClient().then(client => client.resumeParsing(), rejected => {}); + selectClient().then(client => client.resumeParsing(), rejected => { }); } function onShowParsingCommands(): void { onActivationEvent(); - selectClient().then(client => client.handleShowParsingCommands(), rejected => {}); + selectClient().then(client => client.handleShowParsingCommands(), rejected => { }); } function onTakeSurvey(): void { diff --git a/Extension/src/LanguageServer/protocolFilter.ts b/Extension/src/LanguageServer/protocolFilter.ts index bf677034b..5e35e8d0e 100644 --- a/Extension/src/LanguageServer/protocolFilter.ts +++ b/Extension/src/LanguageServer/protocolFilter.ts @@ -7,30 +7,35 @@ import { Middleware } from 'vscode-languageclient'; import { ClientCollection } from './clientCollection'; import { Client } from './client'; +import { provideCustomConfiguration } from './extension'; export function createProtocolFilter(me: Client, clients: ClientCollection): Middleware { // Disabling lint for invoke handlers /* tslint:disable */ - let defaultHandler: (data: any, callback: (data: any) => void) => void = (data, callback: (data) => void) => { if (clients.ActiveClient === me) { callback(data); } }; - let invoke1 = (a, callback: (a) => any) => { if (clients.ActiveClient === me) { return callback(a); } return null; }; - let invoke2 = (a, b, callback: (a, b) => any) => { if (clients.ActiveClient === me) { return callback(a, b); } return null; }; - let invoke3 = (a, b, c, callback: (a, b, c) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c); } return null; }; - let invoke4 = (a, b, c, d, callback: (a, b, c, d) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c, d); } return null; }; - let invoke5 = (a, b, c, d, e, callback: (a, b, c, d, e) => any) => { if (clients.ActiveClient === me) { return callback(a, b, c, d, e); } return null; }; + let defaultHandler: (data: any, callback: (data: any) => void) => void = (data, callback: (data) => void) => { if (clients.ActiveClient === me) {me.notifyWhenReady(() => callback(data));}}; + let invoke1 = (a, callback: (a) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(callback(a)); } return null; }; + let invoke2 = (a, b, callback: (a, b) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(callback(a, b)); } return null; }; + let invoke3 = (a, b, c, callback: (a, b, c) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(callback(a, b, c)); } return null; }; + let invoke4 = (a, b, c, d, callback: (a, b, c, d) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(callback(a, b, c, d)); } return null; }; + let invoke5 = (a, b, c, d, e, callback: (a, b, c, d, e) => any) => { if (clients.ActiveClient === me) { return me.requestWhenReady(callback(a, b, c, d, e)); } return null; }; /* tslint:enable */ return { didOpen: (document, sendMessage) => { if (clients.checkOwnership(me, document)) { me.TrackedDocuments.add(document); - sendMessage(document); + provideCustomConfiguration(document, me).then(() => { + sendMessage(document); + }, () => { + sendMessage(document); + }); } }, didChange: defaultHandler, willSave: defaultHandler, willSaveWaitUntil: (event, sendMessage) => { if (clients.ActiveClient === me) { - return sendMessage(event); + return me.requestWhenReady(() => sendMessage(event)); } return Promise.resolve([]); }, @@ -39,7 +44,7 @@ export function createProtocolFilter(me: Client, clients: ClientCollection): Mid if (clients.ActiveClient === me) { console.assert(me.TrackedDocuments.has(document)); me.TrackedDocuments.delete(document); - sendMessage(document); + me.notifyWhenReady(() => sendMessage(document)); } }, diff --git a/Extension/src/api.ts b/Extension/src/api.ts new file mode 100644 index 000000000..26e9bba9f --- /dev/null +++ b/Extension/src/api.ts @@ -0,0 +1,112 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. + * See 'LICENSE' in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict'; + +import * as vscode from 'vscode'; +import { CancellationToken } from 'vscode-jsonrpc'; + +/** + * An interface to allow Custom Configuration Provider extensions to communicate with this extension. + */ +export interface CppToolsApi { + /** + * Register the Custom Configuration Provider. + * This must be called as soon as the provider extension is ready. This is necessary for cpptools + * to request configurations from the provider. + * @param provider An instance of the [CustomConfigurationProvider](#CustomConfigurationProvider) + * instance representing the provider extension. + */ + registerCustomConfigurationProvider(provider: CustomConfigurationProvider): void; + + /** + * Notifies cpptools that the current configuration has changed. Upon receiving this notification, + * cpptools will request the new configurations. + * @param provider An instance of the [CustomConfigurationProvider](#CustomConfigurationProvider) + * instance representing the provider extension. + */ + didChangeCustomConfiguration(provider: CustomConfigurationProvider): void; +} + +/** + * An interface to allow this extension to communicate with Custom Configuration Provider extensions. + */ +export interface CustomConfigurationProvider { + /** + * The name of the Custom Configuration Provider extension. + */ + name: string; + + /** + * A request to determine whether this provider can provide IntelliSense configurations for the given document. + * @param uri The URI of the document. + * @param token (optional) The cancellation token. + * @returns 'true' if this provider can provide IntelliSense configurations for the given document. + */ + canProvideConfiguration(uri: vscode.Uri, token?: CancellationToken): Thenable; + + /** + * A request to get Intellisense configurations for the given files. + * @param uris A list of one of more URIs for the files to provide configurations for. + * @param token (optional) The cancellation token. + * @returns A list of [SourceFileConfigurationItem](#SourceFileConfigurationItem) for the documents that this provider + * is able to provide IntelliSense configurations for. + * Note: If this provider cannot provide configurations for a file in `uris`, then the file will not be included + * in the return value. An empty list will be returned if the provider cannot provide configurations for any of the files. + */ + provideConfigurations(uris: vscode.Uri[], token?: CancellationToken): Thenable; +} + +/** + * The model representing the custom IntelliSense configurations for a source file. + */ +export interface SourceFileConfiguration { + /** + * This must also include the system include path (compiler defaults) unless + * [compilerPath](#SourceFileConfiguration.compilerPath) is specified. + */ + includePath: string[]; + + /** + * This must also include the compiler default defines (__cplusplus, etc) unless + * [compilerPath](#SourceFileConfiguration.compilerPath) is specified. + */ + defines: string[]; + + /** + * Currently, "msvc-x64" or "clang-x64". + */ + intelliSenseMode: string; + + /** + * The C or C++ standard. See `package.json` for valid values. + */ + standard: string; + + /** + * Any files that need to be included before the source file is parsed. + */ + forcedInclude?: string[]; + + /** + * The full path to the compiler. If specified, the extension will query it for default includes and defines and + * add them to [includePath](#SourceFileConfiguration.includePath) and [defines](#SourceFileConfiguration.defines). + */ + compilerPath?: string; +} + +/** + * A model representing a source file and its corresponding configuration. + */ +export interface SourceFileConfigurationItem { + /** + * The URI of the source file. + */ + uri: string; + + /** + * The IntelliSense configuration for [uri](#SourceFileConfigurationItem.uri) + */ + configuration: SourceFileConfiguration; +} diff --git a/Extension/src/cppTools.ts b/Extension/src/cppTools.ts new file mode 100644 index 000000000..7ba3787ca --- /dev/null +++ b/Extension/src/cppTools.ts @@ -0,0 +1,18 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. + * See 'LICENSE' in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict'; + +import { CppToolsApi, CustomConfigurationProvider } from './api'; +import * as LanguageServer from './LanguageServer/extension'; + +export class CppTools implements CppToolsApi { + registerCustomConfigurationProvider(provider: CustomConfigurationProvider): void { + LanguageServer.registerCustomConfigurationProvider(provider); + } + + didChangeCustomConfiguration(provider: CustomConfigurationProvider): void { + LanguageServer.onDidChangeCustomConfiguration(provider); + } +} \ No newline at end of file diff --git a/Extension/src/main.ts b/Extension/src/main.ts index f5b9e0cc5..b4c632da2 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -19,10 +19,13 @@ import { PackageManager, PackageManagerError, PackageManagerWebResponseError, IP import { PersistentState } from './LanguageServer/persistentState'; import { initializeInstallationInformation, getInstallationInformationInstance, InstallationInformation, setInstallationStage } from './installationInformation'; import { Logger, getOutputChannelLogger, showOutputChannel } from './logger'; +import { CppTools } from './cppTools'; +import { CppToolsApi } from './api'; const releaseNotesVersion: number = 3; +const cppTools: CppTools = new CppTools(); -export function activate(context: vscode.ExtensionContext): void | Promise { +export async function activate(context: vscode.ExtensionContext): Promise { initializeTemporaryCommandRegistrar(); util.setExtensionContext(context); Telemetry.activate(); @@ -33,7 +36,9 @@ export function activate(context: vscode.ExtensionContext): void | Promise // Initialize the DebuggerExtension and register the related commands and providers. DebuggerExtension.initialize(); - return processRuntimeDependencies(); + await processRuntimeDependencies(); + + return cppTools; } export function deactivate(): Thenable { From a4edf98976bdd992759307826d444fe62b27262d Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 18 May 2018 13:31:25 -0700 Subject: [PATCH 20/21] Update package.json --- Extension/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/package.json b/Extension/package.json index e0eba01e9..c7724e999 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2,7 +2,7 @@ "name": "cpptools", "displayName": "C/C++", "description": "C/C++ IntelliSense, debugging, and code browsing.", - "version": "0.17.2-insiders", + "version": "0.17.2", "publisher": "ms-vscode", "preview": true, "icon": "LanguageCCPP_color_128x.png", From 7cd7d3422ce0285886b6f754d790e6de831994b3 Mon Sep 17 00:00:00 2001 From: Bob Brown Date: Fri, 18 May 2018 13:31:37 -0700 Subject: [PATCH 21/21] Update package.json --- Extension/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/package.json b/Extension/package.json index c7724e999..3de4e2ef3 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2,7 +2,7 @@ "name": "cpptools", "displayName": "C/C++", "description": "C/C++ IntelliSense, debugging, and code browsing.", - "version": "0.17.2", + "version": "0.17.2-master", "publisher": "ms-vscode", "preview": true, "icon": "LanguageCCPP_color_128x.png",