Search in sources :

Example 11 with ClassElement

use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method resolveArgumentGenericType.

private boolean resolveArgumentGenericType(GeneratorAdapter visitor, ClassElement type) {
    if (type.isArray()) {
        if (!type.getTypeArguments().isEmpty() && isInternalGenericTypeContainer(type.fromArray())) {
            // skip for arrays of BeanRegistration
            return false;
        }
        final ClassElement componentType = type.fromArray();
        if (componentType.isPrimitive()) {
            visitor.getStatic(TYPE_ARGUMENT, componentType.getName().toUpperCase(Locale.ENGLISH), TYPE_ARGUMENT);
        } else {
            visitor.push(JavaModelUtils.getTypeReference(componentType));
            visitor.push((String) null);
            invokeInterfaceStaticMethod(visitor, Argument.class, METHOD_CREATE_ARGUMENT_SIMPLE);
        }
        return true;
    } else if (type.getTypeArguments().isEmpty()) {
        visitor.visitInsn(ACONST_NULL);
        return true;
    }
    return false;
}
Also used : ClassElement(io.micronaut.inject.ast.ClassElement)

Example 12 with ClassElement

use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method visitMethodInjectionPointInternal.

private void visitMethodInjectionPointInternal(MethodVisitData methodVisitData, GeneratorAdapter injectMethodVisitor, int injectInstanceIndex) {
    MethodElement methodElement = methodVisitData.getMethodElement();
    final AnnotationMetadata annotationMetadata = methodElement.getAnnotationMetadata();
    final List<ParameterElement> argumentTypes = Arrays.asList(methodElement.getParameters());
    applyDefaultNamedToParameters(argumentTypes);
    final TypedElement declaringType = methodVisitData.beanType;
    final String methodName = methodElement.getName();
    final boolean requiresReflection = methodVisitData.requiresReflection;
    final ClassElement returnType = methodElement.getReturnType();
    DefaultAnnotationMetadata.contributeDefaults(this.annotationMetadata, annotationMetadata);
    DefaultAnnotationMetadata.contributeRepeatable(this.annotationMetadata, returnType);
    boolean hasArguments = methodElement.hasParameters();
    int argCount = hasArguments ? argumentTypes.size() : 0;
    Type declaringTypeRef = JavaModelUtils.getTypeReference(declaringType);
    boolean hasInjectScope = false;
    for (ParameterElement value : argumentTypes) {
        DefaultAnnotationMetadata.contributeDefaults(this.annotationMetadata, value.getAnnotationMetadata());
        DefaultAnnotationMetadata.contributeRepeatable(this.annotationMetadata, value.getGenericType());
        if (value.hasDeclaredAnnotation(InjectScope.class)) {
            hasInjectScope = true;
        }
    }
    if (!requiresReflection) {
        // if the method doesn't require reflection then invoke it directly
        // invoke the method on this injected instance
        injectMethodVisitor.loadLocal(injectInstanceIndex, beanType);
        String methodDescriptor;
        if (hasArguments) {
            methodDescriptor = getMethodDescriptor(returnType, argumentTypes);
            Iterator<ParameterElement> argIterator = argumentTypes.iterator();
            for (int i = 0; i < argCount; i++) {
                ParameterElement entry = argIterator.next();
                pushMethodParameterValue(injectMethodVisitor, i, entry);
            }
        } else {
            methodDescriptor = getMethodDescriptor(returnType, Collections.emptyList());
        }
        injectMethodVisitor.visitMethodInsn(isInterface ? INVOKEINTERFACE : INVOKEVIRTUAL, declaringTypeRef.getInternalName(), methodName, methodDescriptor, isInterface);
        if (isConfigurationProperties && returnType != PrimitiveElement.VOID) {
            injectMethodVisitor.pop();
        }
    } else {
        injectMethodVisitor.loadThis();
        injectMethodVisitor.loadArg(0);
        injectMethodVisitor.loadArg(1);
        injectMethodVisitor.push(currentMethodIndex);
        injectMethodVisitor.loadLocal(injectInstanceLocalVarIndex, beanType);
        if (hasArguments) {
            pushNewArray(injectMethodVisitor, Object.class, argumentTypes.size());
            Iterator<ParameterElement> argIterator = argumentTypes.iterator();
            for (int i = 0; i < argCount; i++) {
                int finalI = i;
                pushStoreInArray(injectMethodVisitor, i, argumentTypes.size(), () -> {
                    ParameterElement entry = argIterator.next();
                    pushMethodParameterValue(injectMethodVisitor, finalI, entry);
                    pushBoxPrimitiveIfNecessary(entry.getType(), injectMethodVisitor);
                });
            }
        } else {
            pushNewArray(injectMethodVisitor, Object.class, 0);
        }
        injectMethodVisitor.invokeVirtual(superType, INVOKE_WITH_REFLECTION_METHOD);
    }
    destroyInjectScopeBeansIfNecessary(injectMethodVisitor, hasInjectScope);
}
Also used : Type(org.objectweb.asm.Type) AdvisedBeanType(io.micronaut.inject.AdvisedBeanType) TypedElement(io.micronaut.inject.ast.TypedElement) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) AbstractConstructorInjectionPoint(io.micronaut.context.AbstractConstructorInjectionPoint) ConstructorInjectionPoint(io.micronaut.inject.ConstructorInjectionPoint)

