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
This commit is contained in:
Jinbo Wang 2022-01-24 10:27:23 +08:00 committed by GitHub
parent ff7e35cb4f
commit 5fc394dfa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 21 deletions

View File

@ -432,7 +432,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
exclude = path.join(folder?.uri.fsPath || "", exclude); exclude = path.join(folder?.uri.fsPath || "", exclude);
} }
// use Uri to normalize the fs path // use Uri to normalize the fs path
excludes.set(vscode.Uri.file(exclude).fsPath, this.isFile(exclude)); excludes.set(vscode.Uri.file(exclude).fsPath, this.isFilePath(exclude));
continue; continue;
} }
@ -496,10 +496,30 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
private async resolveAndValidateMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration, private async resolveAndValidateMainClass(folder: vscode.Uri | undefined, config: vscode.DebugConfiguration,
progressReporter: IProgressReporter): Promise<lsPlugin.IMainClassOption | undefined> { progressReporter: IProgressReporter): Promise<lsPlugin.IMainClassOption | undefined> {
if (!config.mainClass || this.isFile(config.mainClass)) { // Validate it if the mainClass is already set in launch configuration.
const currentFile = config.mainClass || _.get(vscode.window.activeTextEditor, "document.uri.fsPath"); if (config.mainClass && !this.isFilePath(config.mainClass)) {
if (currentFile) { const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths);
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile)); const validationResponse = await lsPlugin.validateLaunchConfig(config.mainClass, config.projectName, containsExternalClasspaths, folder);
if (progressReporter.isCancelled()) {
return undefined;
} else if (!validationResponse.mainClass.isValid || !validationResponse.projectName.isValid) {
return this.fixMainClass(folder, config, validationResponse, progressReporter);
}
return {
mainClass: config.mainClass,
projectName: config.projectName,
};
}
return this.resolveMainClass(config, progressReporter);
}
private async resolveMainClass(config: vscode.DebugConfiguration, progressReporter: IProgressReporter):
Promise<lsPlugin.IMainClassOption | undefined> {
if (config.projectName) {
if (this.isFilePath(config.mainClass)) {
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(config.mainClass));
if (progressReporter.isCancelled()) { if (progressReporter.isCancelled()) {
return undefined; return undefined;
} else if (mainEntries.length) { } else if (mainEntries.length) {
@ -510,27 +530,34 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
} }
} }
const hintMessage = currentFile ? return this.promptMainClassUnderProject(config.projectName, progressReporter, "Please select a main class you wan to run");
`The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` :
"Please select a main class you want to run.";
return this.promptMainClass(folder, progressReporter, hintMessage);
} }
const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths); // Try to resolve main class from current file
const validationResponse = await lsPlugin.validateLaunchConfig(config.mainClass, config.projectName, containsExternalClasspaths, folder); const currentFile = config.mainClass || vscode.window.activeTextEditor?.document.uri.fsPath;
if (progressReporter.isCancelled()) { if (currentFile) {
return undefined; const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile));
} else if (!validationResponse.mainClass.isValid || !validationResponse.projectName.isValid) { if (progressReporter.isCancelled()) {
return this.fixMainClass(folder, config, validationResponse, progressReporter); return undefined;
} else if (mainEntries.length) {
if (!mainClassPicker.isAutoPicked(mainEntries)) {
progressReporter.hide(true);
}
return mainClassPicker.showQuickPick(mainEntries, "Please select a main class you want to run.");
}
} }
return { const hintMessage = currentFile ?
mainClass: config.mainClass, `The file '${path.basename(currentFile)}' is not executable, please select a main class you want to run.` :
projectName: config.projectName, "Please select a main class you want to run.";
}; return this.promptMainClassUnderPath(undefined, progressReporter, hintMessage);
} }
private isFile(filePath: string): boolean { private isFilePath(filePath: string): boolean {
if (!filePath) {
return false;
}
try { try {
return fs.lstatSync(filePath).isFile(); return fs.lstatSync(filePath).isFile();
} catch (error) { } catch (error) {
@ -631,7 +658,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
} }
} }
private async promptMainClass(folder: vscode.Uri | undefined, progressReporter: IProgressReporter, hintMessage?: string): private async promptMainClassUnderPath(folder: vscode.Uri | undefined, progressReporter: IProgressReporter, hintMessage?: string):
Promise<lsPlugin.IMainClassOption | undefined> { Promise<lsPlugin.IMainClassOption | undefined> {
const res = await lsPlugin.resolveMainClass(folder); const res = await lsPlugin.resolveMainClass(folder);
if (progressReporter.isCancelled()) { if (progressReporter.isCancelled()) {
@ -650,6 +677,25 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
} }
return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class<project name>"); return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class<project name>");
} }
private async promptMainClassUnderProject(projectName: string, progressReporter: IProgressReporter, hintMessage?: string):
Promise<lsPlugin.IMainClassOption | undefined> {
const res = await lsPlugin.resolveMainClassFromProject(projectName);
if (progressReporter.isCancelled()) {
return undefined;
} else if (res.length === 0) {
throw new utility.UserError({
message: `Cannot find a class with the main method in the project '${projectName}'.`,
type: Type.USAGEERROR,
anchor: anchor.CANNOT_FIND_MAIN_CLASS,
});
}
if (!mainClassPicker.isAutoPicked(res)) {
progressReporter.hide(true);
}
return mainClassPicker.showQuickPickWithRecentlyUsed(res, hintMessage || "Select main class<project name>");
}
} }
async function updateDebugSettings(event?: vscode.ConfigurationChangeEvent) { async function updateDebugSettings(event?: vscode.ConfigurationChangeEvent) {

View File

@ -62,6 +62,10 @@ export function resolveMainClass(workspaceUri?: vscode.Uri): Promise<IMainClassO
return <Promise<IMainClassOption[]>>commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS); return <Promise<IMainClassOption[]>>commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS);
} }
export function resolveMainClassFromProject(projectName: string): Promise<IMainClassOption[]> {
return <Promise<IMainClassOption[]>>commands.executeJavaLanguageServerCommand(commands.JAVA_RESOLVE_MAINCLASS, projectName);
}
export function validateLaunchConfig(mainClass: string, projectName: string, containsExternalClasspaths: boolean, workspaceUri?: vscode.Uri): export function validateLaunchConfig(mainClass: string, projectName: string, containsExternalClasspaths: boolean, workspaceUri?: vscode.Uri):
Promise<ILaunchValidationResponse> { Promise<ILaunchValidationResponse> {
return <Promise<ILaunchValidationResponse>>commands.executeJavaLanguageServerCommand(commands.JAVA_VALIDATE_LAUNCHCONFIG, return <Promise<ILaunchValidationResponse>>commands.executeJavaLanguageServerCommand(commands.JAVA_VALIDATE_LAUNCHCONFIG,