Skip to content

Commit 93cbc19

Browse files
if current file is not a main class, 'Run Java' will run previously used app (#1301)
* if current file is not a main class, 'Run Java' will run previously used app * Show the config name in launch.json as job name if it exists
1 parent c0ed20c commit 93cbc19

File tree

3 files changed

+107
-40
lines changed

3 files changed

+107
-40
lines changed

src/configurationProvider.ts

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const platformNameMappings: { [key: string]: string } = {
3030
};
3131
const platformName = platformNameMappings[process.platform];
3232

33+
export let lastUsedLaunchConfig: vscode.DebugConfiguration | undefined;
34+
3335
export class JavaDebugConfigurationProvider implements vscode.DebugConfigurationProvider {
3436
private isUserSettingsDirty: boolean = true;
3537
constructor() {
@@ -75,6 +77,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
7577
config.type = "java";
7678
config.name = "Java Debug";
7779
config.request = "launch";
80+
config.__origin = "internal";
7881
}
7982

8083
return config;
@@ -200,6 +203,15 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
200203

201204
private async resolveAndValidateDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, config: vscode.DebugConfiguration,
202205
token?: vscode.CancellationToken) {
206+
let configCopy: vscode.DebugConfiguration | undefined;
207+
const isConfigFromInternal = config.__origin === "internal" /** in-memory configuration from debugger */
208+
|| config.__configurationTarget /** configuration from launch.json */;
209+
if (config.request === "launch" && isConfigFromInternal) {
210+
configCopy = _.cloneDeep(config);
211+
delete configCopy.__progressId;
212+
delete configCopy.noDebug;
213+
}
214+
203215
let progressReporter = progressProvider.getProgressReporter(config.__progressId);
204216
if (!progressReporter && config.__progressId) {
205217
return undefined;
@@ -231,35 +243,26 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
231243
}
232244

233245
if (config.request === "launch") {
234-
this.mergeEnvFile(config);
235-
236-
// If the user doesn't specify 'vmArgs' in launch.json, use the global setting to get the default vmArgs.
237-
if (config.vmArgs === undefined) {
238-
const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings");
239-
config.vmArgs = debugSettings.vmArgs;
246+
const mainClassOption = await this.resolveAndValidateMainClass(folder && folder.uri, config, progressReporter);
247+
if (!mainClassOption || !mainClassOption.mainClass) { // Exit silently if the user cancels the prompt fix by ESC.
248+
// Exit the debug session.
249+
return undefined;
240250
}
241-
// If the user doesn't specify 'console' in launch.json, use the global setting to get the launch console.
242-
if (!config.console) {
243-
const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings");
244-
config.console = debugSettings.console;
251+
252+
config.mainClass = mainClassOption.mainClass;
253+
config.projectName = mainClassOption.projectName;
254+
if (config.__workspaceFolder && config.__workspaceFolder !== folder) {
255+
folder = config.__workspaceFolder;
245256
}
246-
// If the console is integratedTerminal, don't auto switch the focus to DEBUG CONSOLE.
247-
if (config.console === "integratedTerminal" && !config.internalConsoleOptions) {
248-
config.internalConsoleOptions = "neverOpen";
257+
// Update the job name if the main class is changed during the resolving of configuration provider.
258+
if (configCopy && configCopy.mainClass !== config.mainClass) {
259+
config.name = config.mainClass.substr(config.mainClass.lastIndexOf(".") + 1);
260+
progressReporter.setJobName(utility.launchJobName(config.name, config.noDebug));
249261
}
250-
251-
252262
if (progressReporter.isCancelled()) {
253263
return undefined;
254264
}
255265

256-
progressReporter.report("Resolving main class...");
257-
const mainClassOption = await this.resolveAndValidateMainClass(folder && folder.uri, config, progressReporter);
258-
if (!mainClassOption || !mainClassOption.mainClass) { // Exit silently if the user cancels the prompt fix by ESC.
259-
// Exit the debug session.
260-
return undefined;
261-
}
262-
263266
if (needsBuildWorkspace()) {
264267
progressReporter.report("Compiling...");
265268
const proceed = await buildWorkspace({
@@ -272,9 +275,26 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
272275
}
273276
}
274277

278+
if (progressReporter.isCancelled()) {
279+
return undefined;
280+
}
281+
275282
progressReporter.report("Resolving launch configuration...");
276-
config.mainClass = mainClassOption.mainClass;
277-
config.projectName = mainClassOption.projectName;
283+
this.mergeEnvFile(config);
284+
// If the user doesn't specify 'vmArgs' in launch.json, use the global setting to get the default vmArgs.
285+
if (config.vmArgs === undefined) {
286+
const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings");
287+
config.vmArgs = debugSettings.vmArgs;
288+
}
289+
// If the user doesn't specify 'console' in launch.json, use the global setting to get the launch console.
290+
if (!config.console) {
291+
const debugSettings: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("java.debug.settings");
292+
config.console = debugSettings.console;
293+
}
294+
// If the console is integratedTerminal, don't auto switch the focus to DEBUG CONSOLE.
295+
if (config.console === "integratedTerminal" && !config.internalConsoleOptions) {
296+
config.internalConsoleOptions = "neverOpen";
297+
}
278298

279299
if (progressReporter.isCancelled()) {
280300
return undefined;
@@ -407,6 +427,14 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
407427
utility.showErrorMessageWithTroubleshooting(utility.convertErrorToMessage(ex));
408428
return undefined;
409429
} finally {
430+
if (configCopy && config.mainClass) {
431+
configCopy.name = config.name;
432+
configCopy.mainClass = config.mainClass;
433+
configCopy.projectName = config.projectName;
434+
configCopy.__workspaceFolder = folder;
435+
lastUsedLaunchConfig = configCopy;
436+
}
437+
410438
progressReporter.done();
411439
}
412440
}
@@ -521,6 +549,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
521549
progressReporter: IProgressReporter): Promise<lsPlugin.IMainClassOption | undefined> {
522550
// Validate it if the mainClass is already set in launch configuration.
523551
if (config.mainClass && !this.isFilePath(config.mainClass)) {
552+
progressReporter.report("Resolving main class...");
524553
const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths);
525554
const validationResponse = await lsPlugin.validateLaunchConfig(config.mainClass, config.projectName, containsExternalClasspaths, folder);
526555
if (progressReporter.isCancelled()) {
@@ -541,6 +570,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
541570
private async resolveMainClass(config: vscode.DebugConfiguration, progressReporter: IProgressReporter):
542571
Promise<lsPlugin.IMainClassOption | undefined> {
543572
if (config.projectName) {
573+
progressReporter.report("Resolving main class...");
544574
if (this.isFilePath(config.mainClass)) {
545575
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(config.mainClass));
546576
if (progressReporter.isCancelled()) {
@@ -570,6 +600,18 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
570600
}
571601
}
572602

603+
// If current file is not executable, run previously used launch config.
604+
if (lastUsedLaunchConfig) {
605+
Object.assign(config, lastUsedLaunchConfig);
606+
progressReporter.setJobName(utility.launchJobName(config.name, config.noDebug));
607+
progressReporter.report("Resolving main class...");
608+
return {
609+
mainClass: config.mainClass,
610+
projectName: config.projectName,
611+
};
612+
}
613+
614+
progressReporter.report("Resolving main class...");
573615
const hintMessage = currentFile ?
574616
`The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` :
575617
"Please select a main class you want to run.";

src/debugCodeLensProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export async function startDebugging(mainClass: string, projectName: string, uri
200200
debugConfig.projectName = projectName;
201201
debugConfig.noDebug = noDebug;
202202
debugConfig.__progressId = progressReporter?.getId();
203+
debugConfig.__origin = "internal";
203204

204205
return vscode.debug.startDebugging(workspaceFolder, debugConfig);
205206
}

src/extension.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import * as vscode from "vscode";
88
import { dispose as disposeTelemetryWrapper, initializeFromJsonFile, instrumentOperation,
99
instrumentOperationAsVsCodeCommand, setUserError } from "vscode-extension-telemetry-wrapper";
1010
import * as commands from "./commands";
11-
import { JavaDebugConfigurationProvider } from "./configurationProvider";
11+
import { JavaDebugConfigurationProvider, lastUsedLaunchConfig } from "./configurationProvider";
1212
import { HCR_EVENT, JAVA_LANGID, USER_NOTIFICATION_EVENT } from "./constants";
1313
import { NotificationBar } from "./customWidget";
1414
import { initializeCodeLensProvider, startDebugging } from "./debugCodeLensProvider";
@@ -251,14 +251,23 @@ async function runJavaFile(uri: vscode.Uri, noDebug: boolean) {
251251
const defaultPlaceHolder: string = "Select the main class to run";
252252

253253
if (!hasMainMethods && !canRunTests) {
254-
progressReporter.report("Resolving main class...");
255-
const mainClasses: IMainClassOption[] = await utility.searchMainMethods();
256-
if (progressReporter.isCancelled()) {
257-
throw new utility.OperationCancelledError("");
254+
// If current file is not a main class, "Run Java" will run previously used launch config.
255+
if (lastUsedLaunchConfig) {
256+
progressReporter.setJobName(utility.launchJobName(lastUsedLaunchConfig.name, noDebug));
257+
progressReporter.report("Resolving launch configuration...");
258+
lastUsedLaunchConfig.noDebug = noDebug;
259+
lastUsedLaunchConfig.__progressId = progressReporter.getId();
260+
vscode.debug.startDebugging(lastUsedLaunchConfig.__workspaceFolder, lastUsedLaunchConfig);
261+
} else {
262+
progressReporter.report("Resolving main class...");
263+
const mainClasses: IMainClassOption[] = await utility.searchMainMethods();
264+
if (progressReporter.isCancelled()) {
265+
throw new utility.OperationCancelledError("");
266+
}
267+
268+
const placeHolder: string = `The file '${path.basename(uri.fsPath)}' is not executable, please select a main class you want to run.`;
269+
await launchMain(mainClasses, uri, noDebug, progressReporter, placeHolder, false /*autoPick*/);
258270
}
259-
260-
const placeHolder: string = `The file '${path.basename(uri.fsPath)}' is not executable, please select a main class you want to run.`;
261-
await launchMain(mainClasses, uri, noDebug, progressReporter, placeHolder, false /*autoPick*/);
262271
} else if (hasMainMethods && !canRunTests) {
263272
await launchMain(mainMethods, uri, noDebug, progressReporter, defaultPlaceHolder);
264273
} else if (!hasMainMethods && canRunTests) {
@@ -330,7 +339,13 @@ async function launchMain(mainMethods: IMainClassOption[], uri: vscode.Uri, noDe
330339
throw new utility.OperationCancelledError("");
331340
}
332341

333-
progressReporter.setJobName(utility.launchJobNameByMainClass(pick.mainClass, noDebug));
342+
const existConfig: vscode.DebugConfiguration | undefined = findLaunchConfiguration(
343+
pick.mainClass, pick.projectName, uri.fsPath);
344+
if (existConfig) {
345+
progressReporter.setJobName(utility.launchJobName(existConfig.name, noDebug));
346+
} else {
347+
progressReporter.setJobName(utility.launchJobNameByMainClass(pick.mainClass, noDebug));
348+
}
334349
progressReporter.report("Launching main class...");
335350
startDebugging(pick.mainClass, pick.projectName || "", uri, noDebug, progressReporter);
336351
}
@@ -367,18 +382,12 @@ async function runJavaProject(node: any, noDebug: boolean) {
367382
throw new utility.OperationCancelledError("");
368383
}
369384

370-
progressReporter.setJobName(utility.launchJobNameByMainClass(pick.mainClass, noDebug));
371-
progressReporter.report("Launching main class...");
372385
const projectName: string | undefined = pick.projectName;
373386
const mainClass: string = pick.mainClass;
374387
const filePath: string | undefined = pick.filePath;
375388
const workspaceFolder: vscode.WorkspaceFolder | undefined =
376389
filePath ? vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath)) : undefined;
377-
const launchConfigurations: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("launch", workspaceFolder);
378-
const existingConfigs: vscode.DebugConfiguration[] = launchConfigurations.configurations;
379-
const existConfig: vscode.DebugConfiguration | undefined = _.find(existingConfigs, (config) => {
380-
return config.mainClass === mainClass && _.toString(config.projectName) === _.toString(projectName);
381-
});
390+
const existConfig: vscode.DebugConfiguration | undefined = findLaunchConfiguration(mainClass, projectName, filePath);
382391
const debugConfig = existConfig || {
383392
type: "java",
384393
name: `${mainClass.substr(mainClass.lastIndexOf(".") + 1)}`,
@@ -388,6 +397,9 @@ async function runJavaProject(node: any, noDebug: boolean) {
388397
};
389398
debugConfig.noDebug = noDebug;
390399
debugConfig.__progressId = progressReporter.getId();
400+
debugConfig.__origin = "internal";
401+
progressReporter.setJobName(utility.launchJobName(debugConfig.name, noDebug));
402+
progressReporter.report("Launching main class...");
391403
vscode.debug.startDebugging(workspaceFolder, debugConfig);
392404
} catch (ex) {
393405
progressReporter.done();
@@ -398,3 +410,15 @@ async function runJavaProject(node: any, noDebug: boolean) {
398410
throw ex;
399411
}
400412
}
413+
414+
function findLaunchConfiguration(mainClass: string, projectName: string | undefined, filePath?: string): vscode.DebugConfiguration | undefined {
415+
const workspaceFolder: vscode.WorkspaceFolder | undefined =
416+
filePath ? vscode.workspace.getWorkspaceFolder(vscode.Uri.file(filePath)) : undefined;
417+
const launchConfigurations: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("launch", workspaceFolder);
418+
const existingConfigs: vscode.DebugConfiguration[] = launchConfigurations.configurations;
419+
const existConfig: vscode.DebugConfiguration | undefined = _.find(existingConfigs, (config) => {
420+
return config.mainClass === mainClass && _.toString(config.projectName) === _.toString(projectName);
421+
});
422+
423+
return existConfig;
424+
}

0 commit comments

Comments
 (0)