4

Using Java Compiler Tree API to Extract Generics Types

 2 years ago
source link: https://blog.jakubholy.net/2012/02/07/using-java-compiler-tree-api-to-extract-generics-types/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Using Java Compiler Tree API to Extract Generics Types

February 6, 2012
I was looking for some way to extract information about types of elements in Java collections/maps using generics (List<String>, Map<String, MyBean>) so that the users of the Static JSF Expression Validator wouldn't need to declare the type of the elements manually. One possible way to get this information is to process the source codes with the Sun Compiler Tree API, available since JDK 6.

It might be best to go and check the resulting 263 lines of CollectionGenericsTypeExctractor.java now. The code is little ugly, largely due to the API being ugly.

Overview
  1. JavaCompiler (Compiler API) is used to compile the source codes that should be searched for generics
  2. A custom annotation provider (Java Annotation API) is used during the compilation to process the sources
  3. The processor only delegates to a custom TreePathScanner (Sun Compiler Tree API) whose visitMethod extracts all the information from the MethodTree, using some dark magic to get fully qualified type names of the class and return type
Limitations
  1. The Compiler must be able to resolve all dependencies (imports) to be able to process the files
  2. It only works with Sun JDK and its tools.jar must be on the class path (the Compiler and Annotation APIs are a part of Java specification but the Compiler Tree API is not and is thus vendor-specific)
  3. The code currently doesn't handle getters inside nested/inner classes (it would need to check that it is such a class and replace the last . with $ in the name)
You'd better check the complete (short) code at GitHub but if it's too far for you :-), here is the crucial piece:

@Override
public Object visitMethod(MethodTree methodTree, Trees trees) {
	String typeNameQualified = getEnclosingClassNameIfAvailable(trees);

// Skip or bad stuff happens (case: inside anonymous inner class) if (typeNameQualified == null) { return super.visitMethod(methodTree, trees); }

Tree returnType = methodTree.getReturnType(); // null for void method if (getter(methodTree) && returnType instanceof ParameterizedTypeTree) { assert Tree.Kind.PARAMETERIZED_TYPE == returnType.getKind(); ParameterizedTypeTree parametrizedReturnType = (ParameterizedTypeTree) returnType;

TypeCategory category = detectTypeCategory(parametrizedReturnType); if (category.isCollectionOrMap()) { Tree valueTypeArgument = parametrizedReturnType.getTypeArguments().get(category.getValueTypeArgumentIdx()); final String qualifiedGenericTypeName = getQualifiedType(valueTypeArgument);

String methodJsfName = getMethodJsfName(methodTree); System.out.println("FOUND " + typeNameQualified + "." + methodJsfName + ".*=" + qualifiedGenericTypeName); // Unqualified name: ((IdentifierTree) valueTypeArgument).getName().toString(); } } return super.visitMethod(methodTree, trees); }


Most of the code has been copied from the article Source Code Analysis Using Java 6 APIs by Seema Richard (4/2008).

Conclusion

It's possible to use the Java Compiler Tree API to get the desired information but it is not exactly easy because the API os overly complex and undocumented. It would likely be better to use some decent open-source Java parser.
Tags: java

Are you benefitting from my writing? Consider buying me a coffee or supporting my work via GitHub Sponsors. Thank you! You can also book me for a mentoring / pair-programming session via Codementor or (cheaper) email.

Allow me to write to you!

Let's get in touch! I will occasionally send you a short email with a few links to interesting stuff I found and with summaries of my new blog posts. Max 1-2 emails per month. I read and answer to all replies.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK