Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when there is only one project matching the mainclass, projectName is not required for evaluation. #156

Merged
merged 5 commits into from
Mar 14, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
package com.microsoft.java.debug.core.adapter;

public final class Constants {
public static final String PROJECTNAME = "projectName";
public static final String PROJECT_NAME = "projectName";
public static final String DEBUGGEE_ENCODING = "debuggeeEncoding";
public static final String MAIN_CLASS = "mainClass";
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
Map<String, Object> options = new HashMap<>();
options.put(Constants.DEBUGGEE_ENCODING, context.getDebuggeeEncoding());
if (attachArguments.projectName != null) {
options.put(Constants.PROJECTNAME, attachArguments.projectName);
options.put(Constants.PROJECT_NAME, attachArguments.projectName);
}
ISourceLookUpProvider sourceProvider = context.getProvider(ISourceLookUpProvider.class);
sourceProvider.initialize(context, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,16 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,

return launch(launchArguments, response, context).thenCompose(res -> {
if (res.success) {
ISourceLookUpProvider sourceProvider = context.getProvider(ISourceLookUpProvider.class);

Map<String, Object> options = new HashMap<>();
options.put(Constants.DEBUGGEE_ENCODING, context.getDebuggeeEncoding());
if (launchArguments.projectName != null) {
options.put(Constants.PROJECTNAME, launchArguments.projectName);
options.put(Constants.PROJECT_NAME, launchArguments.projectName);
}
if (launchArguments.mainClass != null) {
options.put(Constants.MAIN_CLASS, launchArguments.mainClass);
}
ISourceLookUpProvider sourceProvider = context.getProvider(ISourceLookUpProvider.class);
sourceProvider.initialize(context, options);
IEvaluationProvider evaluationProvider = context.getProvider(IEvaluationProvider.class);
evaluationProvider.initialize(context, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public String getSourceFileURI(String fullyQualifiedName, String sourcePath) {

private synchronized ISourceContainer[] getSourceContainers() {
if (sourceContainers == null) {
sourceContainers = JdtUtils.getSourceContainers((String) options.get(Constants.PROJECTNAME));
sourceContainers = JdtUtils.getSourceContainers((String) options.get(Constants.PROJECT_NAME));
}

return sourceContainers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,20 @@

package com.microsoft.java.debug.plugin.internal.eval;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
Expand All @@ -29,6 +36,7 @@
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.eval.ICompiledExpression;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
Expand All @@ -43,6 +51,7 @@
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
import com.microsoft.java.debug.core.adapter.IEvaluationProvider;
import com.microsoft.java.debug.plugin.internal.JdtUtils;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
Expand All @@ -56,6 +65,10 @@ public class JdtEvaluationProvider implements IEvaluationProvider {
private HashMap<String, Object> options = new HashMap<>();
private IDebugAdapterContext context;

private List<IJavaProject> possibleProjects;

private Set<String> visitedClassNames = new HashSet<>();

public JdtEvaluationProvider() {
}

Expand All @@ -80,7 +93,7 @@ public CompletableFuture<Value> evaluateForBreakpoint(IBreakpoint breakpoint, Th

CompletableFuture<Value> completableFuture = new CompletableFuture<>();
try {
ensureDebugTarget(thread.virtualMachine());
ensureDebugTarget(thread.virtualMachine(), thread, 0);
JDIThread jdiThread = getMockJDIThread(thread);
JDIStackFrame stackframe = (JDIStackFrame) jdiThread.getTopStackFrame();

Expand All @@ -101,7 +114,7 @@ public CompletableFuture<Value> evaluateForBreakpoint(IBreakpoint breakpoint, Th
public CompletableFuture<Value> evaluate(String expression, ThreadReference thread, int depth) {
CompletableFuture<Value> completableFuture = new CompletableFuture<>();
try {
ensureDebugTarget(thread.virtualMachine());
ensureDebugTarget(thread.virtualMachine(), thread, depth);
JDIThread jdiThread = getMockJDIThread(thread);
JDIStackFrame stackframe = createStackFrame(jdiThread, depth);
if (stackframe == null) {
Expand All @@ -119,6 +132,91 @@ public CompletableFuture<Value> evaluate(String expression, ThreadReference thre
}
}

/**
* Prepare a list of possible java projects in workspace which contains the main class.
*
* @param mainclass the main class specified by launch.json for finding possible projects
*/
private void initializePossibleProjects(String mainclass) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initializeProjectCandidates

IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
List<IJavaProject> projects = Arrays.stream(root.getProjects()).map(JdtUtils::getJavaProject).filter(p -> {
try {
return p != null && p.hasBuildState();
} catch (Exception e) {
// ignore
}
return false;
}).collect(Collectors.toList());


if (projects.size() > 1 && StringUtils.isNotBlank(mainclass)) {
projects = Arrays.stream(root.getProjects()).map(JdtUtils::getJavaProject).filter(p -> {
try {
return p.findType(mainclass) != null;
} catch (JavaModelException e) {
// ignore
}
return false;
}).collect(Collectors.toList());
visitedClassNames.add(mainclass);
}

if (projects.size() == 1) {
project = projects.get(0);
}

possibleProjects = projects;
}

private void findJavaProjectByStackFrame(ThreadReference thread, int depth) {
if (possibleProjects == null) {
// initial possible projects by main class (projects contains this main class)
initializePossibleProjects((String) options.get(Constants.MAIN_CLASS));
if (project != null) {
return;
}
}

if (possibleProjects.size() == 0) {
logger.severe("No project is available for evaluation.");
throw new IllegalStateException("No project is available for evaluation.");
}

try {
StackFrame sf = thread.frame(depth);
String typeName = sf.location().method().declaringType().name();
// narrow down possible projects by current class
List<IJavaProject> validProjects = visitedClassNames.contains(typeName) ? possibleProjects
: possibleProjects.stream().filter(p -> {
try {
return !visitedClassNames.contains(typeName) && p.findType(typeName) != null;
} catch (Exception e) {
// ignore
}
return false;
}).collect(Collectors.toList());
visitedClassNames.add(typeName);
if (validProjects.size() == 1) {
project = validProjects.get(0);
} else if (validProjects.size() == 0) {
logger.severe("No project is available for evaluation.");
throw new IllegalStateException("No project is available for evaluation, .");
} else {
// narrow down projects
possibleProjects = validProjects;
logger.severe("Multiple projects are valid for evaluation.");
throw new IllegalStateException("Multiple projects are found, please specify projectName in launch.json.");
}

} catch (Exception ex) {
// ignore
}

logger.severe("Cannot evaluate when project is not specified.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Cannot evaluate when the project is not specified

throw new IllegalStateException("Please specify projectName in launch.json.");
}


private JDIStackFrame createStackFrame(JDIThread thread, int depth) {
try {
IStackFrame[] jdiStackFrames = thread.getStackFrames();
Expand Down Expand Up @@ -188,19 +286,19 @@ public void clearState(ThreadReference thread) {
}
}

private void ensureDebugTarget(VirtualMachine vm) {
private void ensureDebugTarget(VirtualMachine vm, ThreadReference thread, int depth) {
if (debugTarget == null) {
String projectName = (String) options.get(Constants.PROJECTNAME);
if (project == null) {
String projectName = (String) options.get(Constants.PROJECT_NAME);
if (StringUtils.isBlank(projectName)) {
logger.severe("Cannot evaluate when project is not specified.");
throw new IllegalStateException("Please specify projectName in launch.json.");
}
IJavaProject javaProject = JdtUtils.getJavaProject(projectName);
if (javaProject == null) {
throw new IllegalStateException(String.format("Project %s cannot be found.", projectName));
findJavaProjectByStackFrame(thread, depth);
} else {
IJavaProject javaProject = JdtUtils.getJavaProject(projectName);
if (javaProject == null) {
throw new IllegalStateException(String.format("Project %s cannot be found.", projectName));
}
project = javaProject;
}
project = javaProject;
}

if (launch == null) {
Expand Down