Example 13 with ClassElement

use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method defineBuilderMethod.

private void defineBuilderMethod(boolean isParametrized) {
    if (isParametrized) {
        this.isParametrized = true;
    }
    String methodDescriptor;
    String methodSignature;
    final ClassElement beanDefinitionParam = ClassElement.of(BeanDefinition.class, AnnotationMetadata.EMPTY_METADATA, Collections.singletonMap("T", beanTypeElement));
    if (isParametrized) {
        methodDescriptor = getMethodDescriptor(Object.class.getName(), BeanResolutionContext.class.getName(), BeanContext.class.getName(), BeanDefinition.class.getName(), Map.class.getName());
        methodSignature = getMethodSignature(getTypeDescriptor(beanTypeElement), getTypeDescriptor(BeanResolutionContext.class.getName()), getTypeDescriptor(BeanContext.class.getName()), getTypeDescriptor(beanDefinitionParam), getTypeDescriptor(Map.class.getName()));
    } else {
        methodDescriptor = getMethodDescriptor(Object.class.getName(), BeanResolutionContext.class.getName(), BeanContext.class.getName(), BeanDefinition.class.getName());
        methodSignature = getMethodSignature(getTypeDescriptor(beanTypeElement), getTypeDescriptor(BeanResolutionContext.class.getName()), getTypeDescriptor(BeanContext.class.getName()), getTypeDescriptor(beanDefinitionParam));
    }
    String methodName = isParametrized ? "doBuild" : "build";
    this.buildMethodVisitor = new GeneratorAdapter(classWriter.visitMethod(ACC_PUBLIC, methodName, methodDescriptor, methodSignature, null), ACC_PUBLIC, methodName, methodDescriptor);
}
Also used : DefaultBeanContext(io.micronaut.context.DefaultBeanContext) BeanContext(io.micronaut.context.BeanContext) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ClassElement(io.micronaut.inject.ast.ClassElement) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) BeanResolutionContext(io.micronaut.context.BeanResolutionContext)

Example 14 with ClassElement

use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method pushConstructorArgument.

