Top Description Constructors Methods
com.google.auto.value.processor

pack-priv final Class ForwardingClassGenerator

extends Object
Class Inheritance
Static Imports
com.google.auto.common.MoreTypes.asArray, .MoreTypes.asTypeElement, java.util.stream.Collectors.joining, org.objectweb.asm.ClassWriter.COMPUTE_MAXS, .Opcodes.ACC_FINAL, .Opcodes.ACC_STATIC, .Opcodes.ACC_SUPER, .Opcodes.ALOAD, .Opcodes.ARETURN, .Opcodes.DLOAD, .Opcodes.DUP, .Opcodes.FLOAD, .Opcodes.ILOAD, .Opcodes.INVOKESPECIAL, .Opcodes.LLOAD, .Opcodes.NEW, .Opcodes.V1_7

Generates a class that invokes the constructor of another class.

The point here is that the constructor might be synthetic, in which case it can't be called directly from Java source code. Say we want to call the constructor ConstructMe(int, String, long) with parameters 1, "2", 3L. If the constructor is synthetic, then Java source code can't just do new ConstructMe(1, "2", 3L). So this class allows you to generate a class file, say Forwarder, that is basically what you would get if you could compile this:

final class Forwarder {
  private Forwarder() {}

  static ConstructMe of(int a, String b, long c) {
    return new ConstructMe(a, b, c);
  }
}

Because the class file is assembled directly, rather than being produced by the Java compiler, it can call the synthetic constructor. Then regular Java source code can do Forwarder.of(1, "2", 3L) to call the constructor.

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
private static String
internalName(String className)

private static String
internalName(javax.lang.model.element.TypeElement typeElement)

Given a class like foo.bar.Outer.Inner, produces a string like "foo/bar/Outer$Inner", which is the way the class is referenced in the JVM.

private static int
loadInstruction(javax.lang.model.type.TypeMirror type)

The bytecode instruction that copies a parameter of the given type onto the JVM stack.

private static int
localSize(javax.lang.model.type.TypeMirror type)

The size in the local variable array of a value of the given type.

pack-priv static byte[]

Returns:

a byte array making up the new class file
makeConstructorForwarder
(String
the fully-qualified name of the class to generate
forwardingClassName
,
javax.lang.model.type.TypeMirror
the type whose constructor will be invoked (ConstructMe in the example above)
classToConstruct
,
ImmutableList<javax.lang.model.type.TypeMirror>
the erased types of the constructor parameters, which will also be the types of the generated of method. We require the types to be erased so as not to require an instance of the Types interface to erase them here. Having to deal with generics would complicate things unnecessarily.
constructorParameters
)

Assembles a class with a static method of that calls the constructor of another class with the same parameters.

private static String
signatureEncoding(javax.lang.model.type.TypeMirror type)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Constructor Detail

ForwardingClassGeneratorback to summary
private ForwardingClassGenerator()

Method Detail

internalNameback to summary
private static String internalName(String className)
internalNameback to summary
private static String internalName(javax.lang.model.element.TypeElement typeElement)

Given a class like foo.bar.Outer.Inner, produces a string like "foo/bar/Outer$Inner", which is the way the class is referenced in the JVM.

loadInstructionback to summary
private static int loadInstruction(javax.lang.model.type.TypeMirror type)

The bytecode instruction that copies a parameter of the given type onto the JVM stack.

localSizeback to summary
private static int localSize(javax.lang.model.type.TypeMirror type)

The size in the local variable array of a value of the given type. A quirk of the JVM means that long and double variables each take up two consecutive slots in the local variable array. (The first n local variables are the parameters, so we need to know their sizes when iterating over them.)

makeConstructorForwarderback to summary
pack-priv static byte[] makeConstructorForwarder(String forwardingClassName, javax.lang.model.type.TypeMirror classToConstruct, ImmutableList<javax.lang.model.type.TypeMirror> constructorParameters)

Assembles a class with a static method of that calls the constructor of another class with the same parameters.

It would be simpler if we could just pass in an ExecutableElement representing the constructor, but if it is synthetic then it won't be visible to the javax.lang.model APIs. So we have to pass the constructed type and the constructor parameter types separately.

Parameters
forwardingClassName:String

the fully-qualified name of the class to generate

classToConstruct:javax.lang.model.type.TypeMirror

the type whose constructor will be invoked (ConstructMe in the example above)

constructorParameters:ImmutableList<javax.lang.model.type.TypeMirror>

the erased types of the constructor parameters, which will also be the types of the generated of method. We require the types to be erased so as not to require an instance of the Types interface to erase them here. Having to deal with generics would complicate things unnecessarily.

Returns:byte[]

a byte array making up the new class file

signatureEncodingback to summary
private static String signatureEncoding(javax.lang.model.type.TypeMirror type)