1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.reflect.code.type;
 27 
 28 import java.lang.constant.ClassDesc;
 29 import java.lang.invoke.MethodHandles.Lookup;
 30 import java.lang.reflect.Type;
 31 import java.util.List;
 32 import java.util.Map;
 33 import java.util.Optional;
 34 
 35 /**
 36  * A primitive type.
 37  */
 38 public final class PrimitiveType implements JavaType {
 39     // Fully qualified name
 40     private final ClassDesc type;
 41 
 42     PrimitiveType(ClassDesc type) {
 43         this.type = type;
 44     }
 45 
 46     @Override
 47     public Type resolve(Lookup lookup) throws ReflectiveOperationException {
 48         return type.resolveConstantDesc(lookup);
 49     }
 50 
 51     @Override
 52     public ExternalizedTypeElement externalize() {
 53         return new ExternalizedTypeElement(type.displayName(), List.of());
 54     }
 55 
 56     @Override
 57     public String toString() {
 58         return externalize().toString();
 59     }
 60 
 61     @Override
 62     public boolean equals(Object o) {
 63         if (this == o) return true;
 64         if (o == null || getClass() != o.getClass()) return false;
 65 
 66         PrimitiveType typeDesc = (PrimitiveType) o;
 67 
 68         return type.equals(typeDesc.type);
 69     }
 70 
 71     @Override
 72     public int hashCode() {
 73         return type.hashCode();
 74     }
 75 
 76     @Override
 77     public JavaType erasure() {
 78         return this;
 79     }
 80 
 81     @Override
 82     public JavaType toBasicType() {
 83         return switch (type.descriptorString().charAt(0)) {
 84             case 'V' -> JavaType.VOID;
 85             case 'J' -> JavaType.LONG;
 86             case 'F' -> JavaType.FLOAT;
 87             case 'D' -> JavaType.DOUBLE;
 88             default -> JavaType.INT;
 89         };
 90     }
 91 
 92     /**
 93      * {@return the boxed class type associated with this primitive type (if any)}
 94      */
 95     public Optional<ClassType> box() {
 96         class LazyHolder {
 97             static final Map<PrimitiveType, ClassType> primitiveToWrapper = Map.of(
 98                     BYTE, J_L_BYTE,
 99                     SHORT, J_L_SHORT,
100                     INT, J_L_INTEGER,
101                     LONG, J_L_LONG,
102                     FLOAT, J_L_FLOAT,
103                     DOUBLE, J_L_DOUBLE,
104                     CHAR, J_L_CHARACTER,
105                     BOOLEAN, J_L_BOOLEAN
106             );
107         }
108         return Optional.ofNullable(LazyHolder.primitiveToWrapper.get(this));
109     };
110 
111     @Override
112     public ClassDesc toNominalDescriptor() {
113         return type;
114     }
115 
116     /**
117      * {@return {@code true} if this type is {@link JavaType#VOID}}
118      */
119     public boolean isVoid() {
120         return toBasicType() == JavaType.VOID;
121     }
122 }