Skip to content

Commit

Permalink
Fix binary evaluation compilation failures #275
Browse files Browse the repository at this point in the history
The changeset tries to generate missing constructors and add imports
for variable type that are visible in the evaluation __run method.
  • Loading branch information
gayanper committed Jul 9, 2023
1 parent fba705b commit 6260d38
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 10 deletions.
9 changes: 9 additions & 0 deletions org.eclipse.jdt.debug.tests/java8/GH275.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import com.debug.test.Subject;
import com.debug.test.Observation;

public class GH275 {
public static void main(String[] args) {
Subject subject = new Subject("Name 1");
Observation.start(() -> subject, sub -> System.out.println(sub)).observe();
}
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@ synchronized void assert18Project() {
try {
if (!loaded18) {
jp = createProject(ONE_EIGHT_PROJECT_NAME, JavaProjectHelper.TEST_1_8_SRC_DIR.toString(), JavaProjectHelper.JAVA_SE_1_8_EE_NAME, false);
IPath lib = new Path(JavaTestPlugin.getDefault().getFileInPlugin(new Path("testjars").append("gh275").append("debug-lib.jar")).getAbsolutePath());
JavaProjectHelper.addLibrary(jp, lib);

cfgs.add(createLaunchConfiguration(jp, "EvalTest18"));
cfgs.add(createLaunchConfiguration(jp, "FunctionalCaptureTest18"));
cfgs.add(createLaunchConfiguration(jp, "EvalTestIntf18"));
Expand Down Expand Up @@ -500,6 +503,7 @@ synchronized void assert18Project() {
cfgs.add(createLaunchConfiguration(jp, "Bug578145LambdaInAnonymous"));
cfgs.add(createLaunchConfiguration(jp, "Bug578145LambdaOnChainCalls"));
cfgs.add(createLaunchConfiguration(jp, "LambdaBreakpoints1"));
cfgs.add(createLaunchConfiguration(jp, "GH275"));
loaded18 = true;
waitForBuild();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,38 @@ public void testContextEvaluations() throws Exception {
}
}

public void testEvaluate_GH275_StaticBinaryMethod_EvaluateSnippetWithImportedTypes() throws Exception {
IJavaThread javaThread = null;
try {
IJavaLineBreakpoint bp = createLineBreakpoint(getType("com.debug.test.Observation"), 25);
javaThread = launchToLineBreakpoint("GH275", bp);
assertNotNull("The program did not suspend", javaThread);

String snippet = "new Observation((Object) subject, (Consumer) action)";
IValue value = doEval(javaThread, snippet);

assertNotNull("value is null", value);
} finally {
removeAllBreakpoints();
terminateAndRemove(javaThread);
}
}

public void testEvaluate_GH275_InstanceBinaryMethod_EvaluateSnippetWithImportedTypes() throws Exception {
IJavaThread javaThread = null;
try {
IJavaLineBreakpoint bp = createLineBreakpoint(getType("com.debug.test.Observation"), 19);
javaThread = launchToLineBreakpoint("GH275", bp);
assertNotNull("The program did not suspend", javaThread);

String snippet = "((Subject)this.subject).getName()";
IValue value = doEval(javaThread, snippet);

assertNotNull("value is null", value);
assertEquals("Return value doesn't match", "Name 1", value.getValueString());
} finally {
removeAllBreakpoints();
terminateAndRemove(javaThread);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.engine;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.debug.core.IJavaReferenceType;
Expand Down Expand Up @@ -50,6 +53,8 @@ public class BinaryBasedSourceGenerator {

private String fCompilationUnitName;

private Set<String> fImports;

/**
* Level of source code to generate (major, minor). For example 1 and 4
* indicates 1.4.
Expand All @@ -63,6 +68,7 @@ public BinaryBasedSourceGenerator(String[] localTypesNames,
fLocalVariableTypeNames = localTypesNames;
fLocalVariableNames = localVariables;
fIsInStaticMethod = isInStaticMethod;
fImports = new HashSet<>();
int index = sourceLevel.indexOf('.');
String num;
if (index != -1) {
Expand Down Expand Up @@ -101,9 +107,16 @@ public void buildSourceStatic(IJavaReferenceType type) {
fSource = buildTypeDeclaration(refType, buildRunMethod(refType), null,
false);
String packageName = getPackageName(refType.name());
int packageEndPos = 0;
if (packageName != null) {
fSource.insert(0, "package " + packageName + ";\n"); //$NON-NLS-1$ //$NON-NLS-2$
fCodeSnippetPosition += 10 + packageName.length();
packageEndPos = 10 + packageName.length();
fCodeSnippetPosition += packageEndPos;
}
if (!fImports.isEmpty()) {
String importBlock = fImports.stream().collect(Collectors.joining(";\nimport ", "import ", ";")).concat("\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
fSource.insert(packageEndPos, importBlock);
fCodeSnippetPosition += importBlock.length();
}
fCompilationUnitName = getSimpleName(refType.name());
}
Expand All @@ -128,7 +141,9 @@ private StringBuilder buildRunMethod(ReferenceType type) {
source.append(getUniqueMethodName(RUN_METHOD_NAME, type));
source.append('(');
for (int i = 0, length = fLocalVariableNames.length; i < length; i++) {
source.append(getDotName(fLocalVariableTypeNames[i]));
String varType = getDotName(fLocalVariableTypeNames[i]);
addToImports(varType);
source.append(varType);
source.append(' ');
source.append(fLocalVariableNames[i]);
if (i + 1 < length)
Expand All @@ -147,6 +162,12 @@ private StringBuilder buildRunMethod(ReferenceType type) {
return source;
}

private void addToImports(String type) {
if (!type.equals(getSimpleName(type))) {
fImports.add(Signature.getTypeErasure(type));
}
}

private StringBuilder buildTypeDeclaration(ReferenceType referenceType,
StringBuilder buffer, String nestedTypeName) {

Expand All @@ -164,9 +185,16 @@ private StringBuilder buildTypeDeclaration(ReferenceType referenceType,

if (thisField == null) {
String packageName = getPackageName(referenceType.name());
int packageEndPos = 0;
if (packageName != null) {
source.insert(0, "package " + packageName + ";\n"); //$NON-NLS-1$ //$NON-NLS-2$
fCodeSnippetPosition += 10 + packageName.length();
packageEndPos = 10 + packageName.length();
fCodeSnippetPosition += packageEndPos;
}
if (!fImports.isEmpty()) {
String importBlock = fImports.stream().collect(Collectors.joining(";\nimport ", "import ", ";")).concat("\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
source.insert(packageEndPos, importBlock);
fCodeSnippetPosition += importBlock.length();
}
if (isAnonymousTypeName(referenceType.name())) {
fCompilationUnitName = ANONYMOUS_CLASS_NAME;
Expand Down Expand Up @@ -338,6 +366,8 @@ && isSourceLevelGreaterOrEqual(1, 5)) {
if (!method.isConstructor() && !method.isStaticInitializer()
&& !method.isBridge()) {
source.append(buildMethodDeclaration(method));
} else if (method.isConstructor()) {
source.append(buildMethodDeclaration(method, getSimpleName(referenceType.name())));
}
}

Expand Down Expand Up @@ -394,6 +424,10 @@ private StringBuilder buildFieldDeclaration(Field field) {
}

private StringBuilder buildMethodDeclaration(Method method) {
return buildMethodDeclaration(method, null);
}

private StringBuilder buildMethodDeclaration(Method method, String methodName) {
StringBuilder source = new StringBuilder();

if (method.isFinal()) {
Expand Down Expand Up @@ -444,11 +478,10 @@ private StringBuilder buildMethodDeclaration(Method method) {
source.append("> "); //$NON-NLS-1$
}

source.append(
Signature.toString(
Signature.getReturnType(genericSignature)).replace(
'/', '.')).append(' ').append(method.name())
.append('(');
if (!method.isConstructor()) {
source.append(Signature.toString(Signature.getReturnType(genericSignature)).replace('/', '.')).append(' ');
}
source.append((methodName == null) ? method.name() : methodName).append('(');

String[] parameterTypes = Signature
.getParameterTypes(genericSignature);
Expand Down Expand Up @@ -481,8 +514,10 @@ private StringBuilder buildMethodDeclaration(Method method) {
}
source.append(')');
} else {
source.append(getDotName(method.returnTypeName())).append(' ')
.append(method.name()).append('(');
if (!method.isConstructor()) {
source.append(getDotName(method.returnTypeName())).append(' ');
}
source.append((methodName == null) ? method.name() : methodName).append('(');

List<String> arguments = method.argumentTypeNames();
int i = 0;
Expand Down

0 comments on commit 6260d38

Please sign in to comment.