Search in sources :

Example 1 with ParameterElement

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

the class ClientTypesRule method validate.

@Override
public RouteValidationResult validate(List<UriMatchTemplate> templates, ParameterElement[] parameters, MethodElement method) {
    String[] errors = new String[] {};
    if (method.hasAnnotation(Client.class)) {
        final Stream.Builder<ClassElement> builder = Stream.<ClassElement>builder().add(method.getReturnType());
        for (ParameterElement param : method.getParameters()) {
            builder.add(param.getType());
        }
        errors = builder.build().filter(type -> {
            for (Class<?> clazz : SERVER_TYPES) {
                if (type.isAssignable(clazz)) {
                    return true;
                }
            }
            return false;
        }).map(type -> "The type [" + type + "] must not be used in declarative client methods. The type is specific to server based usages.").toArray(String[]::new);
    }
    return new RouteValidationResult(errors);
}
Also used : List(java.util.List) RouteValidationResult(io.micronaut.validation.routes.RouteValidationResult) Stream(java.util.stream.Stream) MultipartBody(io.micronaut.http.server.multipart.MultipartBody) StreamedFile(io.micronaut.http.server.types.files.StreamedFile) MethodElement(io.micronaut.inject.ast.MethodElement) UriMatchTemplate(io.micronaut.http.uri.UriMatchTemplate) ClassElement(io.micronaut.inject.ast.ClassElement) Client(io.micronaut.http.client.annotation.Client) SystemFile(io.micronaut.http.server.types.files.SystemFile) ParameterElement(io.micronaut.inject.ast.ParameterElement) Stream(java.util.stream.Stream) ClassElement(io.micronaut.inject.ast.ClassElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) RouteValidationResult(io.micronaut.validation.routes.RouteValidationResult)

Example 2 with ParameterElement

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

the class BeanIntrospectionWriter method invokeBeanConstructor.

private void invokeBeanConstructor(GeneratorAdapter writer, MethodElement constructor, BiConsumer<GeneratorAdapter, MethodElement> argumentsPusher) {
    boolean isConstructor = constructor instanceof ConstructorElement;
    boolean isCompanion = constructor != defaultConstructor && constructor.getDeclaringType().getSimpleName().endsWith("$Companion");
    List<ParameterElement> constructorArguments = Arrays.asList(constructor.getParameters());
    Collection<Type> argumentTypes = constructorArguments.stream().map(pe -> JavaModelUtils.getTypeReference(pe.getType())).collect(Collectors.toList());
    if (isConstructor) {
        writer.newInstance(beanType);
        writer.dup();
    } else if (isCompanion) {
        writer.getStatic(beanType, "Companion", JavaModelUtils.getTypeReference(constructor.getDeclaringType()));
    }
    argumentsPusher.accept(writer, constructor);
    if (isConstructor) {
        final String constructorDescriptor = getConstructorDescriptor(constructorArguments);
        writer.invokeConstructor(beanType, new Method("<init>", constructorDescriptor));
    } else if (constructor.isStatic()) {
        final String methodDescriptor = getMethodDescriptor(beanType, argumentTypes);
        Method method = new Method(constructor.getName(), methodDescriptor);
        if (classElement.isInterface()) {
            writer.visitMethodInsn(Opcodes.INVOKESTATIC, beanType.getInternalName(), method.getName(), method.getDescriptor(), true);
        } else {
            writer.invokeStatic(beanType, method);
        }
    } else if (isCompanion) {
        writer.invokeVirtual(JavaModelUtils.getTypeReference(constructor.getDeclaringType()), new Method(constructor.getName(), getMethodDescriptor(beanType, argumentTypes)));
    }
}
Also used : ConstructorElement(io.micronaut.inject.ast.ConstructorElement) ElementQuery(io.micronaut.inject.ast.ElementQuery) Arrays(java.util.Arrays) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) Internal(io.micronaut.core.annotation.Internal) BeanIntrospectionReference(io.micronaut.core.beans.BeanIntrospectionReference) Type(org.objectweb.asm.Type) Map(java.util.Map) NameUtils(io.micronaut.core.naming.NameUtils) AbstractBeanIntrospectionReference(io.micronaut.core.beans.AbstractBeanIntrospectionReference) AbstractAnnotationMetadataWriter(io.micronaut.inject.writer.AbstractAnnotationMetadataWriter) AnnotationMetadataWriter(io.micronaut.inject.annotation.AnnotationMetadataWriter) AnnotationMetadataHierarchy(io.micronaut.inject.annotation.AnnotationMetadataHierarchy) Collection(java.util.Collection) Set(java.util.Set) NotNull(javax.validation.constraints.NotNull) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Introspected(io.micronaut.core.annotation.Introspected) List(java.util.List) MethodElement(io.micronaut.inject.ast.MethodElement) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) ClassWriter(org.objectweb.asm.ClassWriter) AbstractInitializableBeanIntrospection(io.micronaut.inject.beans.AbstractInitializableBeanIntrospection) Label(org.objectweb.asm.Label) ClassElement(io.micronaut.inject.ast.ClassElement) HashMap(java.util.HashMap) StringSwitchWriter(io.micronaut.inject.writer.StringSwitchWriter) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) ConstructorElement(io.micronaut.inject.ast.ConstructorElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Method(org.objectweb.asm.commons.Method) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) TypedElement(io.micronaut.inject.ast.TypedElement) Nullable(io.micronaut.core.annotation.Nullable) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) BiConsumer(java.util.function.BiConsumer) Argument(io.micronaut.core.type.Argument) ClassWriterOutputVisitor(io.micronaut.inject.writer.ClassWriterOutputVisitor) LinkedHashSet(java.util.LinkedHashSet) OutputStream(java.io.OutputStream) Opcodes(org.objectweb.asm.Opcodes) IOException(java.io.IOException) ReflectionUtils(io.micronaut.core.reflect.ReflectionUtils) NonNull(io.micronaut.core.annotation.NonNull) DispatchWriter(io.micronaut.inject.writer.DispatchWriter) BeanIntrospection(io.micronaut.core.beans.BeanIntrospection) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Collections(java.util.Collections) Type(org.objectweb.asm.Type) ParameterElement(io.micronaut.inject.ast.ParameterElement) Method(org.objectweb.asm.commons.Method)

