aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java
blob: 18f9ed632053e7078d89f5b57a57f2c135e14381 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package ftbsc.lll.processor.tools;

import com.squareup.javapoet.*;
import ftbsc.lll.tools.DescriptorBuilder;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.function.Function;

import static ftbsc.lll.processor.tools.ASTUtils.classArrayFromAnnotation;

/**
 * Collection of static utils that rely on JavaPoet to function.
 */
public class JavaPoetUtils {
   /**
    * Builds a {@link MethodSpec} for a public method whose body simply returns a {@link String}.
    * @param name the name of the method
    * @param returnString the {@link String} to return
    * @return the built {@link MethodSpec}
    */
   public static MethodSpec buildStringReturnMethod(String name, String returnString) {
      return MethodSpec.methodBuilder(name)
         .addModifiers(Modifier.PUBLIC)
         .addAnnotation(Override.class)
         .returns(String.class)
         .addStatement("return $S", returnString)
         .build();
   }

   /**
    * Builds a type descriptor from the given {@link TypeName}.
    * @param type the {@link TypeName} representing the desired type
    * @return a {@link String} containing the relevant descriptor
    */
   public static String descriptorFromType(TypeName type) {
      StringBuilder desc = new StringBuilder();
      //add array brackets
      while(type instanceof ArrayTypeName) {
         desc.append("[");
         type = ((ArrayTypeName) type).componentType;
      }
      if(type instanceof ClassName || type instanceof ParameterizedTypeName) {
         ClassName var = type instanceof ParameterizedTypeName ? ((ParameterizedTypeName) type).rawType : (ClassName) type;
         desc.append(DescriptorBuilder.nameToDescriptor(var.canonicalName(), 0));
      } else {
         if(TypeName.BOOLEAN.equals(type))
            desc.append("Z");
         else if(TypeName.CHAR.equals(type))
            desc.append("C");
         else if(TypeName.BYTE.equals(type))
            desc.append("B");
         else if(TypeName.SHORT.equals(type))
            desc.append("S");
         else if(TypeName.INT.equals(type))
            desc.append("I");
         else if(TypeName.FLOAT.equals(type))
            desc.append("F");
         else if(TypeName.LONG.equals(type))
            desc.append("J");
         else if(TypeName.DOUBLE.equals(type))
            desc.append("D");
         else if(TypeName.VOID.equals(type))
            desc.append("V");
      }
      return desc.toString();
   }

   /**
    * Builds a type descriptor from the given {@link TypeMirror}.
    * @param t the {@link TypeMirror} representing the desired type
    * @return a {@link String} containing the relevant descriptor
    */
   public static String descriptorFromType(TypeMirror t) {
      return descriptorFromType(TypeName.get(t));
   }

   /**
    * Builds a method descriptor from the given {@link ExecutableElement}.
    * @param m the {@link ExecutableElement} for the method
    * @return a {@link String} containing the relevant descriptor
    */
   public static String descriptorFromExecutableElement(ExecutableElement m) {
      StringBuilder methodSignature = new StringBuilder();
      methodSignature.append("(");
      m.getParameters().forEach(p -> methodSignature.append(descriptorFromType(p.asType())));
      methodSignature.append(")");
      methodSignature.append(descriptorFromType(m.getReturnType()));
      return methodSignature.toString();
   }

   /**
    * Builds a (partial, not including the return type) method descriptor from its parameters
    * @param ann the annotation containing the class
    * @param fun the annotation function returning the class
    * @return the method descriptor
    */
   public static <T extends Annotation> String methodDescriptorFromParams(T ann, Function<T, Class<?>[]> fun, Elements elementUtils) {
      List<TypeMirror> mirrors = classArrayFromAnnotation(ann, fun, elementUtils);
      StringBuilder sb = new StringBuilder("(");
      for(TypeMirror t : mirrors)
         sb.append(descriptorFromType(t));
      sb.append(")");
      return sb.toString();
   }
}