Revert "Add deploySteps and variables to cppdbg (#9418)"
This reverts commit b55a98c697
.
This commit is contained in:
Родитель
2a39dc402a
Коммит
e2ca8e8455
|
@ -33,4 +33,3 @@ localized_string_ids.h
|
|||
# ignore generate files. It will be generated when building
|
||||
src/nativeStrings.ts
|
||||
|
||||
vscode*.d.ts
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# C/C++ for Visual Studio Code Change Log
|
||||
|
||||
## Version 1.11.2 (pre-release): July 8, 2022
|
||||
### Enhancements
|
||||
* Add deploySteps and variables to cppdbg. [PR #9418](https://github.com/microsoft/vscode-cpptools/pull/9418)
|
||||
|
||||
## Version 1.11.1 (pre-release): July 7, 2022
|
||||
### Enhancements
|
||||
* Add deploySteps and variables to cppdbg. [PR #9418](https://github.com/microsoft/vscode-cpptools/pull/9418)
|
||||
* Move "auto" inlay hints to the right by default and add `C_Cpp.inlayHints.autoDeclarationTypes.showOnLeft`. [#9478](https://github.com/microsoft/vscode-cpptools/issues/9478)
|
||||
* Allow breakpoints for Rust debugging. [PR #9484](https://github.com/microsoft/vscode-cpptools/pull/9484)
|
||||
* Remove `_` from the start of parameter inlay hints and add `C_Cpp.inlayHints.parameterNames.hideLeadingUnderscores`. [#9485](https://github.com/microsoft/vscode-cpptools/issues/9485)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "cpptools",
|
||||
"displayName": "C/C++",
|
||||
"description": "C/C++ IntelliSense, debugging, and code browsing.",
|
||||
"version": "1.11.1-main",
|
||||
"version": "1.11.2-main",
|
||||
"publisher": "ms-vscode",
|
||||
"icon": "LanguageCCPP_color_128x.png",
|
||||
"readme": "README.md",
|
||||
|
@ -37,9 +37,6 @@
|
|||
"Linters",
|
||||
"Snippets"
|
||||
],
|
||||
"enabledApiProposals": [
|
||||
"terminalDataWriteEvent"
|
||||
],
|
||||
"capabilities": {
|
||||
"untrustedWorkspaces": {
|
||||
"supported": false,
|
||||
|
@ -420,34 +417,34 @@
|
|||
"scope": "resource"
|
||||
},
|
||||
"C_Cpp.codeAnalysis.clangTidy.codeAction.showClear": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.description%",
|
||||
"enum": [
|
||||
"None",
|
||||
"AllOnly",
|
||||
"AllAndAllType",
|
||||
"AllAndAllTypeAndThis"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.None.description%",
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.AllOnly.description%",
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.AllAndAllType.description%",
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.AllAndAllTypeAndThis.description%"
|
||||
],
|
||||
"default": "AllAndAllTypeAndThis",
|
||||
"scope": "application"
|
||||
"type": "string",
|
||||
"description": "%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.description%",
|
||||
"enum": [
|
||||
"None",
|
||||
"AllOnly",
|
||||
"AllAndAllType",
|
||||
"AllAndAllTypeAndThis"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.None.description%",
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.AllOnly.description%",
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.AllAndAllType.description%",
|
||||
"%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showClear.AllAndAllTypeAndThis.description%"
|
||||
],
|
||||
"default": "AllAndAllTypeAndThis",
|
||||
"scope": "application"
|
||||
},
|
||||
"C_Cpp.codeAnalysis.clangTidy.codeAction.showDisable": {
|
||||
"type": "boolean",
|
||||
"markdownDescription": "%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showDisable.markdownDescription%",
|
||||
"default": true,
|
||||
"scope": "application"
|
||||
"type": "boolean",
|
||||
"markdownDescription": "%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showDisable.markdownDescription%",
|
||||
"default": true,
|
||||
"scope": "application"
|
||||
},
|
||||
"C_Cpp.codeAnalysis.clangTidy.codeAction.showDocumentation": {
|
||||
"type": "boolean",
|
||||
"markdownDescription": "%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showDocumentation.markdownDescription%",
|
||||
"default": true,
|
||||
"scope": "application"
|
||||
"type": "boolean",
|
||||
"markdownDescription": "%c_cpp.configuration.codeAnalysis.clangTidy.codeAction.showDocumentation.markdownDescription%",
|
||||
"default": true,
|
||||
"scope": "application"
|
||||
},
|
||||
"C_Cpp.codeAnalysis.runAutomatically": {
|
||||
"type": "boolean",
|
||||
|
@ -3299,427 +3296,6 @@
|
|||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.variables.description%",
|
||||
"default": {
|
||||
"<variable-name>": "<variable-value>"
|
||||
},
|
||||
"properties": {},
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.variables.properties.description%",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"deploySteps": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.deploySteps.description%",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"files",
|
||||
"host",
|
||||
"targetDir"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"scp"
|
||||
]
|
||||
},
|
||||
"files": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.files.description%",
|
||||
"default": ""
|
||||
},
|
||||
"host": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.host.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
},
|
||||
"jumpHosts": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.jumpHost.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"localForwards": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.localForward.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"bindAddress": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.bindAddress.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.port.description%"
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.host.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostPort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.hostPort.description%"
|
||||
},
|
||||
"localSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.localSocket.description%",
|
||||
"default": ""
|
||||
},
|
||||
"remoteSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.remoteSocket.description%",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"targetDir": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.targetDir.description%",
|
||||
"default": ""
|
||||
},
|
||||
"scpPath": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.scpPath.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"host",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"ssh"
|
||||
]
|
||||
},
|
||||
"host": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.host.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
},
|
||||
"jumpHosts": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.jumpHost.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"localForwards": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.localForward.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"bindAddress": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.bindAddress.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.port.description%"
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.host.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostPort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.hostPort.description%"
|
||||
},
|
||||
"localSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.localSocket.description%",
|
||||
"default": ""
|
||||
},
|
||||
"remoteSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.remoteSocket.description%",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"sshPath": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.sshPath.description%",
|
||||
"default": ""
|
||||
},
|
||||
"continueOn": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"shell"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"continueOn": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"command"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.args.description%",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3974,427 +3550,6 @@
|
|||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.variables.description%",
|
||||
"default": {
|
||||
"<variable-name>": "<variable-value>"
|
||||
},
|
||||
"properties": {},
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.variables.properties.description%",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"deploySteps": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.deploySteps.description%",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"files",
|
||||
"host",
|
||||
"targetDir"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"scp"
|
||||
]
|
||||
},
|
||||
"files": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.files.description%",
|
||||
"default": ""
|
||||
},
|
||||
"host": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.host.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
},
|
||||
"jumpHosts": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.jumpHost.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"localForwards": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.localForward.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"bindAddress": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.bindAddress.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.port.description%"
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.host.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostPort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.hostPort.description%"
|
||||
},
|
||||
"localSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.localSocket.description%",
|
||||
"default": ""
|
||||
},
|
||||
"remoteSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.remoteSocket.description%",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"targetDir": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.targetDir.description%",
|
||||
"default": ""
|
||||
},
|
||||
"scpPath": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.scpPath.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"host",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"ssh"
|
||||
]
|
||||
},
|
||||
"host": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.host.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
},
|
||||
"jumpHosts": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.jumpHost.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"localForwards": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.localForward.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"bindAddress": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.bindAddress.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.port.description%"
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.host.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostPort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.hostPort.description%"
|
||||
},
|
||||
"localSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.localSocket.description%",
|
||||
"default": ""
|
||||
},
|
||||
"remoteSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.remoteSocket.description%",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"sshPath": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.sshPath.description%",
|
||||
"default": ""
|
||||
},
|
||||
"continueOn": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"shell"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"continueOn": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"command"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.args.description%",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5361,14 +4516,10 @@
|
|||
"unitTests": "tsc -p test.tsconfig.json && node ./out/test/unitTests/runTest.js",
|
||||
"integrationTests": "tsc -p test.tsconfig.json && node ./out/test/integrationTests/languageServer/runTest.js",
|
||||
"intelliSenseFeaturesTests": "tsc -p test.tsconfig.json && node ./out/test/integrationTests/IntelliSenseFeatures/runTest.js",
|
||||
"import-edge-strings": "node ./import_edge_strings.js",
|
||||
"download-api": "vscode-dts dev",
|
||||
"postdownload-api": "vscode-dts master",
|
||||
"postinstall": "npm run download-api"
|
||||
"import-edge-strings": "node ./import_edge_strings.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"@types/mkdirp": "^0.5.2",
|
||||
"@types/mocha": "^8.2.2",
|
||||
|
@ -5376,6 +4527,7 @@
|
|||
"@types/plist": "^3.0.2",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/tmp": "^0.1.0",
|
||||
"@types/vscode": "1.65.0",
|
||||
"@types/which": "^1.3.2",
|
||||
"@types/yauzl": "^2.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
||||
|
@ -5389,6 +4541,7 @@
|
|||
"eslint-plugin-jsdoc": "^39.3.3",
|
||||
"event-stream": "^4.0.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"glob": "^7.1.6",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-env": "^0.4.0",
|
||||
"gulp-eslint": "^6.0.0",
|
||||
|
@ -5407,7 +4560,6 @@
|
|||
"typescript": "^4.4.3",
|
||||
"vscode-debugadapter": "^1.35.0",
|
||||
"vscode-debugprotocol": "^1.35.0",
|
||||
"vscode-dts": "^0.3.2",
|
||||
"vscode-nls-dev": "^4.0.0-next.1",
|
||||
"webpack": "^5.28.0",
|
||||
"webpack-cli": "^4.5.0",
|
||||
|
@ -5417,7 +4569,6 @@
|
|||
"comment-json": "^4.1.1",
|
||||
"editorconfig": "^0.15.3",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"https-proxy-agent": "^2.2.4",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.5",
|
||||
|
|
|
@ -301,35 +301,6 @@
|
|||
"c_cpp.debuggers.hardwareBreakpoints.description": "Explicit control of hardware breakpoint behavior for remote targets.",
|
||||
"c_cpp.debuggers.hardwareBreakpoints.require.description": "If true, always use hardware breakpoints. Defaults to false.",
|
||||
"c_cpp.debuggers.hardwareBreakpoints.limit.description": "Optional limit on the number of available hardware breakpoints to use. Only enforced when \"require\" is true and \"limit\" is greater than 0. Defaults to 0.",
|
||||
"c_cpp.debuggers.variables.description": "Variables for recursive substitution in this launch configuration. Each variable may refer to others.",
|
||||
"c_cpp.debuggers.variables.properties.description": "Variable for recursive substitution in this launch configuration. The value may refer to other variables.",
|
||||
"c_cpp.debuggers.host.description": "Host information.",
|
||||
"c_cpp.debuggers.host.user.description": "User logging into the host.",
|
||||
"c_cpp.debuggers.host.hostName.description": "Host name.",
|
||||
"c_cpp.debuggers.host.port.description": "SSH port on the host. Default is 22.",
|
||||
"c_cpp.debuggers.host.jumpHost.description": "Connect to the target host by first making a connection to the jump hosts.",
|
||||
"c_cpp.debuggers.host.localForward.description": "Forward connections to the given TCP port or Unix socket on the local (client) host to the given host and port, or Unix socket, on the remote side",
|
||||
"c_cpp.debuggers.host.localForward.bindAddress.description": "Local address",
|
||||
"c_cpp.debuggers.host.localForward.port.description": "Local port",
|
||||
"c_cpp.debuggers.host.localForward.host.description": "Host name",
|
||||
"c_cpp.debuggers.host.localForward.hostPort.description": "Host port",
|
||||
"c_cpp.debuggers.host.localForward.localSocket.description": "Local socket",
|
||||
"c_cpp.debuggers.host.localForward.remoteSocket.description": "Remote socket",
|
||||
"c_cpp.debuggers.deploySteps.description": "Steps needed to deploy the application. Order matters.",
|
||||
"c_cpp.debuggers.deploySteps.scp.description": "Copy files using SCP.",
|
||||
"c_cpp.debuggers.deploySteps.scp.files.description": "Files to be copied via SCP. Supports path pattern.",
|
||||
"c_cpp.debuggers.deploySteps.scp.targetDir.description": "Target directory.",
|
||||
"c_cpp.debuggers.deploySteps.scp.scpPath.description": "Optional full path to SCP. Assumes SCP is on PATH if not specified",
|
||||
"c_cpp.debuggers.deploySteps.debug": "If true, skip when starting without debugging. If false, skip when starting debugging. If undefined, never skip.",
|
||||
"c_cpp.debuggers.deploySteps.ssh.description": "SSH command step.",
|
||||
"c_cpp.debuggers.deploySteps.ssh.command.description": "Command to be executed via SSH. The command after '-c' in SSH command.",
|
||||
"c_cpp.debuggers.deploySteps.ssh.sshPath.description": "Optional full path to SSH. Assumes SSH is on PATH if not specified",
|
||||
"c_cpp.debuggers.deploySteps.continueOn.description": "An optional finish pattern in output. When this pattern is seen in the output, continue the deploy procedures regardless of whether this step returns.",
|
||||
"c_cpp.debuggers.deploySteps.shell.description": "Shell command step.",
|
||||
"c_cpp.debuggers.deploySteps.shell.command.description": "Shell command to be executed.",
|
||||
"c_cpp.debuggers.vsCodeCommand.description": "VS Code command to be invoked. Can be a command in VS Code or an active extension.",
|
||||
"c_cpp.debuggers.vsCodeCommand.command.description": "VS Code command to be invoked.",
|
||||
"c_cpp.debuggers.vsCodeCommand.args.description": "Arguments to the VS Code command.",
|
||||
"c_cpp.taskDefinitions.name.description": "The name of the task.",
|
||||
"c_cpp.taskDefinitions.command.description": "The path to either a compiler or script that performs compilation.",
|
||||
"c_cpp.taskDefinitions.args.description": "Additional arguments to pass to the compiler or compilation script.",
|
||||
|
|
|
@ -23,24 +23,10 @@ import { PlatformInformation } from '../platform';
|
|||
import { Environment, ParsedEnvironmentFile } from './ParsedEnvironmentFile';
|
||||
import { CppSettings, OtherSettings } from '../LanguageServer/settings';
|
||||
import { configPrefix } from '../LanguageServer/extension';
|
||||
import { expandAllStrings, ExpansionOptions, ExpansionVars } from '../expand';
|
||||
import { scp, ssh } from '../SSH/commands';
|
||||
import * as glob from 'glob';
|
||||
import { promisify } from 'util';
|
||||
|
||||
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
|
||||
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
|
||||
enum StepType {
|
||||
scp = 'scp',
|
||||
ssh = 'ssh',
|
||||
shell = 'shell',
|
||||
remoteShell = 'remoteShell',
|
||||
command = 'command'
|
||||
}
|
||||
|
||||
const globAsync: (pattern: string, options?: glob.IOptions | undefined) => Promise<string[]> = promisify(glob);
|
||||
|
||||
/*
|
||||
* Retrieves configurations from a provider and displays them in a quickpick menu to be selected.
|
||||
* Ensures that the selected configuration's preLaunchTask (if existent) is populated in the user's task.json.
|
||||
|
@ -219,11 +205,11 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
* This hook is directly called after 'resolveDebugConfiguration' but with all variables substituted.
|
||||
* This is also ran after the tasks.json has completed.
|
||||
*
|
||||
* Try to add all missing attributes to the debug configuration being launched.
|
||||
* Try to add all missing attributes to the debug configuration being launched.
|
||||
* If return "undefined", the debugging will be aborted silently.
|
||||
* If return "null", the debugging will be aborted and launch.json will be opened.
|
||||
*/
|
||||
async resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, config: CppDebugConfiguration, token?: vscode.CancellationToken): Promise<CppDebugConfiguration | null | undefined> {
|
||||
*/
|
||||
resolveDebugConfigurationWithSubstitutedVariables(folder: vscode.WorkspaceFolder | undefined, config: CppDebugConfiguration, token?: vscode.CancellationToken): vscode.ProviderResult<CppDebugConfiguration> {
|
||||
if (!config || !config.type) {
|
||||
return undefined; // Abort debugging silently.
|
||||
}
|
||||
|
@ -246,7 +232,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
|
||||
// Disable debug heap by default, enable if 'enableDebugHeap' is set.
|
||||
if (!config.enableDebugHeap) {
|
||||
const disableDebugHeapEnvSetting: Environment = { "name": "_NO_DEBUG_HEAP", "value": "1" };
|
||||
const disableDebugHeapEnvSetting: Environment = {"name" : "_NO_DEBUG_HEAP", "value" : "1"};
|
||||
|
||||
if (config.environment && util.isArray(config.environment)) {
|
||||
config.environment.push(disableDebugHeapEnvSetting);
|
||||
|
@ -259,8 +245,6 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
// Add environment variables from .env file
|
||||
this.resolveEnvFile(config, folder);
|
||||
|
||||
await this.expand(config, folder);
|
||||
|
||||
this.resolveSourceFileMapVariables(config);
|
||||
|
||||
// Modify WSL config for OpenDebugAD7
|
||||
|
@ -323,19 +307,6 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
// logger.showOutputChannel();
|
||||
}
|
||||
|
||||
// Run deploy steps
|
||||
if (config.deploySteps && config.deploySteps.length !== 0) {
|
||||
const codeVersion: number[] = vscode.version.split('.').map(num => parseInt(num, undefined));
|
||||
if ((util.isNumber(codeVersion[0]) && codeVersion[0] < 1) || (util.isNumber(codeVersion[0]) && codeVersion[0] === 1 && util.isNumber(codeVersion[1]) && codeVersion[1] < 69)) {
|
||||
logger.getOutputChannelLogger().showErrorMessage(localize("vs.code.1.69+.required", "'deploySteps' require VS Code 1.69+."));
|
||||
return undefined;
|
||||
}
|
||||
const deploySucceeded: boolean = await this.deploySteps(config, token);
|
||||
if (!deploySucceeded || token?.isCancellationRequested) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -624,17 +595,17 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
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 += (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;
|
||||
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 += (message ? ' ' : '\t');
|
||||
message += localize("replacing.editorPath", "Replacing {0} '{1}' with '{2}'.", "editorPath", sourceFileMapTarget, newSourceFileMapTarget["editorPath"]);
|
||||
target = newSourceFileMapTarget;
|
||||
}
|
||||
|
@ -873,7 +844,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
}
|
||||
selectedConfig.debugType = debugModeOn ? DebugType.debug : DebugType.run;
|
||||
// startDebugging will trigger a call to resolveDebugConfiguration.
|
||||
await vscode.debug.startDebugging(folder, selectedConfig, { noDebug: !debugModeOn });
|
||||
await vscode.debug.startDebugging(folder, selectedConfig, {noDebug: !debugModeOn});
|
||||
}
|
||||
|
||||
private async selectConfiguration(textEditor: vscode.TextEditor, pickDefault: boolean = true, onlyWorkspaceFolder: boolean = false): Promise<CppDebugConfiguration | undefined> {
|
||||
|
@ -941,116 +912,6 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async expand(config: vscode.DebugConfiguration, folder: vscode.WorkspaceFolder | undefined): Promise<void> {
|
||||
const folderPath: string | undefined = folder?.uri.fsPath || vscode.workspace.workspaceFolders?.[0].uri.fsPath;
|
||||
const vars: ExpansionVars = config.variables ? config.variables : {};
|
||||
vars.workspaceFolder = folderPath || '{workspaceFolder}';
|
||||
vars.workspaceFolderBasename = folderPath ? path.basename(folderPath) : '{workspaceFolderBasename}';
|
||||
const expansionOptions: ExpansionOptions = { vars, recursive: true };
|
||||
return expandAllStrings(config, expansionOptions);
|
||||
}
|
||||
|
||||
// Returns true when ALL steps succeed; stop all subsequent steps if one fails
|
||||
private async deploySteps(config: vscode.DebugConfiguration, cancellationToken?: vscode.CancellationToken): Promise<boolean> {
|
||||
let succeeded: boolean = true;
|
||||
const deployStart: number = new Date().getTime();
|
||||
|
||||
for (const step of config.deploySteps) {
|
||||
succeeded = await this.singleDeployStep(config, step, cancellationToken);
|
||||
if (!succeeded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const deployEnd: number = new Date().getTime();
|
||||
|
||||
const telemetryProperties: { [key: string]: string } = {
|
||||
Succeeded: `${succeeded}`,
|
||||
IsDebugging: `${!config.noDebug || false}`
|
||||
};
|
||||
const telemetryMetrics: { [key: string]: number } = {
|
||||
NumSteps: config.deploySteps.length,
|
||||
Duration: deployEnd - deployStart
|
||||
};
|
||||
Telemetry.logDebuggerEvent('deploy', telemetryProperties, telemetryMetrics);
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
private async singleDeployStep(config: vscode.DebugConfiguration, step: any, cancellationToken?: vscode.CancellationToken): Promise<boolean> {
|
||||
if ((config.noDebug && step.debug === true) || (!config.noDebug && step.debug === false)) {
|
||||
// Skip steps that doesn't match current launch mode. Explicit true/false check, since a step is always run when debug is undefined.
|
||||
return true;
|
||||
}
|
||||
switch (step.type) {
|
||||
case StepType.command: {
|
||||
// VS Code commands are the same regardless of which extension invokes them, so just invoke them here.
|
||||
if (step.args && !Array.isArray(step.args)) {
|
||||
logger.getOutputChannelLogger().showErrorMessage(localize('command.args.must.be.array', '"args" in command deploy step must be an array.'));
|
||||
return false;
|
||||
}
|
||||
const returnCode: unknown = await vscode.commands.executeCommand(step.command, ...step.args);
|
||||
return !returnCode;
|
||||
}
|
||||
case StepType.scp: {
|
||||
if (!step.files || !step.targetDir || !step.host) {
|
||||
logger.getOutputChannelLogger().showErrorMessage(localize('missing.properties.scp', '"host", "files", and "targetDir" are required in scp steps.'));
|
||||
return false;
|
||||
}
|
||||
const host: util.ISshHostInfo = { hostName: step.host.hostName, user: step.host.user, port: step.host.port };
|
||||
const jumpHosts: util.ISshHostInfo[] = step.host.jumpHosts;
|
||||
let files: vscode.Uri[] = [];
|
||||
if (util.isString(step.files)) {
|
||||
files = files.concat((await globAsync(step.files)).map(file => vscode.Uri.file(file)));
|
||||
} else if (util.isArrayOfString(step.files)) {
|
||||
for (const fileGlob of (step.files as string[])) {
|
||||
files = files.concat((await globAsync(fileGlob)).map(file => vscode.Uri.file(file)));
|
||||
}
|
||||
} else {
|
||||
logger.getOutputChannelLogger().showErrorMessage(localize('incorrect.files.type.scp', '"files" must be a string or an array of strings in scp steps.'));
|
||||
return false;
|
||||
}
|
||||
const scpResult: util.ProcessReturnType = await scp(files, host, step.targetDir, config.scpPath, jumpHosts, cancellationToken);
|
||||
if (!scpResult.succeeded || cancellationToken?.isCancellationRequested) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StepType.ssh: {
|
||||
if (!step.host || !step.command) {
|
||||
logger.getOutputChannelLogger().showErrorMessage(localize('missing.properties.ssh', '"host" and "command" are required for ssh steps.'));
|
||||
return false;
|
||||
}
|
||||
const host: util.ISshHostInfo = { hostName: step.host.hostName, user: step.host.user, port: step.host.port };
|
||||
const jumpHosts: util.ISshHostInfo[] = step.host.jumpHosts;
|
||||
const localForwards: util.ISshLocalForwardInfo[] = step.host.localForwards;
|
||||
const continueOn: string = step.continueOn;
|
||||
const sshResult: util.ProcessReturnType = await ssh(host, step.command, config.sshPath, jumpHosts, localForwards, continueOn, cancellationToken);
|
||||
if (!sshResult.succeeded || cancellationToken?.isCancellationRequested) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StepType.shell: {
|
||||
if (!step.command) {
|
||||
logger.getOutputChannelLogger().showErrorMessage(localize('missing.properties.shell', '"command" is required for shell steps.'));
|
||||
return false;
|
||||
}
|
||||
const taskResult: util.ProcessReturnType = await util.spawnChildProcess(step.command, undefined, step.continueOn);
|
||||
if (!taskResult.succeeded || cancellationToken?.isCancellationRequested) {
|
||||
logger.getOutputChannelLogger().showErrorMessage(taskResult.output);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.getOutputChannelLogger().appendLine(localize('deploy.step.type.not.supported', 'Deploy step type {0} is not supported.', step.type));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IConfigurationAssetProvider {
|
||||
|
@ -1203,7 +1064,7 @@ export class ConfigurationSnippetProvider implements vscode.CompletionItemProvid
|
|||
items = [];
|
||||
|
||||
// Make a copy of each snippet since we are adding a comma to the end of the insertText.
|
||||
this.snippets.forEach((item) => items.push({ ...item }));
|
||||
this.snippets.forEach((item) => items.push({...item}));
|
||||
|
||||
items.map((item) => {
|
||||
item.insertText = item.insertText + ','; // Add comma
|
||||
|
|
|
@ -1,340 +0,0 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { stripEscapeSequences, isWindows, escapeStringForRegex } from '../common';
|
||||
|
||||
export type IDifferingHostConfirmationProvider =
|
||||
(message: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
|
||||
|
||||
export type IFingerprintConfirmationProvider =
|
||||
(host: string, fingerprint: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
|
||||
|
||||
export interface IInteraction {
|
||||
canceled?: boolean;
|
||||
postAction?: 'consume' | 'keep';
|
||||
response?: string;
|
||||
isPassword?: boolean;
|
||||
continue?: boolean; // Continue without waiting for the program to finish or pause
|
||||
}
|
||||
|
||||
export interface IInteractorDataDetails {
|
||||
detectedServerKey?: string;
|
||||
detail?: string;
|
||||
}
|
||||
|
||||
export interface IInteractor {
|
||||
id: string;
|
||||
onData(data: string, cancelToken?: vscode.CancellationToken, extraDetails?: IInteractorDataDetails): Promise<IInteraction>;
|
||||
}
|
||||
|
||||
export class MitmInteractor implements IInteractor {
|
||||
static ID = 'mitm';
|
||||
|
||||
constructor() { }
|
||||
|
||||
get id(): string {
|
||||
return MitmInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string): Promise<IInteraction> {
|
||||
if (!!data.match('Port forwarding is disabled to avoid man-in-the-middle attacks.')) {
|
||||
throw Error('Port forwarding is disabled to avoid man-in-the-middle attacks.');
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export class FingerprintInteractor implements IInteractor {
|
||||
static ID = 'fingerprint';
|
||||
|
||||
constructor(private readonly hostName: string, private readonly confirmationProvider: IFingerprintConfirmationProvider) { }
|
||||
|
||||
get id(): string {
|
||||
return FingerprintInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string, cancelToken?: vscode.CancellationToken, extraDetails?: IInteractorDataDetails): Promise<IInteraction> {
|
||||
const fingerprintMatcher: RegExp = /fingerprint\sis\s(.+)\./;
|
||||
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
data = data.trim();
|
||||
|
||||
let fingerprintMatch: RegExpMatchArray | null;
|
||||
if (
|
||||
data.includes('Are you sure you want to continue connecting') &&
|
||||
(fingerprintMatch = data.match(fingerprintMatcher))
|
||||
) {
|
||||
result.postAction = 'consume';
|
||||
const confirmation: string | undefined = await this.confirmationProvider(
|
||||
this.hostName,
|
||||
fingerprintMatch[1],
|
||||
cancelToken
|
||||
);
|
||||
if (confirmation) {
|
||||
result.response = confirmation;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
} else if (
|
||||
isWindows() &&
|
||||
(data.includes('The authenticity of host ') || (data === '' && extraDetails?.detectedServerKey))
|
||||
) {
|
||||
// hack for #1195
|
||||
// First line local server case (git ssh only gives the first line over ssh_askpass)
|
||||
const key: string = extraDetails?.detectedServerKey || '(unknown)';
|
||||
|
||||
result.postAction = 'consume';
|
||||
const confirmation: string | undefined = await this.confirmationProvider(this.hostName, key, cancelToken);
|
||||
if (confirmation) {
|
||||
result.response = confirmation;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export class DifferingHostKeyInteractor implements IInteractor {
|
||||
static ID = 'differing host key';
|
||||
|
||||
constructor(private readonly confirmationProvider: IDifferingHostConfirmationProvider) { }
|
||||
|
||||
get id(): string {
|
||||
return DifferingHostKeyInteractor.ID;
|
||||
}
|
||||
async onData(data: string, cancelToken?: vscode.CancellationToken, _extraDetails?: IInteractorDataDetails): Promise<IInteraction> {
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
data = data.trim();
|
||||
|
||||
if (
|
||||
data.includes('Are you sure you want to continue connecting') &&
|
||||
data.includes('Offending key for IP in') &&
|
||||
data.includes('Matching host key in')
|
||||
) {
|
||||
result.postAction = 'consume';
|
||||
const message: string = data.substring(data.indexOf('Warning'), data.indexOf('Are')).trim();
|
||||
const confirmation: string | undefined = await this.confirmationProvider(message, cancelToken);
|
||||
if (confirmation) {
|
||||
result.response = confirmation;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export type IStringProvider =
|
||||
(key?: string, detail?: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
|
||||
|
||||
export class PassphraseInteractor implements IInteractor {
|
||||
static ID = 'passphrase';
|
||||
|
||||
constructor(private readonly passphraseProvider: IStringProvider) { }
|
||||
|
||||
get id(): string {
|
||||
return PassphraseInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string, cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
const lines: string[] = data.trim().split('\n');
|
||||
if (lines.some(l => l.indexOf('Enter passphrase for') >= 0)) {
|
||||
result.postAction = 'consume';
|
||||
const passphrase: string | undefined = await this.passphraseProvider(undefined, undefined, cancelToken); // TODO keep track of the key name
|
||||
if (typeof passphrase === 'string') {
|
||||
result.response = passphrase;
|
||||
result.isPassword = true;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
} else if (lines.some(l => l.indexOf('Identity added:') >= 0)) {
|
||||
result.postAction = 'consume';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export function getExitCode(output: string, marker: string): number | undefined {
|
||||
const regex: RegExp = new RegExp(`${marker}##([0-9]*)##`);
|
||||
const match: RegExpExecArray | null = regex.exec(output);
|
||||
if (match) {
|
||||
try {
|
||||
const num: number = parseInt(match[1]);
|
||||
return Number.isNaN(num) ? undefined : num;
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches SSH password prompt of format:
|
||||
* 's password:
|
||||
* or
|
||||
* Password:
|
||||
* not
|
||||
* 's old password:
|
||||
* 's new password:
|
||||
*/
|
||||
function getPasswordPrompt(data: string, details?: IInteractorDataDetails): { user?: string; message?: string } | undefined {
|
||||
if (data.includes('Password:')) {
|
||||
// Password prompt for unspecified user
|
||||
return { user: '' };
|
||||
}
|
||||
|
||||
// Got \r\r\n as a line ending here
|
||||
const match: RegExpMatchArray | null = stripEscapeSequences(data).match(/([a-zA-Z0-9\-_@\.]*)'s password:/);
|
||||
if (match) {
|
||||
return {
|
||||
user: match[1],
|
||||
message: details ? details.detail : undefined
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class PasswordInteractor implements IInteractor {
|
||||
static ID = 'password';
|
||||
|
||||
constructor(private readonly passwordProvider: IStringProvider) { }
|
||||
|
||||
get id(): string {
|
||||
return PasswordInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string, cancelToken?: vscode.CancellationToken, extraDetails?: IInteractorDataDetails): Promise<IInteraction> {
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
const pwPrompt: { user?: string; message?: string } | undefined = getPasswordPrompt(data, extraDetails);
|
||||
if (pwPrompt && typeof pwPrompt.user === 'string') {
|
||||
result.postAction = 'consume';
|
||||
const password: string | undefined = await this.passwordProvider(pwPrompt.user, pwPrompt.message, cancelToken);
|
||||
if (typeof password === 'string') {
|
||||
result.response = password;
|
||||
result.isPassword = true;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export type IVerificationCodeProvider =
|
||||
(msg: string, cancelToken?: vscode.CancellationToken) => Promise<string | undefined>;
|
||||
|
||||
export class TwoFacInteractor implements IInteractor {
|
||||
static ID = '2fa';
|
||||
|
||||
constructor(private readonly verificationCodeProvider: IVerificationCodeProvider) { }
|
||||
|
||||
get id(): string {
|
||||
return TwoFacInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string, cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
if (data.includes('Verification code:')) {
|
||||
result.postAction = 'consume';
|
||||
const verificationCode: string | undefined = await this.verificationCodeProvider('Enter verification code', cancelToken);
|
||||
if (typeof verificationCode === 'string') {
|
||||
result.response = verificationCode;
|
||||
result.isPassword = true;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/vscode-remote-release/issues/2170
|
||||
export class DuoTwoFacInteractor implements IInteractor {
|
||||
static ID = 'duo-2fa';
|
||||
|
||||
constructor(private readonly verificationCodeProvider: IVerificationCodeProvider) { }
|
||||
|
||||
get id(): string {
|
||||
return DuoTwoFacInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string, cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
if (data.includes('Passcode:')) {
|
||||
result.postAction = 'consume';
|
||||
const verificationCode: string | undefined = await this.verificationCodeProvider('Enter passcode', cancelToken);
|
||||
if (typeof verificationCode === 'string') {
|
||||
result.response = verificationCode;
|
||||
result.isPassword = true;
|
||||
} else {
|
||||
result.canceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export class ContinueOnInteractor implements IInteractor {
|
||||
static ID = 'continueOn';
|
||||
|
||||
constructor(private readonly continueOn: string) { }
|
||||
|
||||
get id(): string {
|
||||
return ContinueOnInteractor.ID;
|
||||
}
|
||||
|
||||
async onData(data: string, _cancelToken?: vscode.CancellationToken): Promise<IInteraction> {
|
||||
const result: IInteraction = { postAction: 'keep' };
|
||||
const pattern: string = escapeStringForRegex(this.continueOn);
|
||||
const re: RegExp = new RegExp(pattern, 'g');
|
||||
if (data.match(re)) {
|
||||
result.continue = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export class ComposedInteractor implements IInteractor {
|
||||
constructor(private readonly interactors: IInteractor[]) { }
|
||||
|
||||
get id(): string {
|
||||
return 'composed';
|
||||
}
|
||||
|
||||
async onData(data: string): Promise<IInteraction> {
|
||||
for (const interactor of this.interactors) {
|
||||
const result: IInteraction = await interactor.onData(data);
|
||||
if (result.postAction === 'consume') {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return { postAction: 'keep' };
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISystemInteractor {
|
||||
createTerminal(options: vscode.TerminalOptions): vscode.Terminal;
|
||||
onDidCloseTerminal: typeof vscode.window.onDidCloseTerminal;
|
||||
onDidWriteTerminalData: typeof vscode.window.onDidWriteTerminalData;
|
||||
}
|
||||
|
||||
export const defaultSystemInteractor: ISystemInteractor = {
|
||||
createTerminal: vscode.window.createTerminal,
|
||||
onDidCloseTerminal: vscode.window.onDidCloseTerminal,
|
||||
onDidWriteTerminalData: vscode.window.onDidWriteTerminalData
|
||||
};
|
|
@ -1,98 +0,0 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { ISshHostInfo, ISshLocalForwardInfo, ProcessReturnType } from '../common';
|
||||
import { defaultSystemInteractor } from './commandInteractors';
|
||||
import { runSshTerminalCommandWithLogin } from './sshCommandRunner';
|
||||
|
||||
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
|
||||
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
|
||||
export async function scp(files: vscode.Uri[], host: ISshHostInfo, targetDir: string, scpPath?: string, jumpHosts?: ISshHostInfo[], cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
|
||||
const args: string[] = [];
|
||||
if (jumpHosts && jumpHosts.length > 0) {
|
||||
args.push('-J', jumpHosts.map(getFullHostAddress).join(','));
|
||||
}
|
||||
if (host.port) {
|
||||
// upper case P
|
||||
args.push('-P', `${host.port}`);
|
||||
}
|
||||
args.push(files.map(uri => `"${uri.fsPath}"`).join(' '), `${getFullHostAddressNoPort(host)}:${targetDir}`);
|
||||
|
||||
return runSshTerminalCommandWithLogin(host, { systemInteractor: defaultSystemInteractor, nickname: 'scp', command: `"${scpPath || 'scp'}" ${args.join(' ')}`, token: cancellationToken });
|
||||
}
|
||||
|
||||
export function ssh(host: ISshHostInfo, command: string, sshPath?: string, jumpHosts?: ISshHostInfo[], localForwards?: ISshLocalForwardInfo[], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
|
||||
const args: string[] = [];
|
||||
if (jumpHosts && jumpHosts.length > 0) {
|
||||
args.push('-J', jumpHosts.map(getFullHostAddress).join(','));
|
||||
}
|
||||
if (host.port) {
|
||||
// lower case p
|
||||
args.push('-p', `${host.port}`);
|
||||
}
|
||||
if (localForwards) {
|
||||
localForwards.forEach(info => args.push(...localForwardToArgs(info)));
|
||||
}
|
||||
args.push(getFullHostAddressNoPort(host), `"${command}"`);
|
||||
|
||||
return runSshTerminalCommandWithLogin(host, {
|
||||
systemInteractor: defaultSystemInteractor,
|
||||
command: `"${sshPath || 'ssh'}" ${args.join(' ')}`,
|
||||
nickname: 'ssh',
|
||||
continueOn,
|
||||
token: cancellationToken
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes one local forward info and convert it to '-L' args in ssh.
|
||||
*/
|
||||
function localForwardToArgs(localForward: ISshLocalForwardInfo): string[] {
|
||||
// Do not combine error checking and arg conversion for clarity.
|
||||
if (localForward.localSocket && (localForward.bindAddress || localForward.port)) {
|
||||
throw Error(localize('local.forward.local.conflict', '"localSocket" cannot be specifed at the same time with "bindAddress" or "port" in localForwards'));
|
||||
}
|
||||
if (!localForward.localSocket && !localForward.port) {
|
||||
throw Error(localize('local.forward.local.missing', '"port" or "localSocket" required in localForwards'));
|
||||
}
|
||||
if (localForward.remoteSocket && (localForward.host || localForward.hostPort)) {
|
||||
throw Error(localize('local.forward.remote.conflict', '"remoteSocket" cannot be specifed at the same time with "host" or "hostPort" in localForwards'));
|
||||
}
|
||||
if (!localForward.remoteSocket && (!localForward.host || !localForward.hostPort)) {
|
||||
throw Error(localize('local.forward.remote.missing', '"host" and "hostPort", or "remoteSocket" required in localForwards'));
|
||||
}
|
||||
|
||||
let arg: string = '';
|
||||
if (localForward.localSocket) {
|
||||
arg += `${localForward.localSocket}:`;
|
||||
}
|
||||
if (localForward.bindAddress) {
|
||||
arg += `${localForward.bindAddress}:`;
|
||||
}
|
||||
if (localForward.port) {
|
||||
arg += `${localForward.port}:`;
|
||||
}
|
||||
if (localForward.remoteSocket) {
|
||||
arg += `${localForward.remoteSocket}`;
|
||||
}
|
||||
if (localForward.host && localForward.hostPort) {
|
||||
arg += `${localForward.host}:${localForward.hostPort}`;
|
||||
}
|
||||
|
||||
return ['-L', arg];
|
||||
}
|
||||
|
||||
/** user@host */
|
||||
function getFullHostAddressNoPort(host: ISshHostInfo): string {
|
||||
return host.user ? `${host.user}@${host.hostName}` : `${host.hostName}`;
|
||||
}
|
||||
|
||||
function getFullHostAddress(host: ISshHostInfo): string {
|
||||
const fullHostName: string = getFullHostAddressNoPort(host);
|
||||
return host.port ? `${fullHostName}:${host.port}` : fullHostName;
|
||||
}
|
|
@ -1,518 +0,0 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import {
|
||||
DifferingHostKeyInteractor,
|
||||
DuoTwoFacInteractor,
|
||||
FingerprintInteractor,
|
||||
IInteractor,
|
||||
MitmInteractor,
|
||||
PassphraseInteractor,
|
||||
PasswordInteractor,
|
||||
TwoFacInteractor,
|
||||
ContinueOnInteractor,
|
||||
ISystemInteractor,
|
||||
IInteraction
|
||||
} from './commandInteractors';
|
||||
import { isWindows, ISshHostInfo, splitLines, stripEscapeSequences, ProcessReturnType } from '../common';
|
||||
import { getOutputChannelLogger } from '../logger';
|
||||
|
||||
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
|
||||
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
|
||||
export class CanceledError extends Error {
|
||||
constructor() {
|
||||
super(localize('ssh.canceled', 'SSH command canceled'));
|
||||
}
|
||||
}
|
||||
|
||||
export interface ICommandResult {
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
}
|
||||
|
||||
export function showPassphraseInputBox(
|
||||
keyName?: string,
|
||||
prompt?: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
const keyStr: string = keyName ? `"${keyName}"` : '';
|
||||
const msg: string = localize('ssh.passphrase.input.box', 'Enter passphrase for ssh key {0}', keyStr);
|
||||
return showInputBox(msg, prompt, cancelToken);
|
||||
}
|
||||
|
||||
export function showPasswordInputBox(
|
||||
user: string | undefined,
|
||||
prompt?: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
const msg: string = user ? localize('ssh.enter.password.for.user', 'Enter password for user "{0}"', user) : localize('ssh_message_enterPassword', 'Enter password');
|
||||
return showInputBox(msg, prompt, cancelToken);
|
||||
}
|
||||
|
||||
export function showVerificationCodeInputBox(
|
||||
msg: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
return showInputBox(msg, undefined, cancelToken);
|
||||
}
|
||||
|
||||
export async function showInputBox(
|
||||
msg: string,
|
||||
prompt?: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const quickPick: vscode.InputBox = vscode.window.createInputBox();
|
||||
quickPick.title = msg;
|
||||
quickPick.prompt = prompt;
|
||||
quickPick.password = true;
|
||||
quickPick.ignoreFocusOut = true;
|
||||
|
||||
let isAccepted: boolean = false;
|
||||
|
||||
quickPick.onDidAccept(() => {
|
||||
isAccepted = true;
|
||||
const passphrase: string = quickPick.value;
|
||||
quickPick.dispose();
|
||||
resolve(passphrase);
|
||||
});
|
||||
|
||||
quickPick.onDidHide(() => {
|
||||
if (!isAccepted) {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
|
||||
quickPick.show();
|
||||
|
||||
if (cancelToken) {
|
||||
cancelToken.onCancellationRequested(() => {
|
||||
reject(new CanceledError());
|
||||
quickPick.dispose();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class ConfirmationItem implements vscode.QuickPickItem, vscode.MessageItem {
|
||||
title: string;
|
||||
isCloseAffordance: boolean = true;
|
||||
constructor(public label: string, public value: string) {
|
||||
this.title = label;
|
||||
}
|
||||
}
|
||||
|
||||
const continueConfirmationPlaceholder: string = localize('ssh.continue.confirmation.placeholder', 'Are you sure you want to continue?');
|
||||
|
||||
export async function showHostKeyConfirmation(
|
||||
host: string,
|
||||
fingerprint: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
return showConfirmationPicker(
|
||||
localize('ssh.host.key.confirmation.title', '"{0}" has fingerprint "{1}".', host, fingerprint),
|
||||
continueConfirmationPlaceholder,
|
||||
cancelToken
|
||||
);
|
||||
}
|
||||
|
||||
export async function showDifferingHostConfirmation(
|
||||
message: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
return showConfirmationPicker(message, continueConfirmationPlaceholder, cancelToken);
|
||||
}
|
||||
|
||||
async function showConfirmationPicker(
|
||||
title: string,
|
||||
placeholder: string,
|
||||
cancelToken?: vscode.CancellationToken
|
||||
): Promise<string | undefined> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const quickPick: vscode.QuickPick<ConfirmationItem> = vscode.window.createQuickPick<ConfirmationItem>();
|
||||
quickPick.canSelectMany = false;
|
||||
quickPick.items = [new ConfirmationItem(localize('continue', 'Continue'), 'yes'), new ConfirmationItem(localize('cancel', 'Cancel'), 'no')];
|
||||
quickPick.title = title;
|
||||
quickPick.placeholder = placeholder;
|
||||
|
||||
let isAccepted: boolean = false;
|
||||
|
||||
quickPick.onDidAccept(async () => {
|
||||
isAccepted = true;
|
||||
const value: string = quickPick.selectedItems[0].value;
|
||||
quickPick.dispose();
|
||||
resolve(value);
|
||||
});
|
||||
|
||||
quickPick.onDidHide(() => {
|
||||
if (!isAccepted) {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
|
||||
quickPick.show();
|
||||
|
||||
if (cancelToken) {
|
||||
cancelToken.onCancellationRequested(() => {
|
||||
quickPick.hide();
|
||||
reject(new CanceledError());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export interface ITerminalCommandWithLoginArgs {
|
||||
systemInteractor: ISystemInteractor;
|
||||
command: string;
|
||||
nickname: string;
|
||||
marker?: string;
|
||||
usedInteractors?: Set<string>;
|
||||
interactor?: IInteractor;
|
||||
cwd?: string;
|
||||
token?: vscode.CancellationToken;
|
||||
continueOn?: string;
|
||||
|
||||
revealTerminal?: vscode.Event<void>;
|
||||
}
|
||||
|
||||
export async function runSshTerminalCommandWithLogin(
|
||||
host: ISshHostInfo,
|
||||
terminalArgs: ITerminalCommandWithLoginArgs,
|
||||
showLoginTerminal = false
|
||||
): Promise<ProcessReturnType> {
|
||||
const interactors: IInteractor[] = [];
|
||||
|
||||
if (terminalArgs.interactor) {
|
||||
interactors.push(terminalArgs.interactor);
|
||||
}
|
||||
|
||||
if (!showLoginTerminal) {
|
||||
interactors.push(
|
||||
new MitmInteractor(),
|
||||
new FingerprintInteractor(host.hostName, showHostKeyConfirmation),
|
||||
new PassphraseInteractor(showPassphraseInputBox),
|
||||
new DifferingHostKeyInteractor(showDifferingHostConfirmation),
|
||||
new PasswordInteractor(showPasswordInputBox),
|
||||
new TwoFacInteractor(showVerificationCodeInputBox),
|
||||
new DuoTwoFacInteractor(showVerificationCodeInputBox)
|
||||
);
|
||||
}
|
||||
|
||||
if (terminalArgs.continueOn) {
|
||||
interactors.push(new ContinueOnInteractor(terminalArgs.continueOn));
|
||||
}
|
||||
|
||||
// This terminal is always local
|
||||
const result: ProcessReturnType = await runInteractiveSshTerminalCommand({
|
||||
systemInteractor: terminalArgs.systemInteractor,
|
||||
command: terminalArgs.command,
|
||||
interactors,
|
||||
usedInteractors: terminalArgs.usedInteractors,
|
||||
nickname: terminalArgs.nickname,
|
||||
token: terminalArgs.token,
|
||||
marker: terminalArgs.marker,
|
||||
revealTerminal: terminalArgs.revealTerminal,
|
||||
showLoginTerminal,
|
||||
cwd: terminalArgs.cwd ? vscode.Uri.file(terminalArgs.cwd) : undefined
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface ITerminalCommandArgs {
|
||||
systemInteractor: ISystemInteractor;
|
||||
command: string;
|
||||
interactors?: IInteractor[];
|
||||
nickname: string;
|
||||
usedInteractors?: Set<string>;
|
||||
sendText?: string;
|
||||
cwd?: vscode.Uri;
|
||||
terminalIsWindows?: boolean;
|
||||
token?: vscode.CancellationToken;
|
||||
marker?: string;
|
||||
revealTerminal?: vscode.Event<void>;
|
||||
showLoginTerminal?: boolean; // If true, respect the showLoginTerminal setting
|
||||
}
|
||||
|
||||
export function getPauseLogMarker(uuid: string): string {
|
||||
return `${uuid}: pauseLog`;
|
||||
}
|
||||
|
||||
export function getResumeLogMarker(uuid: string): string {
|
||||
return `${uuid}: resumeLog`;
|
||||
}
|
||||
|
||||
export function runInteractiveSshTerminalCommand(args: ITerminalCommandArgs): Promise<ProcessReturnType> {
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
const { systemInteractor, command, interactors, nickname, token } = args;
|
||||
let logIsPaused: boolean = false;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let stdout: string = '';
|
||||
let windowListener: vscode.Disposable | undefined;
|
||||
let terminalListener: vscode.Disposable | undefined;
|
||||
let terminal: vscode.Terminal | undefined;
|
||||
let tokenListener: vscode.Disposable;
|
||||
let continueWithoutExiting: boolean = false;
|
||||
|
||||
const clean = () => {
|
||||
if (terminalListener) {
|
||||
terminalListener.dispose();
|
||||
terminalListener = undefined;
|
||||
}
|
||||
|
||||
if (terminal) {
|
||||
terminal.dispose();
|
||||
terminal = undefined;
|
||||
}
|
||||
|
||||
if (windowListener) {
|
||||
windowListener.dispose();
|
||||
windowListener = undefined;
|
||||
}
|
||||
|
||||
if (tokenListener) {
|
||||
tokenListener.dispose();
|
||||
}
|
||||
|
||||
disposables.forEach(disposable => disposable.dispose());
|
||||
};
|
||||
|
||||
const done = (cancel: boolean = false, noClean: boolean = false, exitCode?: number) => {
|
||||
if (!noClean) {
|
||||
clean();
|
||||
}
|
||||
getOutputChannelLogger().appendLine(cancel ? localize('ssh.terminal.command.canceled', '"{0}" terminal command canceled.', nickname) : localize('ssh.terminal.command.done', '"{0}" terminal command done.', nickname));
|
||||
|
||||
if (cancel) {
|
||||
if (continueWithoutExiting) {
|
||||
getOutputChannelLogger().showWarningMessage(localize('ssh.continuing.command.canceled', 'Task \'{0}\' is canceled, but the underlying command may not be terminated. Please check manually.', command));
|
||||
}
|
||||
return reject(new CanceledError());
|
||||
}
|
||||
|
||||
// When using showLoginTerminal, stdout include the passphrase prompt, etc. Try to get just the command output on the last line.
|
||||
const actualOutput: string | undefined = cancel ? '' : lastNonemptyLine(stdout);
|
||||
resolve({ succeeded: !exitCode, exitCode, output: actualOutput || '' });
|
||||
};
|
||||
|
||||
const failed = (error?: any) => {
|
||||
clean();
|
||||
getOutputChannelLogger().showErrorMessage(localize('ssh.process.failed', '"{0}" process failed: {1}', nickname, error));
|
||||
reject(error);
|
||||
};
|
||||
|
||||
const handleOutputLogging = (data: string): void => {
|
||||
let nextPauseState: boolean | undefined;
|
||||
if (args.marker) {
|
||||
const pauseMarker: string = getPauseLogMarker(args.marker);
|
||||
const pauseIdx: number = data.lastIndexOf(pauseMarker);
|
||||
if (pauseIdx >= 0) {
|
||||
data = data.substring(0, pauseIdx + pauseMarker.length);
|
||||
nextPauseState = true;
|
||||
}
|
||||
|
||||
const resumeIdx: number = data.lastIndexOf(getResumeLogMarker(args.marker));
|
||||
if (resumeIdx >= 0) {
|
||||
data = data.substring(resumeIdx);
|
||||
nextPauseState = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the chunk of data that includes the pause/resume markers,
|
||||
// so unpause first and pause after logging
|
||||
if (!logIsPaused) {
|
||||
logReceivedData(data, nickname);
|
||||
}
|
||||
|
||||
if (typeof nextPauseState === 'boolean') {
|
||||
logIsPaused = nextPauseState;
|
||||
}
|
||||
};
|
||||
|
||||
const handleTerminalOutput = async (dataWrite: vscode.TerminalDataWriteEvent): Promise<void> => {
|
||||
handleOutputLogging(dataWrite.data);
|
||||
stdout += dataWrite.data;
|
||||
|
||||
if (interactors) {
|
||||
for (const interactor of interactors) {
|
||||
try {
|
||||
const interaction: IInteraction = await interactor.onData(stdout);
|
||||
|
||||
if (interaction.postAction === 'consume') {
|
||||
if (args.usedInteractors) {
|
||||
args.usedInteractors.add(interactor.id);
|
||||
}
|
||||
|
||||
stdout = '';
|
||||
}
|
||||
|
||||
if (interaction.canceled) {
|
||||
if (args.usedInteractors) {
|
||||
args.usedInteractors.add(interactor.id);
|
||||
}
|
||||
|
||||
done(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (interaction.continue) {
|
||||
if (args.usedInteractors) {
|
||||
args.usedInteractors.add(interactor.id);
|
||||
}
|
||||
continueWithoutExiting = true;
|
||||
done(false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof interaction.response === 'string') {
|
||||
if (args.usedInteractors) {
|
||||
args.usedInteractors.add(interactor.id);
|
||||
}
|
||||
|
||||
if (terminal) {
|
||||
terminal.sendText(`${interaction.response}\n`);
|
||||
const logOutput: string = interaction.isPassword
|
||||
? interaction.response.replace(/./g, '*')
|
||||
: interaction.response;
|
||||
getOutputChannelLogger().appendLine(localize('ssh.wrote.data.to.terminal', '"{0}" wrote data to terminal: "{1}".', nickname, logOutput));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
failed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (token) {
|
||||
tokenListener = token.onCancellationRequested(() => {
|
||||
done(true);
|
||||
});
|
||||
}
|
||||
|
||||
const terminalIsWindows: boolean = typeof args.terminalIsWindows === 'boolean' ? args.terminalIsWindows : isWindows();
|
||||
try {
|
||||
// the terminal process should not fail, but exit cleanly
|
||||
let shellArgs: string | string[];
|
||||
if (args.sendText) {
|
||||
shellArgs = '';
|
||||
} else {
|
||||
shellArgs = terminalIsWindows ? `/c (${command})\nexit /b %ErrorLevel%` : ['-c', `${command}\nexit $?`];
|
||||
}
|
||||
|
||||
const options: vscode.TerminalOptions = {
|
||||
cwd:
|
||||
args.cwd ||
|
||||
(terminalIsWindows
|
||||
? vscode.Uri.file(os.homedir() || 'c:\\')
|
||||
: vscode.Uri.file(os.homedir() || '/')),
|
||||
name: nickname,
|
||||
shellPath: getShellPath(terminalIsWindows),
|
||||
shellArgs,
|
||||
hideFromUser: true
|
||||
};
|
||||
|
||||
let terminalDataHandlingQueue: Promise<void> = Promise.resolve();
|
||||
terminalListener = systemInteractor.onDidWriteTerminalData(async e => {
|
||||
if (e.terminal !== terminal) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalDataHandlingQueue = terminalDataHandlingQueue.finally(() => handleTerminalOutput(e));
|
||||
});
|
||||
terminal = systemInteractor.createTerminal(options);
|
||||
|
||||
if (args.revealTerminal) {
|
||||
disposables.push(
|
||||
args.revealTerminal(() => {
|
||||
if (terminal) {
|
||||
terminal.show();
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (args.sendText) {
|
||||
const sendText: string = terminalIsWindows ? `(${args.sendText})\nexit /b %ErrorLevel%` : `${args.sendText}\nexit $?`;
|
||||
|
||||
terminal.sendText(sendText);
|
||||
getOutputChannelLogger().appendLine(localize('ssh.wrote.data.to.terminal', '"{0}" wrote data to terminal: "{1}".', nickname, args.sendText));
|
||||
}
|
||||
|
||||
if (args.showLoginTerminal) {
|
||||
terminal.show();
|
||||
}
|
||||
|
||||
windowListener = systemInteractor.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
terminal = undefined; // Is already disposed
|
||||
done(false, false, t.exitStatus?.code);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
failed(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getShellPath(_isWindows: boolean): string {
|
||||
if (_isWindows) {
|
||||
// Some users don't have cmd.exe on the path...
|
||||
if (process.env.SystemRoot) {
|
||||
// This var should always exist but be paranoid
|
||||
const cmdPath: string = path.join(process.env.SystemRoot, 'System32', 'cmd.exe');
|
||||
return cmdPath;
|
||||
} else {
|
||||
return 'cmd.exe';
|
||||
}
|
||||
} else {
|
||||
// Note - can't rely on having sh in path (#590), and can't check the disk (bc remote terminals)
|
||||
return '/bin/sh';
|
||||
}
|
||||
}
|
||||
|
||||
function logReceivedData(data: string, nickname: string): void {
|
||||
const logData: string = data.replace(/\r?\n$/, ''); // Trim single trailing newline for nicer log
|
||||
if (logData === ' ') {
|
||||
// From the sleep command that must periodically echo ' '
|
||||
return;
|
||||
}
|
||||
const markedLines: string = logData
|
||||
.split(/\n/)
|
||||
.map(line => `${nickname}> ${line}`)
|
||||
.join('\n');
|
||||
|
||||
getOutputChannelLogger().appendLine(markedLines);
|
||||
}
|
||||
|
||||
function lastNonemptyLine(str: string): string | undefined {
|
||||
const lines: string[] = splitLines(str);
|
||||
|
||||
if (isWindows()) {
|
||||
let outputContainingPipeError: string = '';
|
||||
for (let i: number = lines.length - 1; i >= 0; i--) {
|
||||
const strippedLine: string = stripEscapeSequences(lines[i]);
|
||||
if (strippedLine.match(/The process tried to write to a nonexistent pipe/)) {
|
||||
outputContainingPipeError = strippedLine;
|
||||
continue;
|
||||
}
|
||||
if (!!strippedLine) {
|
||||
return strippedLine;
|
||||
}
|
||||
}
|
||||
|
||||
if (outputContainingPipeError) {
|
||||
return outputContainingPipeError;
|
||||
}
|
||||
}
|
||||
|
||||
const nonEmptyLines: string[] = lines.filter(l => !!l);
|
||||
return nonEmptyLines[nonEmptyLines.length - 1];
|
||||
}
|
|
@ -18,9 +18,9 @@ import * as https from 'https';
|
|||
import * as tmp from 'tmp';
|
||||
import { ClientRequest, OutgoingHttpHeaders } from 'http';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Readable } from 'stream';
|
||||
import * as jsonc from 'comment-json';
|
||||
import { TargetPopulation } from 'vscode-tas-client';
|
||||
import { CppSettings } from './LanguageServer/settings';
|
||||
|
||||
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
|
||||
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
|
@ -320,13 +320,10 @@ export function resolveCachePath(input: string | undefined, additionalEnvironmen
|
|||
return resolvedPath;
|
||||
}
|
||||
|
||||
export function isWindows(): boolean {
|
||||
return os.platform() === 'win32';
|
||||
}
|
||||
|
||||
export function defaultExePath(): string {
|
||||
const isWindows: boolean = os.platform() === 'win32';
|
||||
const exePath: string = path.join('${fileDirname}', '${fileBasenameNoExtension}');
|
||||
return isWindows() ? exePath + '.exe' : exePath;
|
||||
return isWindows ? exePath + '.exe' : exePath;
|
||||
}
|
||||
|
||||
export function findExePathInArgs(args: string[]): string | undefined {
|
||||
|
@ -572,9 +569,9 @@ export function checkDirectoryExistsSync(dirPath: string): boolean {
|
|||
}
|
||||
|
||||
/** Test whether a relative path exists */
|
||||
export function checkPathExistsSync(path: string, relativePath: string, _isWindows: boolean, isWSL: boolean, isCompilerPath: boolean): { pathExists: boolean; path: string } {
|
||||
export function checkPathExistsSync(path: string, relativePath: string, isWindows: boolean, isWSL: boolean, isCompilerPath: boolean): { pathExists: boolean; path: string } {
|
||||
let pathExists: boolean = true;
|
||||
const existsWithExeAdded: (path: string) => boolean = (path: string) => isCompilerPath && _isWindows && !isWSL && fs.existsSync(path + ".exe");
|
||||
const existsWithExeAdded: (path: string) => boolean = (path: string) => isCompilerPath && isWindows && !isWSL && fs.existsSync(path + ".exe");
|
||||
if (!fs.existsSync(path)) {
|
||||
if (existsWithExeAdded(path)) {
|
||||
path += ".exe";
|
||||
|
@ -713,83 +710,32 @@ export function execChildProcess(process: string, workingDirectory?: string, cha
|
|||
});
|
||||
}
|
||||
|
||||
export interface ProcessReturnType {
|
||||
succeeded: boolean;
|
||||
exitCode?: number | NodeJS.Signals;
|
||||
output: string;
|
||||
}
|
||||
export function spawnChildProcess(process: string, args: string[], workingDirectory: string,
|
||||
dataCallback: (stdout: string) => void, errorCallback: (stderr: string) => void): Promise<void> {
|
||||
|
||||
export async function spawnChildProcess(program: string, args: string[] = [], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessReturnType> {
|
||||
const programOutput: ProcessOutput = await spawnChildProcessImpl(program, args, continueOn, cancellationToken);
|
||||
const exitCode: number | NodeJS.Signals | undefined = programOutput.exitCode;
|
||||
const settings: CppSettings = new CppSettings();
|
||||
if (settings.loggingLevel === "Information" || settings.loggingLevel === "Debug") {
|
||||
getOutputChannelLogger().appendLine(`$ ${program} ${args.join(' ')}\n${programOutput.stderr || programOutput.stdout}\n`);
|
||||
}
|
||||
if (programOutput.exitCode) {
|
||||
return { succeeded: false, exitCode, output: programOutput.stderr || programOutput.stdout || localize('process.exited', 'Process exited with code {0}', exitCode) };
|
||||
} else {
|
||||
let stdout: string;
|
||||
if (programOutput.stdout.length) {
|
||||
// Type system doesn't work very well here, so we need call toString
|
||||
stdout = programOutput.stdout;
|
||||
} else {
|
||||
stdout = localize('process.succeeded', 'Process executed successfully.');
|
||||
}
|
||||
return { succeeded: true, exitCode, output: stdout };
|
||||
}
|
||||
}
|
||||
return new Promise<void>(function (resolve, reject): void {
|
||||
const child: child_process.ChildProcess = child_process.spawn(process, args, { cwd: workingDirectory });
|
||||
|
||||
interface ProcessOutput {
|
||||
exitCode?: number | NodeJS.Signals;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
}
|
||||
|
||||
async function spawnChildProcessImpl(program: string, args: string[], continueOn?: string, cancellationToken?: vscode.CancellationToken): Promise<ProcessOutput> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let proc: child_process.ChildProcess;
|
||||
if (await isExecutable(program)) {
|
||||
proc = child_process.spawn(`.${isWindows() ? '\\' : '/'}${path.basename(program)}`, args, { shell: true, cwd: path.dirname(program) });
|
||||
} else {
|
||||
proc = child_process.spawn(program, args, { shell: true });
|
||||
}
|
||||
|
||||
const cancellationTokenListener: vscode.Disposable | undefined = cancellationToken?.onCancellationRequested(() => {
|
||||
getOutputChannelLogger().appendLine(localize('killing.process', 'Killing process {0}', program));
|
||||
proc.kill();
|
||||
});
|
||||
|
||||
const clean = () => {
|
||||
proc.removeAllListeners();
|
||||
if (cancellationTokenListener) {
|
||||
cancellationTokenListener.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
let stdout: string = '';
|
||||
let stderr: string = '';
|
||||
if (proc.stdout) {
|
||||
proc.stdout.on('data', data => {
|
||||
stdout += data.toString();
|
||||
if (continueOn) {
|
||||
const continueOnReg: string = escapeStringForRegex(continueOn);
|
||||
if (stdout.search(continueOnReg)) {
|
||||
resolve({ stdout: stdout.trim(), stderr: stderr.trim() });
|
||||
}
|
||||
}
|
||||
const stdout: Readable | null = child.stdout;
|
||||
if (stdout) {
|
||||
stdout.on('data', (data) => {
|
||||
dataCallback(`${data}`);
|
||||
});
|
||||
}
|
||||
if (proc.stderr) {
|
||||
proc.stderr.on('data', data => stderr += data.toString());
|
||||
|
||||
const stderr: Readable | null = child.stderr;
|
||||
if (stderr) {
|
||||
stderr.on('data', (data) => {
|
||||
errorCallback(`${data}`);
|
||||
});
|
||||
}
|
||||
proc.on('close', (code, signal) => {
|
||||
clean();
|
||||
resolve({ exitCode: code || signal, stdout: stdout.trim(), stderr: stderr.trim() });
|
||||
});
|
||||
proc.on('error', error => {
|
||||
clean();
|
||||
reject(error);
|
||||
|
||||
child.on('exit', (code: number) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(localize("process.exited.with.code", "{0} exited with error code {1}", process, code)));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -980,6 +926,7 @@ function resolveWindowsEnvironmentVariables(str: string): string {
|
|||
}
|
||||
|
||||
function legacyExtractArgs(argsString: string): string[] {
|
||||
const isWindows: boolean = os.platform() === 'win32';
|
||||
const result: string[] = [];
|
||||
let currentArg: string = "";
|
||||
let isWithinDoubleQuote: boolean = false;
|
||||
|
@ -1003,7 +950,7 @@ function legacyExtractArgs(argsString: string): string[] {
|
|||
}
|
||||
} else if (c === '\'') {
|
||||
// On Windows, a single quote string is not allowed to join multiple args into a single arg
|
||||
if (!isWindows()) {
|
||||
if (!isWindows) {
|
||||
if (!isWithinDoubleQuote) {
|
||||
isWithinSingleQuote = !isWithinSingleQuote;
|
||||
}
|
||||
|
@ -1462,38 +1409,3 @@ export function isVsCodeInsiders(): boolean {
|
|||
extensionPath.includes(".vscode-server-exploration");
|
||||
}
|
||||
|
||||
export function stripEscapeSequences(str: string): string {
|
||||
return str
|
||||
.replace(/\x1b\[\??[0-9]{0,3}(;[0-9]{1,3})?[a-zA-Z]/g, '')
|
||||
.replace(/\u0008/g, '')
|
||||
.replace(/\r/g, '');
|
||||
}
|
||||
|
||||
export function splitLines(data: string): string[] {
|
||||
return data.split(/\r?\n/g);
|
||||
}
|
||||
|
||||
export function escapeStringForRegex(str: string): string {
|
||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
|
||||
}
|
||||
|
||||
export function replaceAll(str: string, searchValue: string, replaceValue: string): string {
|
||||
const pattern: string = escapeStringForRegex(searchValue);
|
||||
const re: RegExp = new RegExp(pattern, 'g');
|
||||
return str.replace(re, replaceValue);
|
||||
}
|
||||
|
||||
export interface ISshHostInfo {
|
||||
hostName: string;
|
||||
user?: string;
|
||||
port?: number | string;
|
||||
}
|
||||
|
||||
export interface ISshLocalForwardInfo {
|
||||
bindAddress?: string;
|
||||
port?: number | string;
|
||||
host?: string;
|
||||
hostPort?: number | string;
|
||||
localSocket?: string;
|
||||
remoteSocket?: string;
|
||||
}
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { isString, replaceAll } from './common';
|
||||
import { getOutputChannelLogger } from './logger';
|
||||
|
||||
/**
|
||||
* Support ExpansionVars (${var}), env (${env:var}), and optionally VS CODE commands (${command:commandID}).
|
||||
* Supported format follows https://code.visualstudio.com/docs/editor/variables-reference
|
||||
* Expand options and functions are mofidifed from https://github.com/microsoft/vscode-cmake-tools/blob/main/src/expand.ts
|
||||
*/
|
||||
|
||||
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
|
||||
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
|
||||
|
||||
export interface ExpansionVars {
|
||||
[key: string]: string;
|
||||
workspaceFolder: string;
|
||||
workspaceFolderBasename: string;
|
||||
}
|
||||
|
||||
export interface ExpansionOptions {
|
||||
vars: ExpansionVars;
|
||||
doNotSupportCommands?: boolean;
|
||||
recursive?: boolean;
|
||||
}
|
||||
|
||||
export async function expandAllStrings(obj: any, options: ExpansionOptions): Promise<void> {
|
||||
if (Array.isArray(obj) || (obj !== null && typeof obj === 'object')) {
|
||||
for (const key of Object.keys(obj)) {
|
||||
if (isString(obj[key])) {
|
||||
obj[key] = await expandString(obj[key], options);
|
||||
} else {
|
||||
await expandAllStrings(obj[key], options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function expandString(input: string, options: ExpansionOptions): Promise<string> {
|
||||
const MAX_RECURSION: number = 10;
|
||||
let result: string = input;
|
||||
let didReplacement: boolean = false;
|
||||
|
||||
let i: number = 0;
|
||||
do {
|
||||
// TODO: consider a full circular reference check?
|
||||
[result, didReplacement] = await expandStringImpl(result, options);
|
||||
i++;
|
||||
} while (i < MAX_RECURSION && options.recursive && didReplacement);
|
||||
|
||||
if (i === MAX_RECURSION && didReplacement) {
|
||||
getOutputChannelLogger().showErrorMessage(localize('max.recursion.reached', 'Reached max string expansion recursion. Possible circular reference.'));
|
||||
}
|
||||
|
||||
return replaceAll(result, '${dollar}', '$');
|
||||
}
|
||||
|
||||
/** Returns [expandedString, didReplacement] */
|
||||
async function expandStringImpl(input: string, options: ExpansionOptions): Promise<[string, boolean]> {
|
||||
if (!input) {
|
||||
return [input, false];
|
||||
}
|
||||
|
||||
// We accumulate a list of substitutions that we need to make, preventing
|
||||
// recursively expanding or looping forever on bad replacements
|
||||
const subs: Map<string, string> = new Map<string, string>();
|
||||
|
||||
const var_re: RegExp = /\$\{(\w+)\}/g;
|
||||
let match: RegExpMatchArray | null = null;
|
||||
while ((match = var_re.exec(input))) {
|
||||
const full: string = match[0];
|
||||
const key: string = match[1];
|
||||
if (key !== 'dollar') {
|
||||
// Replace dollar sign at the very end of the expanding process
|
||||
const repl: string = options.vars[key];
|
||||
if (!repl) {
|
||||
getOutputChannelLogger().showWarningMessage(localize('invalid.var.reference', 'Invalid variable reference {0} in string: {1}.', full, input));
|
||||
} else {
|
||||
subs.set(full, repl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Regular expression for variable value (between the variable suffix and the next ending curly bracket):
|
||||
// .+? matches any character (except line terminators) between one and unlimited times,
|
||||
// as few times as possible, expanding as needed (lazy)
|
||||
const varValueRegexp: string = ".+?";
|
||||
const env_re: RegExp = RegExp(`\\$\\{env:(${varValueRegexp})\\}`, "g");
|
||||
while ((match = env_re.exec(input))) {
|
||||
const full: string = match[0];
|
||||
const varname: string = match[1];
|
||||
if (process.env[varname] === undefined) {
|
||||
getOutputChannelLogger().showWarningMessage(localize('env.var.not.found', 'Environment variable {0} not found', varname));
|
||||
}
|
||||
const repl: string = process.env[varname] || '';
|
||||
subs.set(full, repl);
|
||||
}
|
||||
|
||||
const command_re: RegExp = RegExp(`\\$\\{command:(${varValueRegexp})\\}`, "g");
|
||||
while ((match = command_re.exec(input))) {
|
||||
if (options.doNotSupportCommands) {
|
||||
getOutputChannelLogger().showWarningMessage(localize('commands.not.supported', 'Commands are not supported for string: {0}.', input));
|
||||
break;
|
||||
}
|
||||
const full: string = match[0];
|
||||
const command: string = match[1];
|
||||
if (subs.has(full)) {
|
||||
continue; // Don't execute commands more than once per string
|
||||
}
|
||||
try {
|
||||
const command_ret: unknown = await vscode.commands.executeCommand(command, options.vars.workspaceFolder);
|
||||
subs.set(full, `${command_ret}`);
|
||||
} catch (e: any) {
|
||||
getOutputChannelLogger().showWarningMessage(localize('exception.executing.command', 'Exception while executing command {0} for string: {1} {2}.', command, input, e));
|
||||
}
|
||||
}
|
||||
|
||||
let result: string = input;
|
||||
let didReplacement: boolean = false;
|
||||
subs.forEach((value, key) => {
|
||||
if (value !== key) {
|
||||
result = replaceAll(result, key, value);
|
||||
didReplacement = true;
|
||||
}
|
||||
});
|
||||
|
||||
return [result, didReplacement];
|
||||
}
|
|
@ -89,11 +89,11 @@ export async function deactivate(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }, metrics?: { [key: string]: number }): void {
|
||||
export function logDebuggerEvent(eventName: string, properties?: { [key: string]: string }): void {
|
||||
const sendTelemetry = () => {
|
||||
if (experimentationTelemetry) {
|
||||
const eventNamePrefix: string = "cppdbg/VS/Diagnostics/Debugger/";
|
||||
experimentationTelemetry.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics);
|
||||
experimentationTelemetry.sendTelemetryEvent(eventNamePrefix + eventName, properties);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
"include": [
|
||||
"test/**/*.ts",
|
||||
"tools/**/*.ts",
|
||||
"ui/**/*.ts",
|
||||
"./vscode*.d.ts"
|
||||
"ui/**/*.ts"
|
||||
]
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All Rights Reserved.
|
||||
* See 'LICENSE' in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
import * as assert from "assert";
|
||||
import { ExpansionOptions, expandAllStrings, expandString } from "../../src/expand";
|
||||
|
||||
suite('Var expansion validation', () => {
|
||||
test('Expand all strings', async () => {
|
||||
const input: object = {
|
||||
in1: "${test2}",
|
||||
in2: "${test4}",
|
||||
in3: [
|
||||
"${test3}",
|
||||
{
|
||||
in4: "${test3}"
|
||||
}
|
||||
]
|
||||
};
|
||||
const variables: object = {
|
||||
test1: "t1",
|
||||
test2: "${dollar}{${test1}}",
|
||||
test3: "test${test2}test:${env:envtest}:${dollar}test",
|
||||
test4: "${test4}"
|
||||
};
|
||||
const expansionOptions: ExpansionOptions = {
|
||||
vars: {
|
||||
workspaceFolder: '{workspaceFolder}',
|
||||
workspaceFolderBasename: '{workspaceFolderBasename}',
|
||||
...variables
|
||||
},
|
||||
recursive: true
|
||||
};
|
||||
await expandAllStrings(input, expansionOptions);
|
||||
assert.deepStrictEqual(input, {
|
||||
in1: "${t1}",
|
||||
in2: "${test4}",
|
||||
in3: [
|
||||
"test${t1}test::$test",
|
||||
{
|
||||
in4: "test${t1}test::$test"
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
|
@ -53,7 +53,7 @@ function updateDefaults(object: any, defaults: any): any {
|
|||
}
|
||||
|
||||
function refReplace(definitions: any, ref: any): any {
|
||||
// $ref is formatted as "#/definitions/ObjectName"
|
||||
// $ref is formatted as "#/definitions/ObjectName"
|
||||
const referenceStringArray: string[] = ref['$ref'].split('/');
|
||||
|
||||
// Getting "ObjectName"
|
||||
|
@ -82,7 +82,11 @@ function replaceReferences(definitions: any, objects: any): any {
|
|||
|
||||
// Handle 'anyOf' with references
|
||||
if (objects[key].hasOwnProperty('anyOf')) {
|
||||
objects[key].anyOf = replaceReferences(definitions, objects[key].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.
|
||||
|
@ -91,15 +95,10 @@ function replaceReferences(definitions: any, objects: any): any {
|
|||
objects[key].properties = updateDefaults(objects[key].properties, objects[key].default);
|
||||
}
|
||||
|
||||
// Items in array contains ref
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Recursively replace references if the array has objects that contains ref in items.
|
||||
if (objects[key].hasOwnProperty('type') && objects[key].type === "array" && objects[key].items !== null) {
|
||||
objects[key].items = replaceReferences(definitions, objects[key].items);
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
|
|
|
@ -193,313 +193,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"Variables": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.variables.description%",
|
||||
"default": {
|
||||
"<variable-name>": "<variable-value>"
|
||||
},
|
||||
"properties": {},
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.variables.properties.description%",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"VsCodeCommand": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"command"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.vsCodeCommand.args.description%",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Host": {
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.host.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
},
|
||||
"jumpHosts": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.jumpHost.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"hostName"
|
||||
],
|
||||
"properties": {
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.user.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.hostName.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.port.description%",
|
||||
"default": 22
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"localForwards": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.host.localForward.description%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"bindAddress": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.bindAddress.description%",
|
||||
"default": ""
|
||||
},
|
||||
"port": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.port.description%"
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.host.description%",
|
||||
"default": ""
|
||||
},
|
||||
"hostPort": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\d+$|^\\${.+}$"
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.host.localForward.hostPort.description%"
|
||||
},
|
||||
"localSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.localSocket.description%",
|
||||
"default": ""
|
||||
},
|
||||
"remoteSocket": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.host.localForward.remoteSocket.description%",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"DeploySteps": {
|
||||
"type": "array",
|
||||
"description": "%c_cpp.debuggers.deploySteps.description%",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"files",
|
||||
"host",
|
||||
"targetDir"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"scp"
|
||||
]
|
||||
},
|
||||
"files": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.files.description%",
|
||||
"default": ""
|
||||
},
|
||||
"host": {
|
||||
"$ref": "#/definitions/Host"
|
||||
},
|
||||
"targetDir": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.targetDir.description%",
|
||||
"default": ""
|
||||
},
|
||||
"scpPath": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.scp.scpPath.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"host",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"ssh"
|
||||
]
|
||||
},
|
||||
"host": {
|
||||
"$ref": "#/definitions/Host"
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"sshPath": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.ssh.sshPath.description%",
|
||||
"default": ""
|
||||
},
|
||||
"continueOn": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
|
||||
"default": {},
|
||||
"required": [
|
||||
"type",
|
||||
"command"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.description%",
|
||||
"default": "",
|
||||
"enum": [
|
||||
"shell"
|
||||
]
|
||||
},
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.shell.command.description%",
|
||||
"default": ""
|
||||
},
|
||||
"continueOn": {
|
||||
"type": "string",
|
||||
"description": "%c_cpp.debuggers.deploySteps.continueOn.description%",
|
||||
"default": ""
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"description": "%c_cpp.debuggers.deploySteps.debug%"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/VsCodeCommand"
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"CppdbgLaunchOptions": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -560,8 +253,8 @@
|
|||
},
|
||||
"launchCompleteCommand": {
|
||||
"enum": [
|
||||
"exec-run",
|
||||
"exec-continue",
|
||||
"exec-run",
|
||||
"exec-continue",
|
||||
"None"
|
||||
],
|
||||
"description": "%c_cpp.debuggers.launchCompleteCommand.description%",
|
||||
|
@ -706,12 +399,6 @@
|
|||
"$ref": "#/definitions/HardwareBreakpoints",
|
||||
"description": "%c_cpp.debuggers.hardwareBreakpoints.description%",
|
||||
"default": {}
|
||||
},
|
||||
"variables": {
|
||||
"$ref": "#/definitions/Variables"
|
||||
},
|
||||
"deploySteps": {
|
||||
"$ref": "#/definitions/DeploySteps"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -826,12 +513,6 @@
|
|||
"symbolLoadInfo": {
|
||||
"$ref": "#/definitions/SymbolLoadInfo",
|
||||
"description": "%c_cpp.debuggers.symbolLoadInfo.description%"
|
||||
},
|
||||
"variables": {
|
||||
"$ref": "#/definitions/Variables"
|
||||
},
|
||||
"deploySteps": {
|
||||
"$ref": "#/definitions/DeploySteps"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"./vscode*.d.ts",
|
||||
"./node_modules/vscode/vscode.d.ts",
|
||||
"./node_modules/vscode/lib/*"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -290,14 +290,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
|
||||
integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
|
||||
|
||||
"@types/glob@^7.1.3":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
|
||||
integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==
|
||||
dependencies:
|
||||
"@types/minimatch" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.6":
|
||||
version "7.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
|
||||
|
@ -313,11 +305,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/minimatch@*":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
||||
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
|
||||
|
||||
"@types/minimatch@^3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
|
@ -365,6 +352,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.1.0.tgz#19cf73a7bcf641965485119726397a096f0049bd"
|
||||
integrity sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA==
|
||||
|
||||
"@types/vscode@1.65.0":
|
||||
version "1.65.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.65.0.tgz#042dd8d93c32ac62cb826cd0fa12376069d1f448"
|
||||
integrity sha512-wQhExnh2nEzpjDMSKhUvnNmz3ucpd3E+R7wJkOhBNK3No6fG3VUdmVmMOKD0A8NDZDDDiQcLNxe3oGmX5SjJ5w==
|
||||
|
||||
"@types/which@^1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf"
|
||||
|
@ -3534,11 +3526,6 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
|||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
|
||||
|
||||
kleur@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
|
||||
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
|
||||
|
||||
last-run@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b"
|
||||
|
@ -4494,14 +4481,6 @@ progress@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||
|
||||
prompts@^2.1.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
|
||||
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
|
||||
dependencies:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.5"
|
||||
|
||||
prr@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||
|
@ -4970,11 +4949,6 @@ signal-exit@^3.0.3:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
||||
|
||||
sisteransi@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
|
||||
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
|
@ -5867,15 +5841,6 @@ vscode-debugprotocol@1.38.0, vscode-debugprotocol@^1.35.0:
|
|||
resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.38.0.tgz#7a9bcd457e6642f48fabef114c0fa1c25a2fb1e7"
|
||||
integrity sha512-oam9iSjNfXSn71a8bmNsXv8k/rIKSOcllIPrFnNgxd1EMBpfnum+gb7lmRpcH0zSjGb+OH8Ncn8B5tv8srWbNQ==
|
||||
|
||||
vscode-dts@^0.3.2:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-dts/-/vscode-dts-0.3.3.tgz#e5ef3afe76182875b252cca7f449938e4a0bf28a"
|
||||
integrity sha512-JfOsWL0NvfVw0UF9bcTjlv1Onz3Ted7cgpPWKWMnHGB+72t/tn8WFDeKLZO42l2k9KJq/NGS9rFC5gZbyI4FTg==
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
prompts "^2.1.0"
|
||||
rimraf "^3.0.0"
|
||||
|
||||
vscode-jsonrpc@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9"
|
||||
|
|
Загрузка…
Ссылка в новой задаче