private void pushConstructorArgument(GeneratorAdapter buildMethodVisitor, String argumentName, ParameterElement argumentType, AnnotationMetadata annotationMetadata, int index) {
    if (isAnnotatedWithParameter(annotationMetadata) && isParametrized) {
        // load the args
        buildMethodVisitor.loadArg(3);
        // the argument name
        buildMethodVisitor.push(argumentName);
        buildMethodVisitor.invokeInterface(Type.getType(Map.class), org.objectweb.asm.commons.Method.getMethod(ReflectionUtils.getRequiredMethod(Map.class, "get", Object.class)));
        pushCastToType(buildMethodVisitor, argumentType);
    } else if (argumentType.getGenericType().isAssignable(BeanContext.class)) {
        buildMethodVisitor.loadArg(1);
    } else if (argumentType.getGenericType().isAssignable(BeanResolutionContext.class)) {
        buildMethodVisitor.loadArg(0);
    } else {
        boolean isArray = false;
        boolean hasGenericType = false;
        Method methodToInvoke;
        final ClassElement genericType = argumentType.getGenericType();
        if (isValueType(annotationMetadata) && !isInnerType(genericType)) {
            Optional<String> property = argumentType.stringValue(Property.class, "name");
            if (property.isPresent()) {
                pushInvokeGetPropertyValueForConstructor(buildMethodVisitor, index, argumentType, property.get());
            } else {
                Optional<String> valueValue = argumentType.stringValue(Value.class);
                if (valueValue.isPresent()) {
                    pushInvokeGetPropertyPlaceholderValueForConstructor(buildMethodVisitor, index, argumentType, valueValue.get());
                }
            }
            return;
        } else {
            isArray = genericType.isArray();
            if (genericType.isAssignable(Collection.class) || isArray) {
                hasGenericType = true;
                ClassElement typeArgument = genericType.isArray() ? genericType.fromArray() : genericType.getFirstTypeArgument().orElse(null);
                if (typeArgument != null && !typeArgument.isPrimitive()) {
                    if (typeArgument.isAssignable(BeanRegistration.class)) {
                        methodToInvoke = GET_BEAN_REGISTRATIONS_FOR_CONSTRUCTOR_ARGUMENT;
                    } else {
                        methodToInvoke = GET_BEANS_OF_TYPE_FOR_CONSTRUCTOR_ARGUMENT;
                    }
                } else {
                    methodToInvoke = GET_BEAN_FOR_CONSTRUCTOR_ARGUMENT;
                    hasGenericType = false;
                }
            } else if (genericType.isAssignable(Stream.class)) {
                hasGenericType = true;
                methodToInvoke = GET_STREAM_OF_TYPE_FOR_CONSTRUCTOR_ARGUMENT;
            } else if (genericType.isAssignable(Optional.class)) {
                hasGenericType = true;
                methodToInvoke = FIND_BEAN_FOR_CONSTRUCTOR_ARGUMENT;
            } else if (genericType.isAssignable(BeanRegistration.class)) {
                hasGenericType = true;
                methodToInvoke = GET_BEAN_REGISTRATION_FOR_CONSTRUCTOR_ARGUMENT;
            } else {
                methodToInvoke = GET_BEAN_FOR_CONSTRUCTOR_ARGUMENT;
            }
        }
        // Load this for method call
        buildMethodVisitor.loadThis();
        // load the first two arguments of the method (the BeanResolutionContext and the BeanContext) to be passed to the method
        buildMethodVisitor.loadArg(0);
        buildMethodVisitor.loadArg(1);
        // pass the index of the method as the third argument
        buildMethodVisitor.push(index);
        if (hasGenericType) {
            resolveConstructorArgumentGenericType(buildMethodVisitor, argumentType.getGenericType(), index);
        }
        // push qualifier
        pushQualifier(buildMethodVisitor, argumentType, () -> {
            resolveConstructorArgument(buildMethodVisitor, index);
        });
        // invoke method
        pushInvokeMethodOnSuperClass(buildMethodVisitor, methodToInvoke);
        if (isArray && hasGenericType) {
            convertToArray(argumentType.getGenericType().fromArray(), buildMethodVisitor);
        }
        pushCastToType(buildMethodVisitor, argumentType);
    }
}
Also used : DefaultBeanContext(io.micronaut.context.DefaultBeanContext) BeanContext(io.micronaut.context.BeanContext) BeanRegistration(io.micronaut.context.BeanRegistration) Collection(java.util.Collection) ClassElement(io.micronaut.inject.ast.ClassElement) Stream(java.util.stream.Stream) OutputStream(java.io.OutputStream) AbstractExecutableMethod(io.micronaut.context.AbstractExecutableMethod) Method(java.lang.reflect.Method) ExecutableMethod(io.micronaut.inject.ExecutableMethod) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap)

Example 15 with ClassElement

use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.

the class BeanDefinitionWriter method populateBeanTypes.

private void populateBeanTypes(Set<String> processedTypes, Set<ClassElement> beanTypes, ClassElement superType, Collection<ClassElement> interfaces) {
    for (ClassElement anInterface : interfaces) {
        final String n = anInterface.getName();
        if (!processedTypes.contains(n)) {
            processedTypes.add(n);
            beanTypes.add(anInterface);
            populateBeanTypes(processedTypes, beanTypes, null, anInterface.getInterfaces());
        }
    }
    if (superType != null) {
        final String n = superType.getName();
        if (!processedTypes.contains(n)) {
            processedTypes.add(n);
            beanTypes.add(superType);
            final ClassElement next = superType.getSuperType().orElse(null);
            populateBeanTypes(processedTypes, beanTypes, next, superType.getInterfaces());
        }
    }
}
Also used : ClassElement(io.micronaut.inject.ast.ClassElement)

Aggregations

ClassElement (io.micronaut.inject.ast.ClassElement)55 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)15 NonNull (io.micronaut.core.annotation.NonNull)15 ParameterElement (io.micronaut.inject.ast.ParameterElement)14 Map (java.util.Map)13 MethodElement (io.micronaut.inject.ast.MethodElement)12 Type (org.objectweb.asm.Type)12 LinkedHashMap (java.util.LinkedHashMap)10 DefaultAnnotationMetadata (io.micronaut.inject.annotation.DefaultAnnotationMetadata)9 ArrayList (java.util.ArrayList)9 List (java.util.List)8 HashMap (java.util.HashMap)7 Internal (io.micronaut.core.annotation.Internal)6 Argument (io.micronaut.core.type.Argument)6 AnnotationMetadataHierarchy (io.micronaut.inject.annotation.AnnotationMetadataHierarchy)6 MutableAnnotationMetadata (io.micronaut.inject.annotation.MutableAnnotationMetadata)6 Collections (java.util.Collections)6 Set (java.util.Set)6 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)6 NameUtils (io.micronaut.core.naming.NameUtils)5