1 package java.lang.reflect.code.type; 2 3 import java.lang.constant.ClassDesc; 4 import java.lang.reflect.code.TypeElement; 5 import java.lang.reflect.code.type.WildcardType.BoundKind; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 public final class CoreTypeFactory { 10 11 private CoreTypeFactory() { 12 } 13 14 // Code model type factory composed 15 16 /** 17 * Create a code model factory combining and composing the construction 18 * of code model types with types constructed from the given type factory. 19 * 20 * @param f the type factory. 21 * @return the code model factory. 22 */ 23 public static TypeElementFactory codeModelTypeFactory(TypeElementFactory f) { 24 class CodeModelFactory implements TypeElementFactory { 25 final TypeElementFactory thisThenF = this.andThen(f); 26 27 @Override 28 public TypeElement constructType(TypeElement.ExternalizedTypeElement tree) { 29 return switch (tree.identifier()) { 30 case VarType.NAME -> { 31 if (tree.arguments().size() != 1) { 32 throw new IllegalArgumentException(); 33 } 34 35 TypeElement v = thisThenF.constructType(tree.arguments().getFirst()); 36 if (v == null) { 37 throw new IllegalArgumentException("Bad type: " + tree); 38 } 39 yield VarType.varType(v); 40 } 41 case TupleType.NAME -> { 42 if (tree.arguments().isEmpty()) { 43 throw new IllegalArgumentException("Bad type: " + tree); 44 } 45 46 List<TypeElement> cs = new ArrayList<>(tree.arguments().size()); 47 for (TypeElement.ExternalizedTypeElement child : tree.arguments()) { 48 TypeElement c = thisThenF.constructType(child); 49 if (c == null) { 50 throw new IllegalArgumentException("Bad type: " + tree); 51 } 52 cs.add(c); 53 } 54 yield TupleType.tupleType(cs); 55 } 56 case FunctionType.NAME -> { 57 if (tree.arguments().isEmpty()) { 58 throw new IllegalArgumentException("Bad type: " + tree); 59 } 60 61 TypeElement rt = thisThenF.constructType(tree.arguments().getFirst()); 62 if (rt == null) { 63 throw new IllegalArgumentException("Bad type: " + tree); 64 } 65 List<TypeElement> pts = new ArrayList<>(tree.arguments().size() - 1); 66 for (TypeElement.ExternalizedTypeElement child : tree.arguments().subList(1, tree.arguments().size())) { 67 TypeElement c = thisThenF.constructType(child); 68 if (c == null) { 69 throw new IllegalArgumentException("Bad type: " + tree); 70 } 71 pts.add(c); 72 } 73 yield FunctionType.functionType(rt, pts); 74 } 75 default -> null; 76 }; 77 } 78 } 79 if (f instanceof CodeModelFactory) { 80 throw new IllegalArgumentException(); 81 } 82 83 return new CodeModelFactory().thisThenF; 84 } 85 86 // Java type factory 87 88 /** 89 * The Java type factory. 90 */ 91 public static final TypeElementFactory JAVA_TYPE_FACTORY = new TypeElementFactory() { 92 @Override 93 public TypeElement constructType(TypeElement.ExternalizedTypeElement tree) { 94 String identifier = tree.identifier(); 95 int dimensions = 0; 96 if (identifier.startsWith("[")) { 97 if (tree.arguments().size() != 1) { 98 throw new IllegalArgumentException("Bad type: " + tree); 99 } 100 for (int i = 1; i < identifier.length(); i++) { 101 if (identifier.charAt(i) != '[') { 102 throw new IllegalArgumentException("Bad type: " + tree); 103 } 104 } 105 dimensions = identifier.length(); 106 tree = tree.arguments().getFirst(); 107 identifier = tree.identifier(); 108 } 109 110 List<JavaType> typeArguments = new ArrayList<>(tree.arguments().size()); 111 for (TypeElement.ExternalizedTypeElement child : tree.arguments()) { 112 TypeElement t = JAVA_TYPE_FACTORY.constructType(child); 113 if (!(t instanceof JavaType a)) { 114 throw new IllegalArgumentException("Bad type: " + tree); 115 } 116 typeArguments.add(a); 117 } 118 if (identifier.equals("+") || identifier.equals("-")) { 119 // wildcard type 120 BoundKind kind = identifier.equals("+") ? 121 BoundKind.EXTENDS : BoundKind.SUPER; 122 return JavaType.wildcard(kind, typeArguments.get(0)); 123 } else if (identifier.startsWith("#")) { 124 // type-var 125 if (typeArguments.size() != 1) { 126 throw new IllegalArgumentException("Bad type-variable bounds: " + tree); 127 } 128 String[] parts = identifier.substring(1).split("::"); 129 if (parts.length == 2) { 130 // class type-var 131 return JavaType.typeVarRef(parts[1], 132 (ClassType)constructType(parseExTypeElem(parts[0])), 133 typeArguments.get(0)); 134 } else { 135 // method type-var 136 return JavaType.typeVarRef(parts[2], 137 parseMethodRef(String.format("%s::%s", parts[0], parts[1])), 138 typeArguments.get(0)); 139 } 140 } 141 JavaType t = switch (identifier) { 142 case "boolean" -> JavaType.BOOLEAN; 143 case "byte" -> JavaType.BYTE; 144 case "char" -> JavaType.CHAR; 145 case "short" -> JavaType.SHORT; 146 case "int" -> JavaType.INT; 147 case "long" -> JavaType.LONG; 148 case "float" -> JavaType.FLOAT; 149 case "double" -> JavaType.DOUBLE; 150 case "void" -> JavaType.VOID; 151 default -> JavaType.type(ClassDesc.of(identifier)); 152 }; 153 if (!typeArguments.isEmpty()) { 154 t = JavaType.parameterized(t, typeArguments); 155 } 156 return dimensions == 0 ? 157 t : JavaType.array(t, dimensions); 158 } 159 }; 160 161 162 /** 163 * The core type factory that can construct instance of {@link JavaType} 164 * or code model types such as {@link VarType} or {@link TupleType} that 165 * may contain instances of those types. 166 */ 167 public static final TypeElementFactory CORE_TYPE_FACTORY = codeModelTypeFactory(JAVA_TYPE_FACTORY); 168 169 // Copied code in jdk.compiler module throws UOE 170 static MethodRef parseMethodRef(String desc) { 171 /*__throw new UnsupportedOperationException();__*/ return java.lang.reflect.code.parser.impl.DescParser.parseMethodRef(desc); 172 } 173 174 // Copied code in jdk.compiler module throws UOE 175 static TypeElement.ExternalizedTypeElement parseExTypeElem(String desc) { 176 /*__throw new UnsupportedOperationException();__*/ return java.lang.reflect.code.parser.impl.DescParser.parseExTypeElem(desc); 177 } 178 }