in src/configurationProvider.ts [190:389]
private async resolveAndValidateDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration,
token?: vscode.CancellationToken) {
let progressReporter = progressProvider.getProgressReporter(config.__progressId);
if (!progressReporter && config.__progressId) {
return undefined;
} else if (!progressReporter) {
progressReporter = progressProvider.createProgressReporter(config.noDebug ? "Run" : "Debug");
}
progressReporter.observe(token);
if (progressReporter.isCancelled()) {
return undefined;
}
try {
const isOnStandardMode = await utility.waitForStandardMode(progressReporter);
if (!isOnStandardMode || progressReporter.isCancelled()) {
return undefined;
}
if (this.isUserSettingsDirty) {
this.isUserSettingsDirty = false;
await updateDebugSettings();
}
// If no debug configuration is provided, then generate one in memory.
if (this.isEmptyConfig(config)) {
config.type = "java";
config.name = "Java Debug";
config.request = "launch";
}
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");
config.vmArgs = debugSettings.vmArgs;
}
// If the user doesn't specify 'console' in launch.json, use the global setting to get the launch console.
if (!config.console) {
const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings");
config.console = debugSettings.console;
}
// If the console is integratedTerminal, don't auto switch the focus to DEBUG CONSOLE.
if (config.console === "integratedTerminal" && !config.internalConsoleOptions) {
config.internalConsoleOptions = "neverOpen";
}
if (needsBuildWorkspace()) {
progressReporter.report("Compiling...");
const proceed = await buildWorkspace(progressReporter);
if (!proceed) {
return undefined;
}
}
if (progressReporter.isCancelled()) {
return undefined;
}
if (!config.mainClass) {
progressReporter.report("Resolving main class...");
} else {
progressReporter.report("Resolving launch configuration...");
}
const mainClassOption = await this.resolveAndValidateMainClass(folder && folder.uri, config, progressReporter);
if (!mainClassOption || !mainClassOption.mainClass) { // Exit silently if the user cancels the prompt fix by ESC.
// Exit the debug session.
return undefined;
}
progressReporter.report("Resolving launch configuration...");
config.mainClass = mainClassOption.mainClass;
config.projectName = mainClassOption.projectName;
if (progressReporter.isCancelled()) {
return undefined;
}
if (_.isEmpty(config.classPaths) && _.isEmpty(config.modulePaths)) {
const result = <any[]>(await lsPlugin.resolveClasspath(config.mainClass, config.projectName));
config.modulePaths = result[0];
config.classPaths = result[1];
} else {
config.modulePaths = await this.resolvePath(folder, config.modulePaths, config.mainClass,
config.projectName, true /*isModulePath*/);
config.classPaths = await this.resolvePath(folder, config.classPaths, config.mainClass,
config.projectName, false /*isModulePath*/);
}
if (_.isEmpty(config.classPaths) && _.isEmpty(config.modulePaths)) {
throw new utility.UserError({
message: "Cannot resolve the modulepaths/classpaths automatically, please specify the value in the launch.json.",
type: Type.USAGEERROR,
});
}
config.javaExec = await lsPlugin.resolveJavaExecutable(config.mainClass, config.projectName);
// Add the default launch options to the config.
config.cwd = config.cwd || _.get(folder, "uri.fsPath");
if (Array.isArray(config.args)) {
config.args = this.concatArgs(config.args);
}
if (Array.isArray(config.vmArgs)) {
config.vmArgs = this.concatArgs(config.vmArgs);
}
if (progressReporter.isCancelled()) {
return undefined;
}
// Populate the class filters to the debug configuration.
await populateStepFilters(config);
const targetJavaVersion: number = await getJavaVersion(config.javaExec);
// Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag.
if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) {
config.vmArgs = (config.vmArgs || "") + " --enable-preview";
validateRuntimeCompatibility(targetJavaVersion);
}
// Add more helpful vmArgs.
await addMoreHelpfulVMArgs(config, targetJavaVersion);
if (!config.shortenCommandLine || config.shortenCommandLine === "auto") {
config.shortenCommandLine = await getShortenApproachForCLI(config, targetJavaVersion);
}
// VS Code internal console uses UTF-8 to display output by default.
if (config.console === "internalConsole" && !config.encoding) {
config.encoding = "UTF-8";
}
} else if (config.request === "attach") {
if (config.hostName && config.port && Number.isInteger(Number(config.port))) {
config.port = Number(config.port);
config.processId = undefined;
// Continue if the hostName and port are configured.
} else if (config.processId !== undefined) {
// tslint:disable-next-line
if (config.processId === "${command:PickJavaProcess}") {
return undefined;
}
const pid: number = Number(config.processId);
if (Number.isNaN(pid)) {
vscode.window.showErrorMessage(`The processId config '${config.processId}' is not a valid process id.`);
return undefined;
}
const javaProcess = await resolveJavaProcess(pid);
if (!javaProcess) {
vscode.window.showErrorMessage(`Attach to process: pid '${config.processId}' is not a debuggable Java process. `
+ `Please make sure the process has turned on debug mode using vmArgs like `
+ `'-agentlib:jdwp=transport=dt_socket,server=y,address=5005.'`);
return undefined;
}
config.processId = undefined;
config.hostName = javaProcess.hostName;
config.port = javaProcess.debugPort;
} else {
throw new utility.UserError({
message: "Please specify the hostName/port directly, or provide the processId of the remote debuggee in the launch.json.",
type: Type.USAGEERROR,
anchor: anchor.ATTACH_CONFIG_ERROR,
});
}
// Populate the class filters to the debug configuration.
await populateStepFilters(config);
} else {
throw new utility.UserError({
message: `Request type "${config.request}" is not supported. Only "launch" and "attach" are supported.`,
type: Type.USAGEERROR,
anchor: anchor.REQUEST_TYPE_NOT_SUPPORTED,
});
}
if (token?.isCancellationRequested || progressReporter.isCancelled()) {
return undefined;
}
delete config.__progressId;
return config;
} catch (ex) {
if (ex instanceof utility.JavaExtensionNotEnabledError) {
utility.guideToInstallJavaExtension();
return undefined;
}
if (ex instanceof utility.UserError) {
utility.showErrorMessageWithTroubleshooting(ex.context);
return undefined;
}
utility.showErrorMessageWithTroubleshooting(utility.convertErrorToMessage(ex));
return undefined;
} finally {
progressReporter.done();
}
}