Get a class as javax.lang.model.element.Element in

2019-06-02 05:03发布

问题:

I would like to test my utility class ElementUtils but I don't know how to get a class as an Element. In AnnotationProcessors I get my elements by using the following code

Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(annotation);

but since the RoundEnvironment is not available in the tests this is not an option.

Is there any way to get a class as an javax.lang.model.element.Element?

回答1:

You can use a JUnit @Rule to invoke a compiler run during the test, at which point you may then use Types and Elements utility classes to obtain TypeMirror and Element instances.

Such a rule has been created and is a part of http://github.com/google/compile-testing and can be used thusly:

public @Rule CompilationRule rule = new CompilationRule();
private Elements elements;
private Types types;


@Before
public void setup() {
  elements = rule.getElements();
  types = rule.getTypes();
}

@Test void testStuff() {
  TypeElement typeElement = elements.getTypeElement("some.fully.qualified.ClassName");
  // do stuff.
}

Some of what stuff you can do to manipulate (whether in tests or otherwise) TypeMirror and Element instances can be found in the http://github.com/google/auto project in the common sub-module, which contains utilities for managing these java.lang.model classes conveniently.



回答2:

Element instances are only valid mid-compile. The docs for equals() state that "the identity of an element involves implicit state", which in the javac implementation is actually invalidated once compilation is completed. So, if you're trying to hold references to Element instances and compare them to other Element instances in a test, it's not going to work.

That said, you do have some flexibility if you cast a javax.tools.JavaCompiler.CompilationTask to a com.sun.source.util.JavacTask. Then, you can manually invoke the parse() and analyze() phases and get at Element instances using the Elements instance returned from JavacTask.getElements().