public static void parse(Path moduleInfoPath, ModuleClassVisitor moduleClassVisitor) throws IOException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); try(StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) { Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(moduleInfoPath); CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits); JavacTask javacTask = (JavacTask)task; Iterable<? extends CompilationUnitTree> units= javacTask.parse(); CompilationUnitTree unit = units.iterator().next(); ModuleHandler moduleHandler = new ModuleHandler(moduleClassVisitor); TreeVisitor<?,?> visitor = (TreeVisitor<?,?>)Proxy.newProxyInstance(TreeVisitor.class.getClassLoader(), new Class<?>[]{ TreeVisitor.class}, (proxy, method, args) -> { ModuleHandler.METHOD_MAP .getOrDefault(method.getName(), (handler, node, v) -> { throw new AssertionError("invalid node " + node.getClass()); }) .visit(moduleHandler, (Tree)args[0], (TreeVisitor<?,?>)proxy); return null; }); unit.accept(visitor, null); } }
@Test public void matches() { // TODO(b/67738557): consolidate helpers for creating fake trees LiteralTree tree = new LiteralTree() { @Override public Kind getKind() { throw new UnsupportedOperationException(); } @Override public <R, D> R accept(TreeVisitor<R, D> visitor, D data) { throw new UnsupportedOperationException(); } @Override public Object getValue() { return "a string literal"; } }; assertTrue(new StringLiteral("a string literal").matches(tree, null)); }
public <R, D> R accept(TreeVisitor<R, D> arg0, D arg1) { R ret = null; for (JCVariableDecl v : vars) { ret = v.accept(arg0, arg1); } return ret; }
@SuppressWarnings("static-method") public void visitCompilationUnit(CompilationUnitTree node, TreeVisitor<?, ?> visitor) { for(Tree decl: node.getTypeDecls()) { if (!(decl instanceof ModuleTree)) { // skip unnecessary nodes: imports, etc continue; } accept(visitor, decl); } }
public void visitModule(ModuleTree node, TreeVisitor<?, ?> visitor) { String name = qualifiedString(node.getName()); int flags = node.getModuleType() == ModuleKind.OPEN? ACC_OPEN: 0; mv = moduleClassVisitor.visitModule(name, flags, null); node.getDirectives().forEach(n -> accept(visitor, n)); }
@Override public <R, D> R accept(TreeVisitor<R, D> tv, D d) { for (T current : children) { if (current != null) { current.accept(tv, d); } } return null; }
@Override public <R, D> R accept(TreeVisitor<R, D> tv, D d) { tv.visitMethod(this, d); for (VariableTree variable : parameters) { variable.accept(tv, d); } return super.accept(tv, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> visitor, D data) { return visitor.visitOther(this, data); }
public static <T> T createInstance(Context ctx, Class<T> clazz, Name ident, JCIdent jcIdent, Class<?>[] requiredConstructor, Object[] params) { try { Class<?> fake = baseClass2Impl.get(clazz); if (fake == null) { Method visitIdent = Visitor.class.getDeclaredMethod("visitIdent", JCIdent.class); Method visitIdentifier = TreeVisitor.class.getDeclaredMethod("visitIdentifier", IdentifierTree.class, Object.class); Method toString = Object.class.getDeclaredMethod("toString"); fake = new ByteBuddy() .subclass(clazz) .implement(IdentifierTree.class) .defineField("ident", Name.class, Visibility.PUBLIC) .defineField("jcIdent", JCIdent.class, Visibility.PUBLIC) .method(ElementMatchers.named("getName")).intercept(FieldAccessor.ofField("ident")) .method(ElementMatchers.named("getKind")).intercept(FixedValue.value(Kind.IDENTIFIER)) .method(ElementMatchers.named("accept").and(ElementMatchers.takesArguments(Visitor.class))).intercept(MethodCall.invoke(visitIdent).onArgument(0).withField("jcIdent")) .method(ElementMatchers.named("accept").and(ElementMatchers.takesArgument(0, TreeVisitor.class))).intercept(MethodCall.invoke(visitIdentifier).onArgument(0).withThis().withArgument(1)) .method(ElementMatchers.named("toString")).intercept(MethodCall.invoke(toString).onField("ident")) .make() .load(JackpotTrees.class.getClassLoader()) .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); } JCTree tree = (JCTree) c.newInstance(instances.toArray(new Object[0])); Field identField = fake.getDeclaredField("ident"); identField.set(tree, ident); Field jcIdentField = fake.getDeclaredField("jcIdent"); jcIdentField.set(tree, jcIdent); return clazz.cast(tree); } throw new IllegalStateException(); } catch (IllegalAccessException | IllegalArgumentException | IllegalStateException | InstantiationException | NoSuchFieldException | NoSuchMethodException | SecurityException | InvocationTargetException ex) { throw new IllegalStateException(ex); } }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitIdentifier(this, d); }
private static void accept(TreeVisitor<?, ?> visitor, Tree node) { node.accept(visitor, null); }
public void visitRequires(RequiresTree node, @SuppressWarnings("unused") TreeVisitor<?, ?> __) { int modifiers = (node.isStatic()? ACC_STATIC: 0) | (node.isTransitive()? ACC_TRANSITIVE: 0); mv.visitRequire(qualifiedString(node.getModuleName()), modifiers, null); }
public void visitExports(ExportsTree node, @SuppressWarnings("unused") TreeVisitor<?, ?> __) { mv.visitExport(qualifiedString(node.getPackageName()), 0, toArray(node.getModuleNames())); }
public void visitOpens(OpensTree node, @SuppressWarnings("unused") TreeVisitor<?, ?> __) { mv.visitOpen(qualifiedString(node.getPackageName()), 0, toArray(node.getModuleNames())); }
public void visitUses(UsesTree node, @SuppressWarnings("unused") TreeVisitor<?, ?> __) { mv.visitUse(qualifiedString(node.getServiceName())); }
public void visitProvides(ProvidesTree node, @SuppressWarnings("unused") TreeVisitor<?, ?> __) { mv.visitProvide(qualifiedString(node.getServiceName()), toArray(node.getImplementationNames())); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitCompilationUnit(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitImport(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitClass(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitMethod(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitVariable(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitEmptyStatement(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitBlock(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitDoWhileLoop(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitWhileLoop(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitForLoop(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitEnhancedForLoop(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitLabeledStatement(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitSwitch(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitCase(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitSynchronized(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitTry(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitCatch(this, d); }
@Override public <R, D> R accept(TreeVisitor<R, D> v, D d) { return v.visitConditionalExpression(this, d); }