Example 3 with ParameterElement

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

the class BeanDefinitionWriter method pushNewMethodReference.

private void pushNewMethodReference(GeneratorAdapter staticInit, Type beanType, MethodElement methodElement, boolean requiresReflection, boolean isPostConstructMethod, boolean isPreDestroyMethod) {
    for (ParameterElement value : methodElement.getParameters()) {
        DefaultAnnotationMetadata.contributeDefaults(this.annotationMetadata, value.getAnnotationMetadata());
        DefaultAnnotationMetadata.contributeRepeatable(this.annotationMetadata, value.getGenericType());
    }
    staticInit.newInstance(Type.getType(AbstractInitializableBeanDefinition.MethodReference.class));
    staticInit.dup();
    // 1: declaringType
    staticInit.push(beanType);
    // 2: methodName
    staticInit.push(methodElement.getName());
    // 3: arguments
    if (!methodElement.hasParameters()) {
        staticInit.visitInsn(ACONST_NULL);
    } else {
        pushBuildArgumentsForMethod(beanFullClassName, beanDefinitionType, classWriter, staticInit, Arrays.asList(methodElement.getParameters()), defaultsStorage, loadTypeMethods);
    }
    // 4: annotationMetadata
    pushAnnotationMetadata(staticInit, methodElement.getAnnotationMetadata());
    // 5: requiresReflection
    staticInit.push(requiresReflection);
    if (isPreDestroyMethod || isPostConstructMethod) {
        // 6: isPostConstructMethod
        staticInit.push(isPostConstructMethod);
        // 7: isPreDestroyMethod
        staticInit.push(isPreDestroyMethod);
        staticInit.invokeConstructor(Type.getType(AbstractInitializableBeanDefinition.MethodReference.class), METHOD_REFERENCE_CONSTRUCTOR_POST_PRE);
    } else {
        staticInit.invokeConstructor(Type.getType(AbstractInitializableBeanDefinition.MethodReference.class), METHOD_REFERENCE_CONSTRUCTOR);
    }
}
Also used : ParameterElement(io.micronaut.inject.ast.ParameterElement)

Example 4 with ParameterElement

use of io.micronaut.inject.ast.ParameterElement 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 5 with ParameterElement

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

the class BeanDefinitionWriter method visitBeanDefinitionConstructorInternal.

