Implement envFile (Issue #523) (#928)

* Implement envFile

* Fix linting issues

* Update README

* Only merge envFile on launch type

* Changes as requested by @testforstephen
This commit is contained in:
Chase Colman 2021-01-13 09:40:22 +08:00 committed by GitHub
parent 4f6951db29
commit 9be9832e47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 77 additions and 6 deletions

View File

@ -102,6 +102,11 @@ In case you want to manually edit the configuration, below are the explanation a
}
```
- `envFile` - Absolute path to a file containing environment variable definitions.
```json
"envFile": "${workspaceFolder}/.env"
```
### Don't step into the specified classes or methods
- `stepFilters` - Skip the specified classes or methods you don't want to step into. Class names should be fully qualified. Wildcard is supported.

View File

@ -58,6 +58,7 @@ Please also check the documentation of [Language Support for Java by Red Hat](ht
- `projectName` - The preferred project in which the debugger searches for classes. There could be duplicated class names in different projects. This setting also works when the debugger looks for the specified main class when launching a program. It is required when the workspace has multiple java projects, otherwise the expression evaluation and conditional breakpoint may not work.
- `cwd` - The working directory of the program. Defaults to `${workspaceFolder}`.
- `env` - The extra environment variables for the program.
- `envFile` - Absolute path to a file containing environment variable definitions.
- `stopOnEntry` - Automatically pause the program after launching.
- `console` - The specified console to launch the program. If not specified, use the console specified by the `java.debug.settings.console` user setting.
- `internalConsole` - VS Code debug console (input stream not supported).

View File

@ -441,6 +441,7 @@ Exception in thread "main" java.lang.IllegalStateException
```
CustomEnv: This env is for test plan.
SystemPath: <value of PATH >
FileEnv: Successfully loaded an env from a file.
```
## Runtime classpath entry

View File

@ -294,6 +294,11 @@
"description": "%java.debugger.launch.env.description%",
"default": {}
},
"envFile": {
"type": "string",
"description": "%java.debugger.launch.envFile.description%",
"default": "${workspaceFolder}/.env"
},
"stopOnEntry": {
"type": "boolean",
"description": "%java.debugger.launch.stopOnEntry.description%",

View File

@ -9,6 +9,7 @@
"java.debugger.launch.encoding.description": "The file.encoding setting for the JVM. If not specified, 'UTF-8' will be used. Possible values can be found in https://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html.",
"java.debugger.launch.cwd.description": "The working directory of the program. Defaults to the current workspace root.",
"java.debugger.launch.env.description": "The extra environment variables for the program.",
"java.debugger.launch.envFile.description": "Absolute path to a file containing environment variable definitions.",
"java.debugger.launch.stopOnEntry.description": "Automatically pause the program after launching.",
"java.debugger.launch.internalConsole.description": "VS Code debug console (input stream not supported).",
"java.debugger.launch.integratedTerminal.description": "VS Code integrated terminal.",

View File

@ -9,6 +9,7 @@
"java.debugger.launch.encoding.description": "JVM的file.encoding设置。如果未指定将使用“UTF-8”。可以在http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html中找到可能的值。",
"java.debugger.launch.cwd.description": "应用程序的工作目录。默认为当前工作空间根目录。",
"java.debugger.launch.env.description": "启动应用程序时自定义的环境变量。",
"java.debugger.launch.envFile.description": "环境变量文件绝对路径。",
"java.debugger.launch.stopOnEntry.description": "启动后自动暂停应用程序。",
"java.debugger.launch.internalConsole.description": "VS Code调试控制台不支持输入流。",
"java.debugger.launch.integratedTerminal.description": "VS Code集成终端。",

View File

@ -20,7 +20,7 @@ import { IProgressReporter } from "./progressAPI";
import { progressProvider } from "./progressImpl";
import * as utility from "./utility";
const platformNameMappings: {[key: string]: string} = {
const platformNameMappings: { [key: string]: string } = {
win32: "windows",
linux: "linux",
darwin: "osx",
@ -103,7 +103,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
const isOnStandardMode = await utility.waitForStandardMode(progressReporter);
if (!isOnStandardMode) {
resolve([defaultLaunchConfig]);
return ;
return;
}
if (progressReporter.isCancelled()) {
@ -154,7 +154,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
}
}
private constructLaunchConfigName(mainClass: string, cache: {[key: string]: any}) {
private constructLaunchConfigName(mainClass: string, cache: { [key: string]: any }) {
const name = `Launch ${mainClass.substr(mainClass.lastIndexOf(".") + 1)}`;
if (cache[name] === undefined) {
cache[name] = 0;
@ -165,6 +165,25 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
}
}
private mergeEnvFile(config: vscode.DebugConfiguration) {
const baseEnv = config.env || {};
let result = baseEnv;
if (config.envFile) {
try {
result = {
...baseEnv,
...readEnvFile(config.envFile),
};
} catch (e) {
throw new utility.UserError({
message: "Cannot load environment file.",
type: Type.USAGEERROR,
});
}
}
config.env = result;
}
private async resolveAndValidateDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration,
token?: vscode.CancellationToken) {
let progressReporter = progressProvider.getProgressReporter(config.__progressId);
@ -198,6 +217,8 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
}
if (config.request === "launch") {
this.mergeEnvFile(config);
// If the user doesn't specify 'vmArgs' in launch.json, use the global setting to get the default vmArgs.
if (config.vmArgs === undefined) {
const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings");
@ -383,7 +404,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
private async resolveAndValidateMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration,
progressReporter: IProgressReporter): Promise<lsPlugin.IMainClassOption | undefined> {
if (!config.mainClass || this.isFile(config.mainClass)) {
const currentFile = config.mainClass || _.get(vscode.window.activeTextEditor, "document.uri.fsPath");
const currentFile = config.mainClass || _.get(vscode.window.activeTextEditor, "document.uri.fsPath");
if (currentFile) {
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile));
if (progressReporter.isCancelled()) {
@ -427,7 +448,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
private async fixMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration,
validationResponse: lsPlugin.ILaunchValidationResponse, progressReporter: IProgressReporter):
Promise<lsPlugin.IMainClassOption | undefined> {
Promise<lsPlugin.IMainClassOption | undefined> {
const errors: string[] = [];
if (!validationResponse.mainClass.isValid) {
errors.push(String(validationResponse.mainClass.message));
@ -576,3 +597,35 @@ function convertLogLevel(commonLogLevel: string) {
return "FINE";
}
}
// from vscode-js-debug https://github.com/microsoft/vscode-js-debug/blob/master/src/targets/node/nodeLauncherBase.ts
function readEnvFile(file: string): { [key: string]: string } {
if (!fs.existsSync(file)) {
return {};
}
const buffer = stripBOM(fs.readFileSync(file, "utf8"));
const env: { [key: string]: string } = {};
for (const line of buffer.split("\n")) {
const r = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (!r) {
continue;
}
let value = r[2] || "";
// .env variables never overwrite existing variables (see #21169)
if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
value = value.replace(/\\n/gm, "\n");
}
env[r[1]] = value.replace(/(^['"]|['"]$)/g, "");
}
return env;
}
function stripBOM(s: string): string {
if (s && s[0] === "\uFEFF") {
s = s.substr(1);
}
return s;
}

View File

@ -0,0 +1 @@
FILE_ENV_FOR_TEST_PLAN=Successfully loaded an env from a file.

View File

@ -17,7 +17,8 @@
"projectName": "26.environmentVariables",
"env": {
"CUSTOM_ENV_FOR_TEST_PLAN": "This env is for test plan."
}
},
"envFile": "${workspaceFolder}/.env"
}
]
}

View File

@ -2,7 +2,9 @@ public class EnvrionmentVariable {
public static void main(String[] args) {
String customEnv = System.getenv("CUSTOM_ENV_FOR_TEST_PLAN");
String systemPath = System.getenv("PATH");
String envFromFile = System.getenv("FILE_ENV_FOR_TEST_PLAN");
System.out.println(String.format("CustomEnv: %s", customEnv));
System.out.println(String.format("SystemPath: %s", systemPath));
System.out.println(String.format("FileEnv: %s", envFromFile));
}
}