package io.vertx.codegen.type;

import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;

Author:Julien Viet
/** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */
class TreeTypeInternal implements TypeUse.TypeInternal { public static final TypeUse.TypeInternalProvider PROVIDER = new TypeUse.TypeInternalProvider() { public TypeUse.TypeInternal forParam(ProcessingEnvironment env, ExecutableElement methodElt, int paramIndex) { Trees trees = Trees.instance(env); if (trees == null) { return null; } MethodTree tree = trees.getTree(methodElt); if (tree == null) { return null; } Tree type = tree.getParameters().get(paramIndex).getType(); return new TreeTypeInternal(type, isNullable(type)); } public TypeUse.TypeInternal forReturn(ProcessingEnvironment env, ExecutableElement methodElt) { Trees trees = Trees.instance(env); if (trees == null) { return null; } JCTree.JCMethodDecl tree = (JCTree.JCMethodDecl) trees.getTree(methodElt); if (tree == null) { return null; } JCTree type = tree.getReturnType(); boolean nullable = isNullable(type); if (!nullable) { JCTree.JCModifiers mods = tree.mods; for (JCTree.JCAnnotation jca : mods.annotations) { if (jca.type.toString().equals(TypeUse.NULLABLE)) { nullable = true; break; } } } return new TreeTypeInternal(type, nullable); } }; private final Tree type; private final boolean nullable; private TreeTypeInternal(Tree type, boolean nullable) { this.type = type; this.nullable = nullable; } public boolean isNullable() { return nullable; } @Override public String rawName() { if (type instanceof ParameterizedTypeTree) { ParameterizedTypeTree parameterizedType = (ParameterizedTypeTree) type; return ((TypeElement)((JCTree.JCTypeApply) parameterizedType).type.asElement()).getQualifiedName().toString(); } return null; } public TypeUse.TypeInternal getArgAt(int index) { ParameterizedTypeTree parameterizedType = (ParameterizedTypeTree) type; Tree type = parameterizedType.getTypeArguments().get(index); return new TreeTypeInternal(type, isNullable(type)); } private static boolean isNullable(Tree type) { TypeMirror typeMirror = ((JCTree)type).type; if (typeMirror instanceof com.sun.tools.javac.code.Type.AnnotatedType) { com.sun.tools.javac.code.Type.AnnotatedType abc = (com.sun.tools.javac.code.Type.AnnotatedType) typeMirror; for (AnnotationMirror mirror : abc.getAnnotationMirrors()) { if (mirror.getAnnotationType().toString().equals(TypeUse.NULLABLE)) { return true; } } } if (type instanceof JCTree.JCTypeApply) { JCTree.JCExpression expr = ((JCTree.JCTypeApply) type).clazz; if (expr instanceof AnnotatedTypeTree) { AnnotatedTypeTree tree2 = (AnnotatedTypeTree) expr; for (AnnotationTree mirror : tree2.getAnnotations()) { if (mirror instanceof JCTree.JCAnnotation) { JCTree.JCAnnotation jca = (JCTree.JCAnnotation) mirror; if (jca.type.toString().equals(TypeUse.NULLABLE)) { return true; } } } } } return false; } }