private void visitBeanDefinitionConstructorInternal(GeneratorAdapter staticInit, Object constructor, boolean requiresReflection) {
    if (constructor instanceof MethodElement) {
        MethodElement methodElement = (MethodElement) constructor;
        AnnotationMetadata constructorMetadata = methodElement.getAnnotationMetadata();
        DefaultAnnotationMetadata.contributeDefaults(this.annotationMetadata, constructorMetadata);
        DefaultAnnotationMetadata.contributeRepeatable(this.annotationMetadata, methodElement.getGenericReturnType());
        ParameterElement[] parameters = methodElement.getParameters();
        List<ParameterElement> parameterList = Arrays.asList(parameters);
        applyDefaultNamedToParameters(parameterList);
        pushNewMethodReference(staticInit, JavaModelUtils.getTypeReference(methodElement.getDeclaringType()), methodElement, requiresReflection, false, false);
    } else if (constructor instanceof FieldElement) {
        FieldElement fieldConstructor = (FieldElement) constructor;
        pushNewFieldReference(staticInit, JavaModelUtils.getTypeReference(fieldConstructor.getDeclaringType()), fieldConstructor, constructorRequiresReflection);
    } else {
        throw new IllegalArgumentException("Unexpected constructor: " + constructor);
    }
    staticInit.putStatic(beanDefinitionType, FIELD_CONSTRUCTOR, Type.getType(AbstractInitializableBeanDefinition.MethodOrFieldReference.class));
    GeneratorAdapter publicConstructor = new GeneratorAdapter(classWriter.visitMethod(ACC_PUBLIC, CONSTRUCTOR_NAME, DESCRIPTOR_DEFAULT_CONSTRUCTOR, null, null), ACC_PUBLIC, CONSTRUCTOR_NAME, DESCRIPTOR_DEFAULT_CONSTRUCTOR);
    publicConstructor.loadThis();
    publicConstructor.push(beanType);
    publicConstructor.getStatic(beanDefinitionType, FIELD_CONSTRUCTOR, Type.getType(AbstractInitializableBeanDefinition.MethodOrFieldReference.class));
    publicConstructor.invokeConstructor(superBeanDefinition ? superType : beanDefinitionType, PROTECTED_ABSTRACT_BEAN_DEFINITION_CONSTRUCTOR);
    publicConstructor.visitInsn(RETURN);
    publicConstructor.visitMaxs(5, 1);
    publicConstructor.visitEnd();
    if (!superBeanDefinition) {
        // create protected constructor for subclasses of AbstractBeanDefinition
        GeneratorAdapter protectedConstructor = new GeneratorAdapter(classWriter.visitMethod(ACC_PROTECTED, PROTECTED_ABSTRACT_BEAN_DEFINITION_CONSTRUCTOR.getName(), PROTECTED_ABSTRACT_BEAN_DEFINITION_CONSTRUCTOR.getDescriptor(), null, null), ACC_PROTECTED, PROTECTED_ABSTRACT_BEAN_DEFINITION_CONSTRUCTOR.getName(), PROTECTED_ABSTRACT_BEAN_DEFINITION_CONSTRUCTOR.getDescriptor());
        AnnotationMetadata annotationMetadata = this.annotationMetadata != null ? this.annotationMetadata : AnnotationMetadata.EMPTY_METADATA;
        protectedConstructor.loadThis();
        // 1: beanType
        protectedConstructor.loadArg(0);
        // 2: `AbstractBeanDefinition2.MethodOrFieldReference.class` constructor
        protectedConstructor.loadArg(1);
        // 3: annotationMetadata
        if (this.annotationMetadata == null) {
            protectedConstructor.push((String) null);
        } else {
            protectedConstructor.getStatic(getTypeReferenceForName(getBeanDefinitionReferenceClassName()), AbstractAnnotationMetadataWriter.FIELD_ANNOTATION_METADATA, Type.getType(AnnotationMetadata.class));
        }
        // 4: `AbstractBeanDefinition2.MethodReference[].class` methodInjection
        if (allMethodVisits.isEmpty()) {
            protectedConstructor.push((String) null);
        } else {
            protectedConstructor.getStatic(beanDefinitionType, FIELD_INJECTION_METHODS, Type.getType(AbstractInitializableBeanDefinition.MethodReference[].class));
        }
        // 5: `AbstractBeanDefinition2.FieldReference[].class` fieldInjection
        if (fieldInjectionPoints.isEmpty()) {
            protectedConstructor.push((String) null);
        } else {
            protectedConstructor.getStatic(beanDefinitionType, FIELD_INJECTION_FIELDS, Type.getType(AbstractInitializableBeanDefinition.FieldReference[].class));
        }
        // 6: `ExecutableMethod[]` executableMethods
        if (executableMethodsDefinitionWriter == null) {
            protectedConstructor.push((String) null);
        } else {
            protectedConstructor.newInstance(executableMethodsDefinitionWriter.getClassType());
            protectedConstructor.dup();
            protectedConstructor.invokeConstructor(executableMethodsDefinitionWriter.getClassType(), METHOD_DEFAULT_CONSTRUCTOR);
        }
        // 7: `Map<String, Argument<?>[]>` typeArgumentsMap
        if (!hasTypeArguments()) {
            protectedConstructor.push((String) null);
        } else {
            protectedConstructor.getStatic(beanDefinitionType, FIELD_TYPE_ARGUMENTS, Type.getType(Map.class));
        }
        // 8: `Optional` scope
        String scope = annotationMetadata.getAnnotationNameByStereotype(AnnotationUtil.SCOPE).orElse(null);
        if (scope != null) {
            protectedConstructor.push(scope);
            protectedConstructor.invokeStatic(TYPE_OPTIONAL, METHOD_OPTIONAL_OF);
        } else {
            protectedConstructor.invokeStatic(TYPE_OPTIONAL, METHOD_OPTIONAL_EMPTY);
        }
        // 9: `boolean` isAbstract
        protectedConstructor.push(isAbstract);
        // 10: `boolean` isProvided
        protectedConstructor.push(annotationMetadata.hasDeclaredStereotype(Provided.class));
        // 11: `boolean` isIterable
        protectedConstructor.push(isIterable(annotationMetadata));
        // 12: `boolean` isSingleton
        protectedConstructor.push(isSingleton(scope));
        // 13: `boolean` isPrimary
        protectedConstructor.push(annotationMetadata.hasDeclaredStereotype(Primary.class));
        // 14: `boolean` isConfigurationProperties
        protectedConstructor.push(isConfigurationProperties);
        // 15: isContainerType
        protectedConstructor.push(isContainerType());
        // 16: requiresMethodProcessing
        protectedConstructor.push(preprocessMethods);
        protectedConstructor.invokeConstructor(isSuperFactory ? TYPE_ABSTRACT_BEAN_DEFINITION : superType, BEAN_DEFINITION_CLASS_CONSTRUCTOR);
        protectedConstructor.visitInsn(RETURN);
        protectedConstructor.visitMaxs(20, 1);
        protectedConstructor.visitEnd();
    }
}
Also used : MethodElement(io.micronaut.inject.ast.MethodElement) FieldElement(io.micronaut.inject.ast.FieldElement) MutableAnnotationMetadata(io.micronaut.inject.annotation.MutableAnnotationMetadata) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) AbstractInitializableBeanDefinition(io.micronaut.context.AbstractInitializableBeanDefinition) Primary(io.micronaut.context.annotation.Primary) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ParameterElement(io.micronaut.inject.ast.ParameterElement) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) Provided(io.micronaut.context.annotation.Provided)

Aggregations

ParameterElement (io.micronaut.inject.ast.ParameterElement)32 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)13 ClassElement (io.micronaut.inject.ast.ClassElement)13 Type (org.objectweb.asm.Type)13 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)13 DefaultAnnotationMetadata (io.micronaut.inject.annotation.DefaultAnnotationMetadata)12 MethodElement (io.micronaut.inject.ast.MethodElement)9 ArrayList (java.util.ArrayList)8 List (java.util.List)8 AbstractConstructorInjectionPoint (io.micronaut.context.AbstractConstructorInjectionPoint)7 Label (org.objectweb.asm.Label)7 Argument (io.micronaut.core.type.Argument)6 ConstructorInjectionPoint (io.micronaut.inject.ConstructorInjectionPoint)6 MutableAnnotationMetadata (io.micronaut.inject.annotation.MutableAnnotationMetadata)6 TypedElement (io.micronaut.inject.ast.TypedElement)6 Map (java.util.Map)6 AnnotationMetadataReference (io.micronaut.inject.annotation.AnnotationMetadataReference)5 FieldElement (io.micronaut.inject.ast.FieldElement)5 HashMap (java.util.HashMap)5 ClassWriter (org.objectweb.asm.ClassWriter)5