use of io.micronaut.inject.annotation.AnnotationMetadataReference in project micronaut-core by micronaut-projects.
the class ExecutableMethodWriter method visitMethod.
/**
* Write the method.
*
* @param declaringType The declaring type
* @param methodElement The method element
*/
public void visitMethod(TypedElement declaringType, MethodElement methodElement) {
String methodName = methodElement.getName();
List<ParameterElement> argumentTypes = Arrays.asList(methodElement.getSuspendParameters());
Type declaringTypeObject = JavaModelUtils.getTypeReference(declaringType);
boolean hasArgs = !argumentTypes.isEmpty();
classWriter.visit(V1_8, ACC_SYNTHETIC, internalName, null, Type.getInternalName(AbstractExecutableMethod.class), null);
classWriter.visitAnnotation(TYPE_GENERATED.getDescriptor(), false);
// initialize and write the annotation metadata
if (!(annotationMetadata instanceof AnnotationMetadataReference)) {
writeAnnotationMetadataStaticInitializer(classWriter);
}
writeGetAnnotationMetadataMethod(classWriter);
MethodVisitor executorMethodConstructor;
GeneratorAdapter constructorWriter;
if (interceptedProxyBridgeMethodName != null) {
// Create default constructor call other one with 'false'
String descriptor = Type.getDescriptor(boolean.class);
classWriter.visitField(ACC_FINAL | ACC_PRIVATE, FIELD_INTERCEPTABLE, descriptor, null, null);
GeneratorAdapter defaultConstructorWriter = new GeneratorAdapter(startConstructor(classWriter), Opcodes.ACC_PUBLIC, CONSTRUCTOR_NAME, DESCRIPTOR_DEFAULT_CONSTRUCTOR);
String executorMethodConstructorDescriptor = getConstructorDescriptor(boolean.class);
executorMethodConstructor = startConstructor(classWriter, boolean.class);
constructorWriter = new GeneratorAdapter(executorMethodConstructor, Opcodes.ACC_PUBLIC, CONSTRUCTOR_NAME, executorMethodConstructorDescriptor);
defaultConstructorWriter.loadThis();
defaultConstructorWriter.push(false);
defaultConstructorWriter.visitMethodInsn(INVOKESPECIAL, internalName, CONSTRUCTOR_NAME, executorMethodConstructorDescriptor, false);
defaultConstructorWriter.visitInsn(RETURN);
defaultConstructorWriter.visitMaxs(DEFAULT_MAX_STACK, 1);
constructorWriter.loadThis();
constructorWriter.loadArg(0);
constructorWriter.putField(Type.getObjectType(internalName), FIELD_INTERCEPTABLE, Type.getType(boolean.class));
} else {
executorMethodConstructor = startConstructor(classWriter);
constructorWriter = new GeneratorAdapter(executorMethodConstructor, Opcodes.ACC_PUBLIC, CONSTRUCTOR_NAME, DESCRIPTOR_DEFAULT_CONSTRUCTOR);
}
// ALOAD 0
constructorWriter.loadThis();
// load 'this'
constructorWriter.loadThis();
// 1st argument: the declaring class
constructorWriter.push(declaringTypeObject);
// 2nd argument: the method name
constructorWriter.push(methodName);
// 3rd argument the generic return type
ClassElement genericReturnType = methodElement.getGenericReturnType();
if (genericReturnType.isPrimitive() && !genericReturnType.isArray()) {
String constantName = genericReturnType.getName().toUpperCase(Locale.ENGLISH);
// refer to constant for primitives
Type type = Type.getType(Argument.class);
constructorWriter.getStatic(type, constantName, type);
} else {
pushCreateArgument(declaringType.getName(), methodType, classWriter, constructorWriter, genericReturnType.getName(), genericReturnType, genericReturnType.getAnnotationMetadata(), genericReturnType.getTypeArguments(), new HashMap<>(), loadTypeMethods);
}
if (hasArgs) {
// 4th argument: the generic types
pushBuildArgumentsForMethod(methodType.getClassName(), methodType, classWriter, constructorWriter, argumentTypes, new HashMap<>(), loadTypeMethods);
for (ParameterElement pe : argumentTypes) {
DefaultAnnotationMetadata.contributeDefaults(this.annotationMetadata, pe.getAnnotationMetadata());
DefaultAnnotationMetadata.contributeRepeatable(this.annotationMetadata, pe.getGenericType());
}
// now invoke super(..) if no arg constructor
invokeConstructor(executorMethodConstructor, AbstractExecutableMethod.class, Class.class, String.class, Argument.class, Argument[].class);
} else {
invokeConstructor(executorMethodConstructor, AbstractExecutableMethod.class, Class.class, String.class, Argument.class);
}
constructorWriter.visitInsn(RETURN);
constructorWriter.visitMaxs(DEFAULT_MAX_STACK, 1);
// add isAbstract method
GeneratorAdapter isAbstractMethod = new GeneratorAdapter(classWriter.visitMethod(ACC_PUBLIC | ACC_FINAL, METHOD_IS_ABSTRACT.getName(), METHOD_IS_ABSTRACT.getDescriptor(), null, null), ACC_PUBLIC, METHOD_IS_ABSTRACT.getName(), METHOD_IS_ABSTRACT.getDescriptor());
isAbstractMethod.push(isAbstract());
isAbstractMethod.returnValue();
isAbstractMethod.visitMaxs(1, 1);
isAbstractMethod.endMethod();
// add isSuspend method
GeneratorAdapter isSuspendMethod = new GeneratorAdapter(classWriter.visitMethod(ACC_PUBLIC | ACC_FINAL, METHOD_IS_SUSPEND.getName(), METHOD_IS_SUSPEND.getDescriptor(), null, null), ACC_PUBLIC, METHOD_IS_SUSPEND.getName(), METHOD_IS_SUSPEND.getDescriptor());
isSuspendMethod.push(isSuspend());
isSuspendMethod.returnValue();
isSuspendMethod.visitMaxs(1, 1);
isSuspendMethod.endMethod();
// invoke the methods with the passed arguments
String invokeDescriptor = METHOD_INVOKE_INTERNAL.getDescriptor();
String invokeInternalName = METHOD_INVOKE_INTERNAL.getName();
GeneratorAdapter invokeMethod = new GeneratorAdapter(classWriter.visitMethod(Opcodes.ACC_PUBLIC, invokeInternalName, invokeDescriptor, null, null), ACC_PUBLIC, invokeInternalName, invokeDescriptor);
ClassElement returnType = methodElement.isSuspend() ? ClassElement.of(Object.class) : methodElement.getReturnType();
buildInvokeMethod(declaringTypeObject, methodName, returnType, argumentTypes, invokeMethod);
buildResolveTargetMethod(methodName, declaringTypeObject, hasArgs, argumentTypes);
for (GeneratorAdapter method : loadTypeMethods.values()) {
method.visitMaxs(3, 1);
method.visitEnd();
}
}
use of io.micronaut.inject.annotation.AnnotationMetadataReference in project micronaut-core by micronaut-projects.
the class ExecutableMethodsDefinitionWriter method pushNewMethodReference.
private void pushNewMethodReference(ClassWriter classWriter, GeneratorAdapter staticInit, TypedElement declaringType, MethodElement methodElement) {
staticInit.newInstance(Type.getType(AbstractExecutableMethodsDefinition.MethodReference.class));
staticInit.dup();
// 1: declaringType
Type typeReference = JavaModelUtils.getTypeReference(declaringType.getType());
staticInit.push(typeReference);
// 2: annotationMetadata
AnnotationMetadata annotationMetadata = methodElement.getAnnotationMetadata();
if (annotationMetadata instanceof AnnotationMetadataHierarchy) {
annotationMetadata = new AnnotationMetadataHierarchy(new AnnotationMetadataReference(beanDefinitionReferenceClassName, annotationMetadata), annotationMetadata.getDeclaredMetadata());
}
pushAnnotationMetadata(classWriter, staticInit, annotationMetadata);
// 3: methodName
staticInit.push(methodElement.getName());
// 4: return argument
ClassElement genericReturnType = methodElement.getGenericReturnType();
pushArgument(thisType, classWriter, staticInit, declaringType.getName(), genericReturnType, defaultsStorage, loadTypeMethods);
// 5: arguments
ParameterElement[] parameters = methodElement.getSuspendParameters();
if (parameters.length == 0) {
staticInit.visitInsn(ACONST_NULL);
} else {
pushBuildArgumentsForMethod(typeReference.getClassName(), thisType, classWriter, staticInit, Arrays.asList(parameters), defaultsStorage, loadTypeMethods);
}
// 6: isAbstract
staticInit.push(methodElement.isAbstract());
// 7: isSuspend
staticInit.push(methodElement.isSuspend());
invokeConstructor(staticInit, AbstractExecutableMethodsDefinition.MethodReference.class, Class.class, AnnotationMetadata.class, String.class, Argument.class, Argument[].class, boolean.class, boolean.class);
}
use of io.micronaut.inject.annotation.AnnotationMetadataReference in project micronaut-core by micronaut-projects.
the class AbstractAnnotationMetadataWriter method writeGetAnnotationMetadataMethod.
/**
* @param classWriter The {@link ClassWriter}
*/
protected void writeGetAnnotationMetadataMethod(ClassWriter classWriter) {
GeneratorAdapter annotationMetadataMethod = beginAnnotationMetadataMethod(classWriter);
annotationMetadataMethod.loadThis();
// then we setup an annotation metadata reference from the method to the class (or inherited method) metadata
if (annotationMetadata == AnnotationMetadata.EMPTY_METADATA) {
annotationMetadataMethod.getStatic(Type.getType(AnnotationMetadata.class), "EMPTY_METADATA", Type.getType(AnnotationMetadata.class));
} else if (annotationMetadata instanceof AnnotationMetadataReference) {
AnnotationMetadataReference reference = (AnnotationMetadataReference) annotationMetadata;
String className = reference.getClassName();
annotationMetadataMethod.getStatic(getTypeReferenceForName(className), AbstractAnnotationMetadataWriter.FIELD_ANNOTATION_METADATA, Type.getType(AnnotationMetadata.class));
} else {
annotationMetadataMethod.getStatic(targetClassType, AbstractAnnotationMetadataWriter.FIELD_ANNOTATION_METADATA, Type.getType(AnnotationMetadata.class));
}
annotationMetadataMethod.returnValue();
annotationMetadataMethod.visitMaxs(1, 1);
annotationMetadataMethod.visitEnd();
}
use of io.micronaut.inject.annotation.AnnotationMetadataReference in project micronaut-core by micronaut-projects.
the class BeanDefinitionReferenceWriter method generateClassBytes.
private ClassWriter generateClassBytes() {
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
Type superType = Type.getType(AbstractInitializableBeanDefinitionReference.class);
String[] interfaceInternalNames;
if (interceptedType != null) {
interfaceInternalNames = new String[] { Type.getType(AdvisedBeanType.class).getInternalName() };
} else {
interfaceInternalNames = StringUtils.EMPTY_STRING_ARRAY;
}
startService(classWriter, BeanDefinitionReference.class.getName(), beanDefinitionClassInternalName, superType, interfaceInternalNames);
Type beanDefinitionType = getTypeReferenceForName(beanDefinitionName);
writeAnnotationMetadataStaticInitializer(classWriter);
GeneratorAdapter cv = startConstructor(classWriter);
cv.loadThis();
// 1: beanTypeName
cv.push(beanTypeName);
// 2: beanDefinitionTypeName
cv.push(beanDefinitionName);
// 3: annotationMetadata
if (annotationMetadata == AnnotationMetadata.EMPTY_METADATA || annotationMetadata.isEmpty()) {
cv.getStatic(Type.getType(AnnotationMetadata.class), "EMPTY_METADATA", Type.getType(AnnotationMetadata.class));
} else if (annotationMetadata instanceof AnnotationMetadataReference) {
AnnotationMetadataReference reference = (AnnotationMetadataReference) annotationMetadata;
String className = reference.getClassName();
cv.getStatic(getTypeReferenceForName(className), AbstractAnnotationMetadataWriter.FIELD_ANNOTATION_METADATA, Type.getType(AnnotationMetadata.class));
} else {
cv.getStatic(targetClassType, AbstractAnnotationMetadataWriter.FIELD_ANNOTATION_METADATA, Type.getType(AnnotationMetadata.class));
}
// 4: isPrimary
cv.push(annotationMetadata.hasDeclaredStereotype(Primary.class));
// 5: isContextScope
cv.push(contextScope);
// 6: isConditional
cv.push(annotationMetadata.hasStereotype(Requires.class));
// 7: isContainerType
cv.push(DefaultArgument.CONTAINER_TYPES.stream().anyMatch(clazz -> clazz.getName().equals(beanTypeName)));
// 8: isSingleton
cv.push(annotationMetadata.hasDeclaredStereotype(AnnotationUtil.SINGLETON) || (!annotationMetadata.hasDeclaredStereotype(AnnotationUtil.SCOPE) && annotationMetadata.hasDeclaredStereotype(DefaultScope.class) && annotationMetadata.stringValue(DefaultScope.class).map(t -> t.equals(Singleton.class.getName()) || t.equals(AnnotationUtil.SINGLETON)).orElse(false)));
// 9: isConfigurationProperties
cv.push(annotationMetadata.hasDeclaredStereotype(ConfigurationReader.class));
// 10: hasExposedTypes
cv.push(annotationMetadata.hasDeclaredAnnotation(Bean.class) && annotationMetadata.stringValues(Bean.class, "typed").length > 0);
// 10: requiresMethodProcessing
cv.push(requiresMethodProcessing);
// (...)
cv.invokeConstructor(Type.getType(AbstractInitializableBeanDefinitionReference.class), BEAN_DEFINITION_REF_CLASS_CONSTRUCTOR);
// RETURN
cv.visitInsn(RETURN);
// MAXSTACK = 2
// MAXLOCALS = 1
cv.visitMaxs(2, 1);
// start method: BeanDefinition load()
GeneratorAdapter loadMethod = startPublicMethodZeroArgs(classWriter, BeanDefinition.class, "load");
// return new BeanDefinition()
pushNewInstance(loadMethod, beanDefinitionType);
// RETURN
loadMethod.returnValue();
loadMethod.visitMaxs(2, 1);
// start method: Class getBeanDefinitionType()
GeneratorAdapter getBeanDefinitionType = startPublicMethodZeroArgs(classWriter, Class.class, "getBeanDefinitionType");
getBeanDefinitionType.push(beanDefinitionType);
getBeanDefinitionType.returnValue();
getBeanDefinitionType.visitMaxs(2, 1);
// start method: Class getBeanType()
GeneratorAdapter getBeanType = startPublicMethodZeroArgs(classWriter, Class.class, "getBeanType");
getBeanType.push(providedType);
getBeanType.returnValue();
getBeanType.visitMaxs(2, 1);
if (interceptedType != null) {
super.implementInterceptedTypeMethod(interceptedType, classWriter);
}
for (GeneratorAdapter generatorAdapter : loadTypeMethods.values()) {
generatorAdapter.visitMaxs(3, 1);
}
return classWriter;
}
use of io.micronaut.inject.annotation.AnnotationMetadataReference in project micronaut-core by micronaut-projects.
the class AbstractAnnotationMetadataWriter method writeAnnotationMetadataStaticInitializer.
/**
* @param classWriter The {@link ClassWriter}
* @param defaults The annotation defaults
*/
protected void writeAnnotationMetadataStaticInitializer(ClassWriter classWriter, Map<String, Integer> defaults) {
if (!(annotationMetadata instanceof AnnotationMetadataReference)) {
// write the static initializers for the annotation metadata
GeneratorAdapter staticInit = visitStaticInitializer(classWriter);
staticInit.visitCode();
if (writeAnnotationDefault && annotationMetadata instanceof DefaultAnnotationMetadata) {
DefaultAnnotationMetadata dam = (DefaultAnnotationMetadata) annotationMetadata;
AnnotationMetadataWriter.writeAnnotationDefaults(targetClassType, classWriter, staticInit, dam, defaults, loadTypeMethods);
}
staticInit.visitLabel(new Label());
initializeAnnotationMetadata(staticInit, classWriter, defaults);
staticInit.visitInsn(RETURN);
staticInit.visitMaxs(1, 1);
staticInit.visitEnd();
}
}
Aggregations