| // Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | package com.android.tools.r8.references; | 
 |  | 
 | import com.android.tools.r8.Keep; | 
 | import com.android.tools.r8.utils.DescriptorUtils; | 
 | import com.google.common.collect.ImmutableList; | 
 | import java.lang.reflect.Constructor; | 
 | import java.lang.reflect.Field; | 
 | import java.lang.reflect.Method; | 
 | import java.util.Collections; | 
 | import java.util.List; | 
 |  | 
 | /** | 
 |  * Reference provider/factory. | 
 |  * | 
 |  * <p>The reference class provides a single point for creating and managing reference objects that | 
 |  * represent types, methods and fields in a JVM/DEX application. The objects may or may not be | 
 |  * interned/shared. | 
 |  * | 
 |  * <p>No guarantees are made on identity and all references must be compared by {@code equals}. | 
 |  */ | 
 | @Keep | 
 | public final class Reference { | 
 |  | 
 |   public static PrimitiveReference BOOL = PrimitiveReference.BOOL; | 
 |   public static PrimitiveReference BYTE = PrimitiveReference.BYTE; | 
 |   public static PrimitiveReference CHAR = PrimitiveReference.CHAR; | 
 |   public static PrimitiveReference SHORT = PrimitiveReference.SHORT; | 
 |   public static PrimitiveReference INT = PrimitiveReference.INT; | 
 |   public static PrimitiveReference FLOAT = PrimitiveReference.FLOAT; | 
 |   public static PrimitiveReference LONG = PrimitiveReference.LONG; | 
 |   public static PrimitiveReference DOUBLE = PrimitiveReference.DOUBLE; | 
 |  | 
 |   private Reference() { | 
 |     // Intentionally hidden. | 
 |   } | 
 |  | 
 |   public static TypeReference returnTypeFromDescriptor(String descriptor) { | 
 |     return descriptor.equals("V") ? null : typeFromDescriptor(descriptor); | 
 |   } | 
 |  | 
 |   public static TypeReference returnTypeFromTypeName(String typename) { | 
 |     return typename.equals("void") ? null : typeFromTypeName(typename); | 
 |   } | 
 |  | 
 |   public static TypeReference typeFromDescriptor(String descriptor) { | 
 |     switch (descriptor.charAt(0)) { | 
 |       case 'L': | 
 |         return classFromDescriptor(descriptor); | 
 |       case '[': | 
 |         return arrayFromDescriptor(descriptor); | 
 |       default: | 
 |         return primitiveFromDescriptor(descriptor); | 
 |     } | 
 |   } | 
 |  | 
 |   public static TypeReference typeFromTypeName(String typeName) { | 
 |     return typeFromDescriptor(DescriptorUtils.javaTypeToDescriptor(typeName)); | 
 |   } | 
 |  | 
 |   // Internal helper to convert Class<?> for primitive/array types too. | 
 |   private static TypeReference typeFromClass(Class<?> clazz) { | 
 |     return typeFromDescriptor(DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName())); | 
 |   } | 
 |  | 
 |   public static PrimitiveReference primitiveFromDescriptor(String descriptor) { | 
 |     return PrimitiveReference.fromDescriptor(descriptor); | 
 |   } | 
 |  | 
 |   /** Get a class reference from a JVM descriptor. */ | 
 |   public static ClassReference classFromDescriptor(String descriptor) { | 
 |     return ClassReference.fromDescriptor(descriptor); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Get a class reference from a JVM binary name. | 
 |    * | 
 |    * <p>See JVM SE 9 Specification, Section 4.2.1. Binary Class and Interface Names. | 
 |    */ | 
 |   public static ClassReference classFromBinaryName(String binaryName) { | 
 |     return classFromDescriptor(DescriptorUtils.getDescriptorFromClassBinaryName(binaryName)); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Get a class reference from a Java type name. | 
 |    * | 
 |    * <p>See Class.getTypeName() from Java 1.8. | 
 |    */ | 
 |   public static ClassReference classFromTypeName(String typeName) { | 
 |     return classFromDescriptor(DescriptorUtils.javaTypeToDescriptor(typeName)); | 
 |   } | 
 |  | 
 |   /** Get a class reference from a Java java.lang.Class object. */ | 
 |   public static ClassReference classFromClass(Class<?> clazz) { | 
 |     return classFromTypeName(clazz.getTypeName()); | 
 |   } | 
 |  | 
 |   /** Get an array reference from a JVM descriptor. */ | 
 |   public static ArrayReference arrayFromDescriptor(String descriptor) { | 
 |     return ArrayReference.fromDescriptor(descriptor); | 
 |   } | 
 |  | 
 |   /** Get an array reference from a base type and dimensions. */ | 
 |   public static ArrayReference array(TypeReference baseType, int dimensions) { | 
 |     return ArrayReference.fromBaseType(baseType, dimensions); | 
 |   } | 
 |  | 
 |   /** Get a method reference from its full reference specification. */ | 
 |   public static MethodReference method( | 
 |       ClassReference holderClass, | 
 |       String methodName, | 
 |       List<TypeReference> formalTypes, | 
 |       TypeReference returnType) { | 
 |     return new MethodReference( | 
 |         holderClass, methodName, ImmutableList.copyOf(formalTypes), returnType); | 
 |   } | 
 |  | 
 |   /** Get a method reference from a Java reflection method. */ | 
 |   public static MethodReference methodFromMethod(Method method) { | 
 |     String methodName = method.getName(); | 
 |     Class<?> holderClass = method.getDeclaringClass(); | 
 |     Class<?>[] parameterTypes = method.getParameterTypes(); | 
 |     Class<?> returnType = method.getReturnType(); | 
 |     ImmutableList.Builder<TypeReference> builder = ImmutableList.builder(); | 
 |     for (Class<?> parameterType : parameterTypes) { | 
 |       builder.add(typeFromClass(parameterType)); | 
 |     } | 
 |     return method( | 
 |         classFromClass(holderClass), | 
 |         methodName, | 
 |         builder.build(), | 
 |         returnType == Void.TYPE ? null : typeFromClass(returnType)); | 
 |   } | 
 |  | 
 |   /** Get a method reference from a Java reflection constructor. */ | 
 |   public static MethodReference methodFromMethod(Constructor<?> method) { | 
 |     Class<?> holderClass = method.getDeclaringClass(); | 
 |     Class<?>[] parameterTypes = method.getParameterTypes(); | 
 |     ImmutableList.Builder<TypeReference> builder = ImmutableList.builder(); | 
 |     for (Class<?> parameterType : parameterTypes) { | 
 |       builder.add(typeFromClass(parameterType)); | 
 |     } | 
 |     return method(classFromClass(holderClass), "<init>", builder.build(), null); | 
 |   } | 
 |  | 
 |   /** Get a method reference from class name, method name and signature. */ | 
 |   public static MethodReference methodFromDescriptor( | 
 |       String classDescriptor, String methodName, String methodDescriptor) { | 
 |     ImmutableList.Builder<TypeReference> builder = ImmutableList.builder(); | 
 |     for (String parameterTypeDescriptor : | 
 |         DescriptorUtils.getArgumentTypeDescriptors(methodDescriptor)) { | 
 |       builder.add(typeFromDescriptor(parameterTypeDescriptor)); | 
 |     } | 
 |     String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(methodDescriptor); | 
 |     return method( | 
 |         classFromDescriptor(classDescriptor), | 
 |         methodName, | 
 |         builder.build(), | 
 |         returnTypeDescriptor.equals("V") ? null : typeFromDescriptor(returnTypeDescriptor)); | 
 |   } | 
 |  | 
 |   public static MethodReference classConstructor(ClassReference type) { | 
 |     return method(type, "<clinit>", Collections.emptyList(), null); | 
 |   } | 
 |  | 
 |   /** Get a field reference from its full reference specification. */ | 
 |   public static FieldReference field( | 
 |       ClassReference holderClass, String fieldName, TypeReference fieldType) { | 
 |     return new FieldReference(holderClass, fieldName, fieldType); | 
 |   } | 
 |  | 
 |   /** Get a field reference from a Java reflection field. */ | 
 |   public static FieldReference fieldFromField(Field field) { | 
 |     Class<?> holderClass = field.getDeclaringClass(); | 
 |     String fieldName = field.getName(); | 
 |     Class<?> fieldType = field.getType(); | 
 |     return field(classFromClass(holderClass), fieldName, typeFromClass(fieldType)); | 
 |   } | 
 |  | 
 |   /** Create a package reference from a string */ | 
 |   public static PackageReference packageFromString(String packageName) { | 
 |     // Note, we rely on equality check for packages and do not canonicalize them. | 
 |     return new PackageReference(packageName); | 
 |   } | 
 |  | 
 |   /** Create a package from a java.lang.Package */ | 
 |   public static PackageReference packageFromPackage(Package pkg) { | 
 |     return new PackageReference(pkg.getName()); | 
 |   } | 
 | } |