Search in sources :

Example 1 with AnnotationMetadataReference

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();
    }
}
Also used : Argument(io.micronaut.core.type.Argument) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) ClassElement(io.micronaut.inject.ast.ClassElement) MethodVisitor(org.objectweb.asm.MethodVisitor) Type(org.objectweb.asm.Type) AbstractExecutableMethod(io.micronaut.context.AbstractExecutableMethod) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ParameterElement(io.micronaut.inject.ast.ParameterElement)

Example 2 with AnnotationMetadataReference

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);
}
Also used : Type(org.objectweb.asm.Type) Argument(io.micronaut.core.type.Argument) AbstractExecutableMethodsDefinition(io.micronaut.context.AbstractExecutableMethodsDefinition) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) ClassElement(io.micronaut.inject.ast.ClassElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) AnnotationMetadataHierarchy(io.micronaut.inject.annotation.AnnotationMetadataHierarchy) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

Example 3 with AnnotationMetadataReference

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();
}
Also used : GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

Example 4 with AnnotationMetadataReference

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;
}
Also used : ClassWriter(org.objectweb.asm.ClassWriter) OutputStream(java.io.OutputStream) DefaultArgument(io.micronaut.core.type.DefaultArgument) Singleton(jakarta.inject.Singleton) AdvisedBeanType(io.micronaut.inject.AdvisedBeanType) IOException(java.io.IOException) io.micronaut.context.annotation(io.micronaut.context.annotation) Internal(io.micronaut.core.annotation.Internal) Type(org.objectweb.asm.Type) StringUtils(io.micronaut.core.util.StringUtils) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) AnnotationUtil(io.micronaut.core.annotation.AnnotationUtil) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) BeanDefinition(io.micronaut.inject.BeanDefinition) BeanDefinitionReference(io.micronaut.inject.BeanDefinitionReference) AbstractInitializableBeanDefinitionReference(io.micronaut.context.AbstractInitializableBeanDefinitionReference) AbstractInitializableBeanDefinitionReference(io.micronaut.context.AbstractInitializableBeanDefinitionReference) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) ClassWriter(org.objectweb.asm.ClassWriter) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) AdvisedBeanType(io.micronaut.inject.AdvisedBeanType) Type(org.objectweb.asm.Type) BeanDefinitionReference(io.micronaut.inject.BeanDefinitionReference) AbstractInitializableBeanDefinitionReference(io.micronaut.context.AbstractInitializableBeanDefinitionReference) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter)

Example 5 with AnnotationMetadataReference

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();
    }
}
Also used : Label(org.objectweb.asm.Label) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata)

Aggregations

AnnotationMetadataReference (io.micronaut.inject.annotation.AnnotationMetadataReference)5 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)4 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)3 DefaultAnnotationMetadata (io.micronaut.inject.annotation.DefaultAnnotationMetadata)3 Type (org.objectweb.asm.Type)3 Argument (io.micronaut.core.type.Argument)2 ClassElement (io.micronaut.inject.ast.ClassElement)2 ParameterElement (io.micronaut.inject.ast.ParameterElement)2 AbstractExecutableMethod (io.micronaut.context.AbstractExecutableMethod)1 AbstractExecutableMethodsDefinition (io.micronaut.context.AbstractExecutableMethodsDefinition)1 AbstractInitializableBeanDefinitionReference (io.micronaut.context.AbstractInitializableBeanDefinitionReference)1 io.micronaut.context.annotation (io.micronaut.context.annotation)1 AnnotationUtil (io.micronaut.core.annotation.AnnotationUtil)1 Internal (io.micronaut.core.annotation.Internal)1 DefaultArgument (io.micronaut.core.type.DefaultArgument)1 StringUtils (io.micronaut.core.util.StringUtils)1 AdvisedBeanType (io.micronaut.inject.AdvisedBeanType)1 BeanDefinition (io.micronaut.inject.BeanDefinition)1 BeanDefinitionReference (io.micronaut.inject.BeanDefinitionReference)1 AnnotationMetadataHierarchy (io.micronaut.inject.annotation.AnnotationMetadataHierarchy)1