Java8, how discover the class and method name in visitMethodInvocation?

后端 未结 2 1561
予麋鹿
予麋鹿 2020-12-15 14:30

With Java7 and Java8, I would like to generate a warning if some methods was called. The warning will be print if a specific jar is present when then user compile.

I

2条回答
  •  囚心锁ツ
    2020-12-15 14:56

    As an alternative to the great answer from @emory, you can consider using the pluggable type-checking annotation processing provided by the Checker Framework. The advantage is it can help you to easily determinate the type of the method invoker. Here is an example processor based on the checker framework (add checker.jar to the classpath when compile).

    @SupportedAnnotationTypes("*")
    @SupportedSourceVersion(SourceVersion.RELEASE_8)
    public class MyTypeProcessor extends AbstractTypeProcessor {
        class MyTreePathScanner extends TreePathScanner {
            private final Trees trees;
            private final TreePath root;
    
            public MyTreePathScanner(TreePath root) {
                this.trees = Trees.instance(processingEnv);
                this.root = root;
            }
    
            @Override
            public Void visitMemberSelect(MemberSelectTree node, Void aVoid) {
                ExpressionTree expression = node.getExpression();
                TreePath expr = TreePath.getPath(root, expression);
                TypeMirror type = trees.getTypeMirror(expr);
                Element typeElement = processingEnv.getTypeUtils().asElement(type);
                Optional invoker = typeElement.getEnclosedElements().stream().filter(
                        e -> e.getSimpleName().equals(node.getIdentifier())).findFirst();
                if (invoker.isPresent() && invoker.get().getKind() == ElementKind.METHOD) {
                    System.out.println("Type: " + typeElement + ", method: " + invoker.get());
                }
                return super.visitMemberSelect(node, aVoid);
            }
    
        }
    
        @Override
        public void typeProcess(TypeElement typeElement, TreePath root) {
            new MyTreePathScanner(root).scan(root, null);
        }
    }
    

    Which is processing the following input source.

    public class Test {
    
        public void foo() {
        }
    
        public static void main(String[] args) {
            System.out.println("Hello world!");
            Test t = new Test();
            t.foo();
        }
    }
    

    Here is the output:

    Type: java.io.PrintStream, method: println()
    Type: Test, method: foo()
    

提交回复
热议问题