8000 Only search main class from sources and the specified project or paths by testforstephen · Pull Request #1113 · microsoft/vscode-java-debug · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 67 additions & 21 deletions src/configurationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
exclude = path.join(folder?.uri.fsPath || "", exclude);
}
// 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;
}

Expand Down Expand Up @@ -496,10 +496,30 @@ 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");
if (currentFile) {
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile));
// Validate it if the mainClass is already set in launch configuration.
if (config.mainClass && !this.isFilePath(config.mainClass)) {
const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths);
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()) {
return undefined;
} else if (mainEntries.length) {
Expand All @@ -510,27 +530,34 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
}
}

const hintMessage = currentFile ?
`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);
return this.promptMainClassUnderProject(config.projectName, progressReporter, "Please select a main class you wan to run");
}

const containsExternalClasspaths = !_.isEmpty(config.classPaths) || !_.isEmpty(config.modulePaths);
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);
// Try to resolve main class from current file
const currentFile = config.mainClass || vscode.window.activeTextEditor?.document.uri.fsPath;
if (currentFile) {
const mainEntries = await lsPlugin.resolveMainMethod(vscode.Uri.file(currentFile));
if (progressReporter.isCancelled()) {
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 {
mainClass: config.mainClass,
projectName: config.projectName,
};
const hintMessage = currentFile ?
`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.promptMainClassUnderPath(undefined, progressReporter, hintMessage);
}

private isFile(filePath: string): boolean {
private isFilePath(filePath: string): boolean {
if (!filePath) {
return false;
}

try {
return fs.lstatSync(filePath).isFile();
} catch (error) {
Expand Down Expand Up @@ -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> {
const res = await lsPlugin.resolveMainClass(folder);
if (progressReporter.isCancelled()) {
Expand All @@ -650,6 +677,25 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
}
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) {
Expand Down
4 changes: 4 additions & 0 deletions src/languageServerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export function resolveMainClass(workspaceUri?: vscode.Uri): Promise<IMainClassO
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):
Promise<ILaunchValidationResponse> {
return <Promise<ILaunchValidationResponse>>commands.executeJavaLanguageServerCommand(commands.JAVA_VALIDATE_LAUNCHCONFIG,
Expand Down
0