This is an automated email from the ASF dual-hosted git repository. neilcsmith pushed a commit to branch delivery in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/delivery by this push: new 2dcead8 attempt to make JackpotTrees more robust. new e6bef73 Merge pull request #3283 from mbien/happytrees 2dcead8 is described below commit 2dcead8dde01037abf983d7632e3143d1e3fee88 Author: Michael Bien <mbie...@gmail.com> AuthorDate: Thu Oct 28 22:50:30 2021 +0200 attempt to make JackpotTrees more robust. - JackpotTrees.createInstance() will match constructors directly (no unknown parameter filling with null anymore) - extracted typesafe factory methods to keep the fragile code in one place and make it hopefully easier to update it in future --- .../modules/java/hints/spiimpl/JackpotTrees.java | 91 +++++++++++----------- .../modules/java/hints/spiimpl/Utilities.java | 13 +--- 2 files changed, 48 insertions(+), 56 deletions(-) diff --git a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java index 96d3e00..8515d68 100644 --- a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java +++ b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java @@ -33,6 +33,7 @@ import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.JCTree.JCCase; import com.sun.tools.javac.tree.JCTree.Visitor; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.Context; @@ -40,9 +41,7 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; import java.lang.reflect.Constructor; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -61,7 +60,35 @@ import net.bytebuddy.matcher.ElementMatchers; public class JackpotTrees { private static final Map<Class<?>, Class<?>> baseClass2Impl = new HashMap<>(); - public static <T> T createInstance(Context ctx, Class<T> clazz, Name ident, JCIdent jcIdent, Class<?>[] requiredConstructor, Object[] params) { + + // JDK 8-11 + public static JCCase createJCCase(Name ident, JCIdent jcIdent, List<?> stats) { + return createInstance(JCCase.class, ident, jcIdent, + new Class<?>[] {JCExpression.class, List.class}, + new Object[] {jcIdent, stats}); + } + + // JDK 12-17+ + public static JCCase createJCCase(Name ident, JCIdent jcIdent, String caseKind, List<?> labels, List<?> stats, JCTree body) throws ReflectiveOperationException { + + @SuppressWarnings("rawtypes") + Class kindClass = Class.forName("com.sun.source.tree.CaseTree$CaseKind", false, JCCase.class.getClassLoader()); + @SuppressWarnings("unchecked") + Object caseKindValue = Enum.valueOf(kindClass, caseKind); + + return createInstance(JCCase.class, ident, jcIdent, + new Class<?>[] {kindClass, List.class, List.class, JCTree.class}, + new Object[] {caseKindValue, labels, stats, body}); + } + + // JDK 8-17+ + public static JCVariableDecl createJCVariableDecl(Name ident, JCIdent jcIdent, JCModifiers mods, Name param2, JCExpression vartype, JCExpression init, VarSymbol sym) { + return createInstance(JCVariableDecl.class, ident, jcIdent, + new Class<?>[] {JCModifiers.class, Name.class, JCExpression.class, JCExpression.class, VarSymbol.class}, + new Object[] {mods, param2, vartype, init, sym}); + } + + private static <T> T createInstance(Class<T> clazz, Name ident, JCIdent jcIdent, Class<?>[] requiredConstructor, Object[] params) { try { Class<?> fake = baseClass2Impl.get(clazz); @@ -84,37 +111,31 @@ public class JackpotTrees { .getLoaded(); baseClass2Impl.put(clazz, fake); } - - NEXT: for (Constructor<?> c : fake.getDeclaredConstructors()) { - if (c.getParameterCount() < requiredConstructor.length) - continue; - for (int e = 0; e < requiredConstructor.length; e++) { - if (!c.getParameterTypes()[e].equals(requiredConstructor[e])) { - continue NEXT; - } - } - java.util.List<Object> instances = new ArrayList<>(); - instances.addAll(Arrays.asList(params)); - for (int i = instances.size(); i < c.getParameterCount(); i++) { - instances.add(null); + + Constructor<?> compatible = null; + for (Constructor<?> constructor : fake.getDeclaredConstructors()) { + if (Arrays.equals(constructor.getParameterTypes(), requiredConstructor)) { + compatible = constructor; + break; } - - JCTree tree = (JCTree) c.newInstance(instances.toArray(new Object[0])); + } + + if (compatible != null) { + + JCTree tree = (JCTree) compatible.newInstance(params); Field identField = fake.getDeclaredField("ident"); - identField.set(tree, ident); Field jcIdentField = fake.getDeclaredField("jcIdent"); - jcIdentField.set(tree, jcIdent); return clazz.cast(tree); + } else { + throw new IllegalStateException("no compatible constructors found in: "+Arrays.asList(fake.getDeclaredConstructors()).toString()); } - - throw new IllegalStateException(Arrays.asList(fake.getDeclaredConstructors()).toString()); - } catch (IllegalAccessException | IllegalArgumentException | IllegalStateException | InstantiationException | NoSuchFieldException | NoSuchMethodException | SecurityException | InvocationTargetException ex) { - throw new IllegalStateException(ex); + } catch (ReflectiveOperationException | IllegalArgumentException | IllegalStateException | SecurityException ex) { + throw new IllegalStateException("can't instantiate "+Arrays.asList(requiredConstructor).toString()+" of "+clazz, ex); } } @@ -202,27 +223,7 @@ public class JackpotTrees { err.type = Symtab.instance(ctx).errType; - JCVariableDecl var; - - try { - var = createInstance(ctx, - JCVariableDecl.class, - name, - jcIdent, - new Class<?>[] {JCModifiers.class, Name.class, JCExpression.class, JCExpression.class, VarSymbol.class}, - new Object[] {new FakeModifiers(), name, err, null, null}); - } catch (IllegalStateException ex) { - try { - var = createInstance(ctx, - JCVariableDecl.class, - name, - jcIdent, - new Class<?>[] {JCModifiers.class, Name.class, JCExpression.class, JCExpression.class, VarSymbol.class, List.class}, - new Object[] {new FakeModifiers(), name, err, null, null, List.nil()}); - } catch (IllegalStateException ex2) { - throw ex; - } - } + JCVariableDecl var = createJCVariableDecl(name, jcIdent, new FakeModifiers(), name, err, null, null); var.sym = new VarSymbol(0, name, var.vartype.type, Symtab.instance(ctx).errSymbol); var.type = var.vartype.type; diff --git a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java index 59d17bc..b41ef37 100644 --- a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java +++ b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java @@ -1525,8 +1525,7 @@ public class Utilities { } JCIdent identTree = F.at(pos).Ident(name); - - return JackpotTrees.createInstance(ctx, JCCase.class, name, identTree, new Class<?>[] {JCExpression.class, com.sun.tools.javac.util.List.class}, new Object[] {identTree, com.sun.tools.javac.util.List.nil()}); + return JackpotTrees.createJCCase(name, identTree, com.sun.tools.javac.util.List.nil()); } } } @@ -1555,17 +1554,9 @@ public class Utilities { nextToken(); } - @SuppressWarnings("rawtypes") - Class caseKind = Class.forName("com.sun.source.tree.CaseTree$CaseKind", false, JCCase.class.getClassLoader()); - @SuppressWarnings("unchecked") - Object statement = Enum.valueOf(caseKind, "STATEMENT"); - JCIdent identTree = F.at(pos).Ident(name); return com.sun.tools.javac.util.List.of( - JackpotTrees.createInstance(ctx, JCCase.class, name, identTree, - new Class<?>[] {caseKind, com.sun.tools.javac.util.List.class, com.sun.tools.javac.util.List.class, JCTree.class}, - new Object[] {statement, com.sun.tools.javac.util.List.of(identTree), com.sun.tools.javac.util.List.nil(), null} - ) + JackpotTrees.createJCCase(name, identTree, "STATEMENT", com.sun.tools.javac.util.List.of(identTree), com.sun.tools.javac.util.List.nil(), null) ); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists