From 839eefa0325a718b7feefc737eaf9d3bdae18a6a Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Thu, 22 Oct 2020 13:36:06 -0700 Subject: [PATCH] [cppdbg] Support new sourceFileMap schema (#6319) * [cppdbg] Support new sourceFileMap schema For cppdbg, sourceFileMap can be used for binding breakpoints. If keeping with the old format "":"", it will always be used for breakpoints. If you use the new: "" : { "editorPath": "", "useForBreakpoints": true } The sourceMap will only be used for frame enumeration. * Fix linter issues * Addressing PR comments --- Extension/package.json | 90 ++++++++++++++++--- Extension/package.nls.json | 5 +- .../src/Debugger/configurationProvider.ts | 31 ++++--- Extension/src/common.ts | 4 + Extension/tools/GenerateOptionsSchema.ts | 9 ++ Extension/tools/OptionsSchema.json | 67 +++++++++++--- 6 files changed, 175 insertions(+), 31 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index 63375d0043..3d5b8f3734 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -1455,11 +1455,46 @@ "default": false }, "sourceFileMap": { - "type": "object", - "description": "%c_cpp.debuggers.sourceFileMap.description%", - "default": { - "": "" - } + "anyOf": [ + { + "type": "object", + "description": "%c_cpp.debuggers.sourceFileMap.description%", + "default": { + "": "" + } + }, + { + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.description%", + "type": "object", + "default": { + "": { + "editorPath": "", + "useForBreakpoints": true + } + }, + "properties": { + "": { + "type": "object", + "default": { + "editorPath": "", + "useForBreakpoints": true + }, + "properties": { + "editorPath": { + "type": "string", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.editorPath.description%", + "default": "" + }, + "useForBreakpoints": { + "type": "boolean", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.useForBreakpoints.description%", + "default": true + } + } + } + } + } + ] }, "logging": { "description": "%c_cpp.debuggers.logging.description%", @@ -1648,11 +1683,46 @@ "default": false }, "sourceFileMap": { - "type": "object", - "description": "%c_cpp.debuggers.sourceFileMap.description%", - "default": { - "": "" - } + "anyOf": [ + { + "type": "object", + "description": "%c_cpp.debuggers.sourceFileMap.description%", + "default": { + "": "" + } + }, + { + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.description%", + "type": "object", + "default": { + "": { + "editorPath": "", + "useForBreakpoints": true + } + }, + "properties": { + "": { + "type": "object", + "default": { + "editorPath": "", + "useForBreakpoints": true + }, + "properties": { + "editorPath": { + "type": "string", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.editorPath.description%", + "default": "" + }, + "useForBreakpoints": { + "type": "boolean", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.useForBreakpoints.description%", + "default": true + } + } + } + } + } + ] }, "logging": { "description": "%c_cpp.debuggers.logging.description%", diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 0ad5b0051f..120d14ad07 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -227,5 +227,8 @@ "c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script", "c_cpp.taskDefinitions.options.description": "Additional command options", "c_cpp.taskDefinitions.options.cwd.description": "The current working directory of the executed program or script. If omitted Code's current workspace root is used.", - "c_cpp.taskDefinitions.detail.description": "Additional details of the task" + "c_cpp.taskDefinitions.detail.description": "Additional details of the task", + "c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.description": "Current and compile-time paths to the same source trees. Files found under the EditorPath are mapped to the CompileTimePath path for breakpoint matching and mapped from CompileTimePath to EditorPath when displaying stacktrace locations.", + "c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.editorPath.description": "The path to the source tree the editor will use.", + "c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.useForBreakpoints.description": "False if this entry is only used for stack frame location mapping. True if this entry should also be used when specifying breakpoint locations." } diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 1757cb6ec1..3fc8fa74cc 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -344,24 +344,35 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { let message: string = ""; const sourceFileMapTarget: string = config.sourceFileMap[sourceFileMapSource]; - // TODO: pass config.environment as 'additionalEnvironment' to resolveVariables when it is { key: value } instead of { "key": key, "value": value } - const newSourceFileMapSource: string = util.resolveVariables(sourceFileMapSource, undefined); - const newSourceFileMapTarget: string = util.resolveVariables(sourceFileMapTarget, undefined); - let source: string = sourceFileMapSource; - let target: string = sourceFileMapTarget; + let target: string | object = sourceFileMapTarget; + // TODO: pass config.environment as 'additionalEnvironment' to resolveVariables when it is { key: value } instead of { "key": key, "value": value } + const newSourceFileMapSource: string = util.resolveVariables(sourceFileMapSource, undefined); if (sourceFileMapSource !== newSourceFileMapSource) { message = "\t" + localize("replacing.sourcepath", "Replacing {0} '{1}' with '{2}'.", "sourcePath", sourceFileMapSource, newSourceFileMapSource); delete config.sourceFileMap[sourceFileMapSource]; source = newSourceFileMapSource; } - if (sourceFileMapTarget !== newSourceFileMapTarget) { - // Add a space if source was changed, else just tab the target message. - message += (message ? ' ' : '\t'); - message += localize("replacing.targetpath", "Replacing {0} '{1}' with '{2}'.", "targetPath", sourceFileMapTarget, newSourceFileMapTarget); - target = newSourceFileMapTarget; + if (util.isString(sourceFileMapTarget)) { + const newSourceFileMapTarget: string = util.resolveVariables(sourceFileMapTarget, undefined); + if (sourceFileMapTarget !== newSourceFileMapTarget) { + // Add a space if source was changed, else just tab the target message. + message += (message ? ' ' : '\t'); + message += localize("replacing.targetpath", "Replacing {0} '{1}' with '{2}'.", "targetPath", sourceFileMapTarget, newSourceFileMapTarget); + target = newSourceFileMapTarget; + } + } else if (util.isObject(sourceFileMapTarget)) { + const newSourceFileMapTarget: {"editorPath": string; "useForBreakpoints": boolean } = sourceFileMapTarget; + newSourceFileMapTarget["editorPath"] = util.resolveVariables(sourceFileMapTarget["editorPath"], undefined); + + if (sourceFileMapTarget !== newSourceFileMapTarget) { + // Add a space if source was changed, else just tab the target message. + message += (message ? ' ' : '\t'); + message += localize("replacing.editorPath", "Replacing {0} '{1}' with '{2}'.", "editorPath", sourceFileMapTarget, newSourceFileMapTarget["editorPath"]); + target = newSourceFileMapTarget; + } } if (message) { diff --git a/Extension/src/common.ts b/Extension/src/common.ts index dc8377b837..a957d65461 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -262,6 +262,10 @@ export function isBoolean(input: any): input is boolean { return typeof(input) === "boolean"; } +export function isObject(input: any): input is object { + return typeof(input) === "object"; +} + export function isArray(input: any): input is any[] { return input instanceof Array; } diff --git a/Extension/tools/GenerateOptionsSchema.ts b/Extension/tools/GenerateOptionsSchema.ts index 418f34ad29..1f74be5ea3 100644 --- a/Extension/tools/GenerateOptionsSchema.ts +++ b/Extension/tools/GenerateOptionsSchema.ts @@ -80,6 +80,15 @@ function replaceReferences(definitions: any, objects: any): any { objects[key] = refReplace(definitions, objects[key]); } + // Handle 'anyOf' with references + if (objects[key].hasOwnProperty('anyOf')) { + for (const index in objects[key].anyOf) { + if (objects[key].anyOf[index].hasOwnProperty('$ref')) { + objects[key].anyOf[index] = refReplace(definitions, objects[key].anyOf[index]); + } + } + } + // 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); diff --git a/Extension/tools/OptionsSchema.json b/Extension/tools/OptionsSchema.json index c8f0f07e1d..1cee13b3ef 100644 --- a/Extension/tools/OptionsSchema.json +++ b/Extension/tools/OptionsSchema.json @@ -145,6 +145,37 @@ } } }, + "SourceFileMapEntry": { + "type": "object", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.description%", + "default": { + "": { + "editorPath": "", + "useForBreakpoints": true + } + }, + "properties": { + "": { + "type": "object", + "default": { + "editorPath": "", + "useForBreakpoints": true + }, + "properties": { + "editorPath": { + "type": "string", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.editorPath.description%", + "default": "" + }, + "useForBreakpoints": { + "type": "boolean", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.useForBreakpoints.description%", + "default": true + } + } + } + } + }, "CppdbgLaunchOptions": { "type": "object", "default": {}, @@ -304,11 +335,19 @@ "default": false }, "sourceFileMap": { - "type": "object", - "description": "%c_cpp.debuggers.sourceFileMap.description%", - "default": { - "": "" - } + "anyOf": [ + { + "type": "object", + "description": "%c_cpp.debuggers.sourceFileMap.description%", + "default": { + "": "" + } + }, + { + "$ref": "#/definitions/SourceFileMapEntry", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.description%" + } + ] }, "logging": { "$ref": "#/definitions/Logging", @@ -402,11 +441,19 @@ "default": false }, "sourceFileMap": { - "type": "object", - "description": "%c_cpp.debuggers.sourceFileMap.description%", - "default": { - "": "" - } + "anyOf": [ + { + "type": "object", + "description": "%c_cpp.debuggers.sourceFileMap.description%", + "default": { + "": "" + } + }, + { + "$ref": "#/definitions/SourceFileMapEntry", + "description": "%c_cpp.debuggers.sourceFileMap.sourceFileMapEntry.description%" + } + ] }, "logging": { "$ref": "#/definitions/Logging",