Search in sources :

Example 21 with ClassElement

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

the class AbstractClassFileWriter method pushBoxPrimitiveIfNecessary.

/**
 * @param fieldType           The field type
 * @param injectMethodVisitor The {@link MethodVisitor}
 */
protected static void pushBoxPrimitiveIfNecessary(TypedElement fieldType, MethodVisitor injectMethodVisitor) {
    ClassElement type = fieldType.getType();
    if (type.isPrimitive() && !type.isArray()) {
        String primitiveName = type.getName();
        final Optional<Class> pt = ClassUtils.getPrimitiveType(primitiveName);
        Class<?> wrapperType = pt.map(ReflectionUtils::getWrapperType).orElse(null);
        if (wrapperType != null && wrapperType != Void.class) {
            Type wrapper = Type.getType(wrapperType);
            String sig = wrapperType.getName() + " valueOf(" + primitiveName + ")";
            org.objectweb.asm.commons.Method valueOfMethod = org.objectweb.asm.commons.Method.getMethod(sig);
            injectMethodVisitor.visitMethodInsn(INVOKESTATIC, wrapper.getInternalName(), "valueOf", valueOfMethod.getDescriptor(), false);
        }
    }
}
Also used : Method(org.objectweb.asm.commons.Method) Type(org.objectweb.asm.Type) ClassElement(io.micronaut.inject.ast.ClassElement)

Example 22 with ClassElement

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

the class AbstractClassFileWriter method pushTypeArgumentElements.

private static void pushTypeArgumentElements(Type owningType, ClassWriter declaringClassWriter, GeneratorAdapter generatorAdapter, String declaringElementName, Map<String, ClassElement> types, Set<String> visitedTypes, Map<String, Integer> defaults, Map<String, GeneratorAdapter> loadTypeMethods) {
    if (visitedTypes.contains(declaringElementName)) {
        generatorAdapter.getStatic(TYPE_ARGUMENT, ZERO_ARGUMENTS_CONSTANT, TYPE_ARGUMENT_ARRAY);
    } else {
        visitedTypes.add(declaringElementName);
        int len = types.size();
        // Build calls to Argument.create(...)
        pushNewArray(generatorAdapter, Argument.class, len);
        int i = 0;
        for (Map.Entry<String, ClassElement> entry : types.entrySet()) {
            // the array index
            generatorAdapter.push(i);
            String argumentName = entry.getKey();
            ClassElement classElement = entry.getValue();
            Type classReference = JavaModelUtils.getTypeReference(classElement);
            Map<String, ClassElement> typeArguments = classElement.getTypeArguments();
            if (CollectionUtils.isNotEmpty(typeArguments) || classElement.getAnnotationMetadata() != AnnotationMetadata.EMPTY_METADATA) {
                buildArgumentWithGenerics(owningType, declaringClassWriter, generatorAdapter, argumentName, classReference, classElement, typeArguments, visitedTypes, defaults, loadTypeMethods);
            } else {
                buildArgument(generatorAdapter, argumentName, classElement);
            }
            // store the type reference
            generatorAdapter.visitInsn(AASTORE);
            // if we are not at the end of the array duplicate array onto the stack
            if (i != (len - 1)) {
                generatorAdapter.visitInsn(DUP);
            }
            i++;
        }
    }
}
Also used : Type(org.objectweb.asm.Type) ClassElement(io.micronaut.inject.ast.ClassElement) Map(java.util.Map) AbstractMap(java.util.AbstractMap)

Example 23 with ClassElement

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

the class AbstractClassFileWriter method pushCreateArgument.

/**
 * Pushes a new Argument creation.
 *
 * @param declaringTypeName    The declaring type name
 * @param owningType           The owning type
 * @param declaringClassWriter The declaring class writer
 * @param generatorAdapter     The generator adapter
 * @param argumentName         The argument name
 * @param typedElement         The typed element
 * @param annotationMetadata   The annotation metadata
 * @param typeArguments        The type arguments
 * @param defaults             The annotation defaults
 * @param loadTypeMethods      The load type methods
 */
