diff --git a/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/ResolveMainClassHandler.java b/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/ResolveMainClassHandler.java index a554a6e67..f70d0c044 100644 --- a/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/ResolveMainClassHandler.java +++ b/com.microsoft.java.debug.plugin/src/main/java/com/microsoft/java/debug/plugin/internal/ResolveMainClassHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017-2021 Microsoft Corporation and others. + * Copyright (c) 2017-2022 Microsoft Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,6 +12,7 @@ package com.microsoft.java.debug.plugin.internal; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -21,6 +22,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.SourceVersion; @@ -79,15 +81,26 @@ public Object validateLaunchConfig(List arguments) throws Exception { } private List resolveMainClassCore(List arguments) { - IPath rootPath = null; if (arguments != null && arguments.size() > 0 && arguments.get(0) != null) { - rootPath = ResourceUtils.filePathFromURI((String) arguments.get(0)); - } - final ArrayList targetProjectPath = new ArrayList<>(); - if (rootPath != null) { - targetProjectPath.add(rootPath); + String argument = (String) arguments.get(0); + IProject[] projects = ProjectUtils.getAllProjects(); + if (Stream.of(projects).anyMatch(project -> Objects.equals(project.getName(), argument))) { + return resolveMainClassUnderProject(argument); + } + + IPath rootPath = ResourceUtils.filePathFromURI(argument); + if (rootPath != null) { + return resolveMainClassUnderPaths(Arrays.asList(rootPath)); + } } - IJavaSearchScope searchScope = SearchEngine.createWorkspaceScope(); + + return resolveMainClassUnderPaths(Collections.emptyList()); + } + + private List resolveMainClassUnderPaths(List parentPaths) { + // Limit to search main method from source code only. + IJavaSearchScope searchScope = SearchEngine.createJavaSearchScope(ProjectUtils.getJavaProjects(), + IJavaSearchScope.REFERENCED_PROJECTS | IJavaSearchScope.SOURCES); SearchPattern pattern = SearchPattern.createPattern("main(String[]) void", IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CASE_SENSITIVE | SearchPattern.R_EXACT_MATCH); final List res = new ArrayList<>(); @@ -112,10 +125,9 @@ public void acceptSearchMatch(SearchMatch match) { } } String projectName = ProjectsManager.DEFAULT_PROJECT_NAME.equals(project.getName()) ? null : project.getName(); - if (projectName == null - || targetProjectPath.isEmpty() - || ResourceUtils.isContainedIn(project.getLocation(), targetProjectPath) - || isContainedInInvisibleProject(project, targetProjectPath)) { + if (parentPaths.isEmpty() + || ResourceUtils.isContainedIn(project.getLocation(), parentPaths) + || isContainedInInvisibleProject(project, parentPaths)) { String filePath = null; if (match.getResource() instanceof IFile) { @@ -149,6 +161,66 @@ public void acceptSearchMatch(SearchMatch match) { return resolutions; } + private List resolveMainClassUnderProject(final String projectName) { + // Limit to search main method from source code only. + IJavaProject javaProject = ProjectUtils.getJavaProject(projectName); + IJavaSearchScope searchScope = SearchEngine.createJavaSearchScope(javaProject == null ? new IJavaProject[0] : new IJavaProject[] {javaProject}, + IJavaSearchScope.REFERENCED_PROJECTS | IJavaSearchScope.SOURCES); + SearchPattern pattern = SearchPattern.createPattern("main(String[]) void", IJavaSearchConstants.METHOD, + IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CASE_SENSITIVE | SearchPattern.R_EXACT_MATCH); + final List res = new ArrayList<>(); + SearchRequestor requestor = new SearchRequestor() { + @Override + public void acceptSearchMatch(SearchMatch match) { + Object element = match.getElement(); + if (element instanceof IMethod) { + IMethod method = (IMethod) element; + try { + if (method.isMainMethod()) { + IResource resource = method.getResource(); + if (resource != null) { + IProject project = resource.getProject(); + if (project != null) { + String mainClass = method.getDeclaringType().getFullyQualifiedName(); + IJavaProject javaProject = JdtUtils.getJavaProject(project); + if (javaProject != null) { + String moduleName = JdtUtils.getModuleName(javaProject); + if (moduleName != null) { + mainClass = moduleName + "/" + mainClass; + } + } + + String filePath = null; + if (match.getResource() instanceof IFile) { + try { + filePath = match.getResource().getLocation().toOSString(); + } catch (Exception ex) { + // ignore + } + } + res.add(new ResolutionItem(mainClass, projectName, filePath)); + } + } + } + } catch (JavaModelException e) { + // ignore + } + } + } + }; + SearchEngine searchEngine = new SearchEngine(); + try { + searchEngine.search(pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, + searchScope, requestor, null /* progress monitor */); + } catch (Exception e) { + logger.log(Level.SEVERE, String.format("Searching the main class failure: %s", e.toString()), e); + } + + List resolutions = res.stream().distinct().collect(Collectors.toList()); + Collections.sort(resolutions); + return resolutions; + } + private boolean isContainedInInvisibleProject(IProject project, Collection rootPaths) { if (project == null) { return false;