Skip to content

Commit

Permalink
Merge pull request apache#8016 from lahodaj/ensure-checkContext-is-ba…
Browse files Browse the repository at this point in the history
…sicHandler-in-Scopes

Ensure AttrContext.returnResult's checkContext is set to Check.basicHandler in javac's Scopes, to avoid it throwing exceptions.
  • Loading branch information
lahodaj authored Dec 5, 2024
2 parents 2e32e97 + 3959bf1 commit 583e9ca
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
import java.beans.PropertyVetoException;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -1553,6 +1555,63 @@ public void run(WorkingCopy parameter) throws Exception {
parameter.rewrite(testTree, nueTestTree);
}
}

public void testGenerateMethodInLambda() throws Exception {
performTest("test/Test.java",
"""
package test;
public class Test {
private void test(Runnable r) {
test(() -> {
new Base<Void, Void>() {};
});
}
}
class Base<T1, T2> {
public T1 test(T1 p) {}
}
""",
"17",
new Task<WorkingCopy>() {
@Override
public void run(WorkingCopy copy) throws java.lang.Exception {
copy.toPhase(Phase.RESOLVED);
new TreePathScanner<Void, Void>() {
@Override
public Void visitNewClass(NewClassTree node, Void p) {
if (node.getClassBody() != null) {
ClassTree clazz = node.getClassBody();
TypeElement anon = (TypeElement) copy.getTrees().getElement(new TreePath(getCurrentPath(), clazz));
TypeElement superClass = (TypeElement) ((DeclaredType) anon.getSuperclass()).asElement();
ExecutableElement method = (ExecutableElement) superClass.getEnclosedElements().stream().filter(el -> el.getSimpleName().contentEquals("test")).findAny().get();
copy.rewrite(clazz, copy.getTreeMaker().addClassMember(clazz, GeneratorUtilities.get(copy).createOverridingMethod(anon, method)));
}
return super.visitNewClass(node, p);
}

}.scan(copy.getCompilationUnit(), null);
}
},
new ContentValidator("""
package test;
public class Test {
private void test(Runnable r) {
test(() -> {
new Base<Void, Void>() {
@Override
public Void test(Void p) {
return super.test(p); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/OverriddenMethodBody
}
};
});
}
}
class Base<T1, T2> {
public T1 test(T1 p) {}
}
"""),
false);
}

private static final class ContentValidator implements Validator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
import java.util.regex.Pattern;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.source.Comment.Style;
Expand Down Expand Up @@ -874,4 +876,27 @@ public void testPathForInUnnamedClass() throws Exception {

assertEquals("System", it.getName().toString());
}

public void testAttributeTreeCrashes() throws Exception {
this.sourceLevel = "21";

String code = """
package test;
public class Test {
private void test(Runnable r) {
test(() -> {
|
});
}
}
""";

prepareTest("Test", code.replace("|", ""));

int pos = code.indexOf("|");
TreePath tp = info.getTreeUtilities().pathFor(pos);
Scope scope = info.getTrees().getScope(tp);
StatementTree tree = info.getTreeUtilities().parseStatement("{ return super.test(p); }", new SourcePositions[1]);
info.getTreeUtilities().attributeTree(tree, scope);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,21 @@
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.lang.model.element.Element;

/**
Expand All @@ -39,7 +47,9 @@
*/
public class NBJavacTrees extends JavacTrees {

private static final Logger LOG = Logger.getLogger(NBJavacTrees.class.getName());
private final Map<Element, TreePath> element2paths = new HashMap<>();
private final CheckContext chkBasicHandler;

public static void preRegister(Context context) {
context.put(JavacTrees.class, new Context.Factory<JavacTrees>() {
Expand All @@ -50,7 +60,21 @@ public JavacTrees make(Context c) {
}
protected NBJavacTrees(Context context) {
super(context);
Check chk = Check.instance(context);

CheckContext chkBasicHandlerTemp = null;

try {
if (basicHandlerField != null) {
chkBasicHandlerTemp = (CheckContext) basicHandlerField.get(chk);
}
} catch (ReflectiveOperationException ex) {
LOG.log(Level.FINE, null, ex);
}

chkBasicHandler = chkBasicHandlerTemp;
}

@Override
public TreePath getPath(Element e) {
TreePath path = super.getPath(e);
Expand Down Expand Up @@ -81,4 +105,53 @@ public JCTree visitVariable(VariableTree node, JCTree p) {
};
}

@Override
public JavacScope getScope(TreePath path) {
JavacScope result = super.getScope(path);

if (returnResultField != null) {
Env<AttrContext> env = result.getEnv();

try {
Object returnResult = returnResultField.get(env.info);
if (returnResult != null) {
//ensure the returnResult's checkContext is the Check.basicHandler:
returnResultField.set(env.info, dupMethod.invoke(returnResult, chkBasicHandler));
}
} catch (ReflectiveOperationException ex) {
LOG.log(Level.FINE, null, ex);
}
}

return result;
}

private static final Field basicHandlerField;
private static final Field returnResultField;
private static final Method dupMethod;

static {
Field basicHandlerFieldTemp;
Field returnResultFieldTemp;
Method dupMethodTemp;

try {
basicHandlerFieldTemp = Check.class.getDeclaredField("basicHandler");
basicHandlerFieldTemp.setAccessible(true);
returnResultFieldTemp = AttrContext.class.getDeclaredField("returnResult");
returnResultFieldTemp.setAccessible(true);
dupMethodTemp = Class.forName("com.sun.tools.javac.comp.Attr$ResultInfo")
.getDeclaredMethod("dup", CheckContext.class);
dupMethodTemp.setAccessible(true);
} catch (ReflectiveOperationException ex) {
LOG.log(Level.FINE, null, ex);
basicHandlerFieldTemp = null;
returnResultFieldTemp = null;
dupMethodTemp = null;
}

basicHandlerField = basicHandlerFieldTemp;
returnResultField = returnResultFieldTemp;
dupMethod = dupMethodTemp;
}
}

0 comments on commit 583e9ca

Please sign in to comment.