protected static void pushCreateArgument(String declaringTypeName, Type owningType, ClassWriter declaringClassWriter, GeneratorAdapter generatorAdapter, String argumentName, TypedElement typedElement, AnnotationMetadata annotationMetadata, Map<String, ClassElement> typeArguments, Map<String, Integer> defaults, Map<String, GeneratorAdapter> loadTypeMethods) {
    Type argumentType = JavaModelUtils.getTypeReference(typedElement);
    // 1st argument: The type
    generatorAdapter.push(argumentType);
    // 2nd argument: The argument name
    generatorAdapter.push(argumentName);
    boolean hasAnnotations = !annotationMetadata.isEmpty() && annotationMetadata instanceof DefaultAnnotationMetadata;
    boolean hasTypeArguments = typeArguments != null && !typeArguments.isEmpty();
    boolean isGenericPlaceholder = typedElement instanceof GenericPlaceholderElement;
    boolean isTypeVariable = isGenericPlaceholder || ((typedElement instanceof ClassElement) && ((ClassElement) typedElement).isTypeVariable());
    String variableName = argumentName;
    if (isGenericPlaceholder) {
        variableName = ((GenericPlaceholderElement) typedElement).getVariableName();
    }
    boolean hasVariableName = !variableName.equals(argumentName);
    if (!hasAnnotations && !hasTypeArguments && !isTypeVariable) {
        invokeInterfaceStaticMethod(generatorAdapter, Argument.class, METHOD_CREATE_ARGUMENT_SIMPLE);
        return;
    }
    if (isTypeVariable && hasVariableName) {
        generatorAdapter.push(variableName);
    }
    // 3rd argument: The annotation metadata
    if (hasAnnotations) {
        AnnotationMetadataWriter.instantiateNewMetadata(owningType, declaringClassWriter, generatorAdapter, (DefaultAnnotationMetadata) annotationMetadata, defaults, loadTypeMethods);
    } else {
        generatorAdapter.visitInsn(ACONST_NULL);
    }
    // 4th argument: The generic types
    if (hasTypeArguments) {
        pushTypeArgumentElements(owningType, declaringClassWriter, generatorAdapter, declaringTypeName, typeArguments, defaults, loadTypeMethods);
    } else {
        generatorAdapter.visitInsn(ACONST_NULL);
    }
    if (isTypeVariable) {
        // Argument.create( .. )
        invokeInterfaceStaticMethod(generatorAdapter, Argument.class, hasVariableName ? METHOD_CREATE_GENERIC_PLACEHOLDER_WITH_ANNOTATION_METADATA_GENERICS : METHOD_CREATE_TYPE_VAR_WITH_ANNOTATION_METADATA_GENERICS);
    } else {
        // Argument.create( .. )
        invokeInterfaceStaticMethod(generatorAdapter, Argument.class, METHOD_CREATE_ARGUMENT_WITH_ANNOTATION_METADATA_GENERICS);
    }
}
Also used : Type(org.objectweb.asm.Type) GenericPlaceholderElement(io.micronaut.inject.ast.GenericPlaceholderElement) ClassElement(io.micronaut.inject.ast.ClassElement) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata)

Example 24 with ClassElement

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

the class AbstractClassFileWriter method pushBuildArgumentsForMethod.

/**
 * @param declaringElementName The declaring element name
 * @param owningType           The owning type
 * @param declaringClassWriter The declaring class writer
 * @param generatorAdapter     The {@link GeneratorAdapter}
 * @param argumentTypes        The argument types
 * @param defaults             The annotation defaults
 * @param loadTypeMethods      The load type methods
 */
protected static void pushBuildArgumentsForMethod(String declaringElementName, Type owningType, ClassWriter declaringClassWriter, GeneratorAdapter generatorAdapter, Collection<ParameterElement> argumentTypes, Map<String, Integer> defaults, Map<String, GeneratorAdapter> loadTypeMethods) {
    int len = argumentTypes.size();
    pushNewArray(generatorAdapter, Argument.class, len);
    int i = 0;
    for (ParameterElement entry : argumentTypes) {
        // the array index position
        generatorAdapter.push(i);
        ClassElement classElement = entry.getGenericType();
        String argumentName = entry.getName();
        AnnotationMetadata annotationMetadata = entry.getAnnotationMetadata();
        Map<String, ClassElement> typeArguments = classElement.getTypeArguments();
        pushCreateArgument(declaringElementName, owningType, declaringClassWriter, generatorAdapter, argumentName, classElement, annotationMetadata, typeArguments, defaults, loadTypeMethods);
        // store the type reference
        generatorAdapter.visitInsn(AASTORE);
        // if we are not at the end of the array duplicate array onto the stack
        if (i != (len - 1)) {
            generatorAdapter.visitInsn(DUP);
        }
        i++;
    }
}
Also used : ClassElement(io.micronaut.inject.ast.ClassElement) ParameterElement(io.micronaut.inject.ast.ParameterElement) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

Example 25 with ClassElement

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

the class JavaModelUtils method getTypeReference.

/**
 * Return the type reference for a class.
 *
 * @param type The type
 * @return The {@link Type}
 */
public static Type getTypeReference(TypedElement type) {
    ClassElement classElement = type.getType();
    if (type.isPrimitive()) {
        String internalName = NAME_TO_TYPE_MAP.get(classElement.getName());
        if (type.isArray()) {
            StringBuilder name = new StringBuilder(internalName);
            for (int i = 0; i < type.getArrayDimensions(); i++) {
                name.insert(0, "[");
            }
            return Type.getObjectType(name.toString());
        } else {
            return Type.getType(internalName);
        }
    } else {
        Object nativeType = type.getNativeType();
        if (nativeType instanceof Class) {
            Class<?> t = (Class<?>) nativeType;
            return Type.getType(t);
        } else {
            String internalName = type.getType().getName().replace('.', '/');
            if (internalName.isEmpty()) {
                return Type.getType(Object.class);
            }
            if (type.isArray()) {
                StringBuilder name = new StringBuilder(internalName);
                name.insert(0, "L");
                for (int i = 0; i < type.getArrayDimensions(); i++) {
                    name.insert(0, "[");
                }
                name.append(";");
                return Type.getObjectType(name.toString());
            } else {
                return Type.getObjectType(internalName);
            }
        }
    }
}
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