Skip to content

Commit 5fc394d

Browse files
Only search main class from sources and the specified project or paths (#1113)
* Only search main class from sources and the specified project or paths
1 parent ff7e35c commit 5fc394d

File tree

2 files changed

+71
-21
lines changed

2 files changed

+71
-21
lines changed

src/configurationProvider.ts

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
432432
exclude = path.join(folder?.uri.fsPath || "", exclude);
433433
}
434434
// use Uri to normalize the fs path
435-
excludes.set(vscode.Uri.file(exclude).fsPath, this.isFile(exclude));
435+
excludes.set(vscode.Uri.file(exclude).fsPath, this.isFilePath(exclude));
436436
continue;
437437
}
438438

@@ -496,10 +496,30 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
496496

497497
private async resolveAndValidateMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration,
498498
progressReporter: IProgressReporter): Promise<lsPlugin.IMainClassOption | undefined> {
499-
if (!config.mainClass || this.isFile(config.mainClass)) {
500-
const currentFile = config.mainClass || _.get(vscode.window.activeTextEditor, "document.uri.fsPath");
501-
if (currentFile) {
502-
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile));
499+
// Validate it if the mainClass is already set in launch configuration.
500+
if (config.mainClass && !this.isFilePath(config.mainClass)) {
501+
const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths);
502+
const validationResponse = await lsPlugin.validateLaunchConfig(config.mainClass, config.projectName, containsExternalClasspaths, folder);
503+
if (progressReporter.isCancelled()) {
504+
return undefined;
505+
} else if (!validationResponse.mainClass.isValid || !validationResponse.projectName.isValid) {
506+
return this.fixMainClass(folder, config, validationResponse, progressReporter);
507+
}
508+
509+
return {
510+
mainClass: config.mainClass,
511+
projectName: config.projectName,
512+
};
513+
}
514+
515+
return this.resolveMainClass(config, progressReporter);
516+
}
517+
518+
private async resolveMainClass(config: vscode.DebugConfiguration, progressReporter: IProgressReporter):
519+
Promise<lsPlugin.IMainClassOption | undefined> {
520+
if (config.projectName) {
521+
if (this.isFilePath(config.mainClass)) {
522+
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(config.mainClass));
503523
if (progressReporter.isCancelled()) {
504524
return undefined;
505525
} else if (mainEntries.length) {
@@ -510,27 +530,34 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
510530
}
511531
}
512532

513-
const hintMessage = currentFile ?
514-
`The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` :
515-
"Please select a main class you want to run.";
516-
return this.promptMainClass(folder, progressReporter, hintMessage);
533+
return this.promptMainClassUnderProject(config.projectName, progressReporter, "Please select a main class you wan to run");
517534
}
518535

519-
const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths);
520-
const validationResponse = await lsPlugin.validateLaunchConfig(config.mainClass, config.projectName, containsExternalClasspaths, folder);
521-
if (progressReporter.isCancelled()) {
522-
return undefined;
523-
} else if (!validationResponse.mainClass.isValid || !validationResponse.projectName.isValid) {
524-
return this.fixMainClass(folder, config, validationResponse, progressReporter);
536+
// Try to resolve main class from current file
537+
const currentFile = config.mainClass || vscode.window.activeTextEditor?.document.uri.fsPath;
538+
if (currentFile) {
539+
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile));
540+
if (progressReporter.isCancelled()) {
541+
return undefined;
542+
} else if (mainEntries.length) {
543+
if (!mainClassPicker.isAutoPicked(mainEntries)) {
544+
progressReporter.hide(true);
545+
}
546+
return mainClassPicker.showQuickPick(mainEntries, "Please select a main class you want to run.");
547+
}
525548
}
526549

527-
return {
528-
mainClass: config.mainClass,
529-
projectName: config.projectName,
530-
};
550+
const hintMessage = currentFile ?
551+
`The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` :
552+
"Please select a main class you want to run.";
553+
return this.promptMainClassUnderPath(undefined, progressReporter, hintMessage);
531554
}
532555

533-
private isFile(filePath: string): boolean {
556+
private isFilePath(filePath: string): boolean {
557+
if (!filePath) {
558+
return false;
559+
}
560+
534561
try {
535562
return fs.lstatSync(filePath).isFile();
536563
} catch (error) {
@@ -631,7 +658,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
631658
}
632659
}
633660

634-
private async promptMainClass(folder: vscode.Uri | undefined, progressReporter: IProgressReporter, hintMessage?: string):
661+
private async promptMainClassUnderPath(folder: vscode.Uri | undefined, progressReporter: IProgressReporter, hintMessage?: string):
635662
Promise<lsPlugin.IMainClassOption | undefined> {
636663
const res = await lsPlugin.resolveMainClass(folder);
637664
if (progressReporter.isCancelled()) {
@@ -650,6 +677,25 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
650677
}
651678
return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class<project name>");
652679
}
680+
681+
private async promptMainClassUnderProject(projectName: string, progressReporter: IProgressReporter, hintMessage?: string):
682+
Promise<lsPlugin.IMainClassOption | undefined> {
683+
const res = await lsPlugin.resolveMainClassFromProject(projectName);
684+
if (progressReporter.isCancelled()) {
685+
return undefined;
686+
} else if (res.length === 0) {
687+
throw new utility.UserError({
688+
message: `Cannot find a class with the main method in the project '${projectName}'.`,
689+
type: Type.USAGEERROR,
690+
anchor: anchor.CANNOT_FIND_MAIN_CLASS,
691+
});
692+
}
693+
694+
if (!mainClassPicker.isAutoPicked(res)) {
695+
progressReporter.hide(true);
696+
}
697+
return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class<project name>");
698+
}
653699
}
654700

655701
async function updateDebugSettings(event?: vscode.ConfigurationChangeEvent) {

src/languageServerPlugin.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ export function resolveMainClass(workspaceUri?: vscode.Uri): Promise<IMainClassO
6262
return <Promise<IMainClassOption[]>>commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS);
6363
}
6464

65+
export function resolveMainClassFromProject(projectName: string): Promise<IMainClassOption[]> {
66+
return <Promise<IMainClassOption[]>>commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS, projectName);
67+
}
68+
6569
export function validateLaunchConfig(mainClass: string, projectName: string, containsExternalClasspaths: boolean, workspaceUri?: vscode.Uri):
6670
Promise<ILaunchValidationResponse> {
6771
return <Promise<ILaunchValidationResponse>>commands.executeJavaLanguageServerCommand(commands.JAVA_VALIDATE_LAUNCHCONFIG,

0 commit comments

Comments
 (0)