Search in sources :

Example 16 with ParameterElement

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

the class ExecutableMethodWriter method buildResolveTargetMethod.

private void buildResolveTargetMethod(String methodName, Type declaringTypeObject, boolean hasArgs, Collection<ParameterElement> argumentTypeClasses) {
    String targetMethodInternalName = METHOD_GET_TARGET.getName();
    String targetMethodDescriptor = METHOD_GET_TARGET.getDescriptor();
    GeneratorAdapter getTargetMethod = new GeneratorAdapter(classWriter.visitMethod(ACC_PUBLIC | ACC_FINAL, targetMethodInternalName, targetMethodDescriptor, null, null), ACC_PUBLIC | ACC_FINAL, targetMethodInternalName, targetMethodDescriptor);
    getTargetMethod.push(declaringTypeObject);
    getTargetMethod.push(methodName);
    if (hasArgs) {
        int len = argumentTypeClasses.size();
        Iterator<ParameterElement> iter = argumentTypeClasses.iterator();
        pushNewArray(getTargetMethod, Class.class, len);
        for (int i = 0; i < len; i++) {
            ParameterElement type = iter.next();
            pushStoreInArray(getTargetMethod, i, len, () -> getTargetMethod.push(JavaModelUtils.getTypeReference(type)));
        }
    } else {
        getTargetMethod.getStatic(TYPE_REFLECTION_UTILS, "EMPTY_CLASS_ARRAY", Type.getType(Class[].class));
    }
    getTargetMethod.invokeStatic(TYPE_REFLECTION_UTILS, METHOD_GET_REQUIRED_METHOD);
    getTargetMethod.returnValue();
    getTargetMethod.visitMaxs(1, 1);
    getTargetMethod.endMethod();
}
Also used : GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ParameterElement(io.micronaut.inject.ast.ParameterElement)

Example 17 with ParameterElement

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

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

the class ExecutableMethodsDefinitionWriter method buildInvokeMethod.

private void buildInvokeMethod(Type declaringTypeObject, String methodName, boolean isInterface, ClassElement returnType, Collection<ParameterElement> argumentTypes, GeneratorAdapter invokeMethodVisitor, String interceptedProxyClassName, String interceptedProxyBridgeMethodName) {
    Type returnTypeObject = JavaModelUtils.getTypeReference(returnType);
    // load this
    invokeMethodVisitor.loadArg(1);
    // duplicate target
    invokeMethodVisitor.dup();
    String methodDescriptor = getMethodDescriptor(returnType, argumentTypes);
    if (interceptedProxyClassName != null) {
        Label invokeTargetBlock = new Label();
        Type interceptedProxyType = getObjectType(interceptedProxyClassName);
        // load this.$interceptable field value
        invokeMethodVisitor.loadThis();
        invokeMethodVisitor.getField(Type.getObjectType(internalName), FIELD_INTERCEPTABLE, Type.getType(boolean.class));
        // check if it equals true
        invokeMethodVisitor.push(true);
        invokeMethodVisitor.ifCmp(Type.BOOLEAN_TYPE, GeneratorAdapter.NE, invokeTargetBlock);
        // target instanceOf intercepted proxy
        invokeMethodVisitor.loadArg(1);
        invokeMethodVisitor.instanceOf(interceptedProxyType);
        // check if instanceOf
        invokeMethodVisitor.push(true);
        invokeMethodVisitor.ifCmp(Type.BOOLEAN_TYPE, GeneratorAdapter.NE, invokeTargetBlock);
        pushCastToType(invokeMethodVisitor, interceptedProxyType);
        // load arguments
        Iterator<ParameterElement> iterator = argumentTypes.iterator();
        for (int i = 0; i < argumentTypes.size(); i++) {
            invokeMethodVisitor.loadArg(2);
            invokeMethodVisitor.push(i);
            invokeMethodVisitor.visitInsn(AALOAD);
            pushCastToType(invokeMethodVisitor, iterator.next());
        }
        invokeMethodVisitor.visitMethodInsn(INVOKEVIRTUAL, interceptedProxyType.getInternalName(), interceptedProxyBridgeMethodName, methodDescriptor, false);
        if (returnTypeObject.equals(Type.VOID_TYPE)) {
            invokeMethodVisitor.visitInsn(ACONST_NULL);
        } else {
            pushBoxPrimitiveIfNecessary(returnType, invokeMethodVisitor);
        }
        invokeMethodVisitor.returnValue();
        invokeMethodVisitor.visitLabel(invokeTargetBlock);
        // remove parent
        invokeMethodVisitor.pop();
    }
    pushCastToType(invokeMethodVisitor, declaringTypeObject);
    boolean hasArgs = !argumentTypes.isEmpty();
    if (hasArgs) {
        int argCount = argumentTypes.size();
        Iterator<ParameterElement> argIterator = argumentTypes.iterator();
        for (int i = 0; i < argCount; i++) {
            invokeMethodVisitor.loadArg(2);
            invokeMethodVisitor.push(i);
            invokeMethodVisitor.visitInsn(AALOAD);
            // cast the return value to the correct type
            pushCastToType(invokeMethodVisitor, argIterator.next());
        }
    }
    invokeMethodVisitor.visitMethodInsn(isInterface ? INVOKEINTERFACE : INVOKEVIRTUAL, declaringTypeObject.getInternalName(), methodName, methodDescriptor, isInterface);
    if (returnTypeObject.equals(Type.VOID_TYPE)) {
        invokeMethodVisitor.visitInsn(ACONST_NULL);
    } else {
        pushBoxPrimitiveIfNecessary(returnType, invokeMethodVisitor);
    }
}
Also used : Type(org.objectweb.asm.Type) Label(org.objectweb.asm.Label) ParameterElement(io.micronaut.inject.ast.ParameterElement)

Example 19 with ParameterElement

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

the class AopProxyWriter method visitAroundMethod.

/**
 * Visit a method that is to be proxied.
 *
 * @param beanType      The bean type.
 * @param methodElement The method element
 */
public void visitAroundMethod(TypedElement beanType, MethodElement methodElement) {
    ClassElement returnType = methodElement.isSuspend() ? ClassElement.of(Object.class) : methodElement.getReturnType();
    Type returnTypeObject = JavaModelUtils.getTypeReference(returnType);
    boolean isPrimitive = returnType.isPrimitive();
    boolean isVoidReturn = isPrimitive && returnTypeObject.equals(Type.VOID_TYPE);
    final Optional<MethodElement> overridden = methodElement.getOwningType().getEnclosedElement(ElementQuery.ALL_METHODS.onlyInstance().named(name -> name.equals(methodElement.getName())).filter(el -> el.overrides(methodElement)));
    if (overridden.isPresent()) {
        MethodElement overriddenBy = overridden.get();
        String methodElementKey = methodElement.getName() + Arrays.stream(methodElement.getSuspendParameters()).map(p -> p.getType().getName()).collect(Collectors.joining(","));
        String overriddenByKey = overriddenBy.getName() + Arrays.stream(methodElement.getSuspendParameters()).map(p -> p.getGenericType().getName()).collect(Collectors.joining(","));
        if (!methodElementKey.equals(overriddenByKey)) {
            buildMethodDelegate(methodElement, overriddenBy, isVoidReturn);
            return;
        }
    }
    String methodName = methodElement.getName();
    List<ParameterElement> argumentTypeList = Arrays.asList(methodElement.getSuspendParameters());
    int argumentCount = argumentTypeList.size();
    final Type declaringTypeReference = JavaModelUtils.getTypeReference(beanType);
    MethodRef methodKey = new MethodRef(methodName, argumentTypeList, returnTypeObject);
    if (!proxiedMethodsRefSet.contains(methodKey)) {
        String interceptedProxyClassName = null;
        String interceptedProxyBridgeMethodName = null;
        if (!isProxyTarget) {
            if (!methodElement.isAbstract() || methodElement.isDefault()) {
                interceptedProxyClassName = proxyFullName;
                interceptedProxyBridgeMethodName = "$$access$$" + methodName;
                String bridgeDesc = getMethodDescriptor(returnType, argumentTypeList);
                // now build a bridge to invoke the original method
                MethodVisitor bridgeWriter = classWriter.visitMethod(ACC_SYNTHETIC, interceptedProxyBridgeMethodName, bridgeDesc, null, null);
                GeneratorAdapter bridgeGenerator = new GeneratorAdapter(bridgeWriter, ACC_SYNTHETIC, interceptedProxyBridgeMethodName, bridgeDesc);
                bridgeGenerator.loadThis();
                for (int i = 0; i < argumentTypeList.size(); i++) {
                    bridgeGenerator.loadArg(i);
                }
                String desc = getMethodDescriptor(returnType, argumentTypeList);
                bridgeWriter.visitMethodInsn(INVOKESPECIAL, declaringTypeReference.getInternalName(), methodName, desc, this.isInterface && methodElement.isDefault());
                pushReturnValue(bridgeWriter, returnType);
                bridgeWriter.visitMaxs(DEFAULT_MAX_STACK, 1);
                bridgeWriter.visitEnd();
            }
        }
        BeanDefinitionWriter beanDefinitionWriter = parentWriter == null ? proxyBeanDefinitionWriter : parentWriter;
        int methodIndex = beanDefinitionWriter.visitExecutableMethod(beanType, methodElement, interceptedProxyClassName, interceptedProxyBridgeMethodName);
        int index = proxyMethodCount++;
        methodKey.methodIndex = methodIndex;
        proxiedMethods.add(methodKey);
        proxiedMethodsRefSet.add(methodKey);
        proxyTargetMethods.add(methodKey);
        buildMethodOverride(returnType, methodName, index, argumentTypeList, argumentCount, isVoidReturn);
    }
}
Also used : ElementQuery(io.micronaut.inject.ast.ElementQuery) Arrays(java.util.Arrays) InterceptedProxy(io.micronaut.aop.InterceptedProxy) MethodVisitor(org.objectweb.asm.MethodVisitor) BeanContext(io.micronaut.context.BeanContext) ArrayUtils(io.micronaut.core.util.ArrayUtils) FieldElement(io.micronaut.inject.ast.FieldElement) DefaultBeanContext(io.micronaut.context.DefaultBeanContext) Type(org.objectweb.asm.Type) ProxyingBeanDefinitionVisitor(io.micronaut.inject.writer.ProxyingBeanDefinitionVisitor) Introduced(io.micronaut.aop.Introduced) MethodInterceptorChain(io.micronaut.aop.chain.MethodInterceptorChain) Map(java.util.Map) BeanResolutionContext(io.micronaut.context.BeanResolutionContext) AbstractClassFileWriter(io.micronaut.inject.writer.AbstractClassFileWriter) HotSwappableInterceptedProxy(io.micronaut.aop.HotSwappableInterceptedProxy) BeanLocator(io.micronaut.context.BeanLocator) ClassVisitor(org.objectweb.asm.ClassVisitor) ReadWriteLock(java.util.concurrent.locks.ReadWriteLock) Set(java.util.Set) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) StringUtils(io.micronaut.core.util.StringUtils) List(java.util.List) Interceptor(io.micronaut.aop.Interceptor) AnnotationUtil(io.micronaut.core.annotation.AnnotationUtil) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) ProxyBeanDefinition(io.micronaut.inject.ProxyBeanDefinition) MethodElement(io.micronaut.inject.ast.MethodElement) Optional(java.util.Optional) InterceptorChain(io.micronaut.aop.chain.InterceptorChain) BeanDefinitionWriter(io.micronaut.inject.writer.BeanDefinitionWriter) ConfigurationMetadata(io.micronaut.inject.configuration.ConfigurationMetadata) JavaModelUtils(io.micronaut.inject.processing.JavaModelUtils) ClassWriter(org.objectweb.asm.ClassWriter) BeanRegistration(io.micronaut.context.BeanRegistration) OriginatingElements(io.micronaut.inject.writer.OriginatingElements) Qualifier(io.micronaut.context.Qualifier) Label(org.objectweb.asm.Label) ClassElement(io.micronaut.inject.ast.ClassElement) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) Toggleable(io.micronaut.core.util.Toggleable) DefaultAnnotationMetadata(io.micronaut.inject.annotation.DefaultAnnotationMetadata) Constructor(java.lang.reflect.Constructor) ExecutableMethod(io.micronaut.inject.ExecutableMethod) 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) AnnotationMetadataReference(io.micronaut.inject.annotation.AnnotationMetadataReference) ConfigurationReader(io.micronaut.context.annotation.ConfigurationReader) Argument(io.micronaut.core.type.Argument) ClassWriterOutputVisitor(io.micronaut.inject.writer.ClassWriterOutputVisitor) LinkedHashSet(java.util.LinkedHashSet) ExecutableMethodsDefinitionWriter(io.micronaut.inject.writer.ExecutableMethodsDefinitionWriter) OutputStream(java.io.OutputStream) Opcodes(org.objectweb.asm.Opcodes) Element(io.micronaut.inject.ast.Element) Iterator(java.util.Iterator) InterceptedMethodUtil(io.micronaut.aop.internal.intercepted.InterceptedMethodUtil) IOException(java.io.IOException) OptionalValues(io.micronaut.core.value.OptionalValues) ReflectionUtils(io.micronaut.core.reflect.ReflectionUtils) File(java.io.File) InterceptorKind(io.micronaut.aop.InterceptorKind) NonNull(io.micronaut.core.annotation.NonNull) ExecutionHandleLocator(io.micronaut.context.ExecutionHandleLocator) VisitorContext(io.micronaut.inject.visitor.VisitorContext) Lock(java.util.concurrent.locks.Lock) ConfigurationMetadataBuilder(io.micronaut.inject.configuration.ConfigurationMetadataBuilder) BeanDefinitionVisitor(io.micronaut.inject.writer.BeanDefinitionVisitor) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) BeanDefinition(io.micronaut.inject.BeanDefinition) Collections(java.util.Collections) Intercepted(io.micronaut.aop.Intercepted) MethodElement(io.micronaut.inject.ast.MethodElement) ClassElement(io.micronaut.inject.ast.ClassElement) BeanDefinitionWriter(io.micronaut.inject.writer.BeanDefinitionWriter) MethodVisitor(org.objectweb.asm.MethodVisitor) Type(org.objectweb.asm.Type) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ParameterElement(io.micronaut.inject.ast.ParameterElement)

Example 20 with ParameterElement

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

the class JavaMethodElement method getParameters.

@Override
public ParameterElement[] getParameters() {
    if (this.parameters == null) {
        List<? extends VariableElement> parameters = executableElement.getParameters();
        List<ParameterElement> elts = new ArrayList<>(parameters.size());
        for (Iterator<? extends VariableElement> i = parameters.iterator(); i.hasNext(); ) {
            VariableElement variableElement = i.next();
            if (!i.hasNext() && isSuspend(variableElement)) {
                this.continuationParameter = newParameterElement(variableElement, AnnotationMetadata.EMPTY_METADATA);
                continue;
            }
            AnnotationMetadata annotationMetadata = visitorContext.getAnnotationUtils().getAnnotationMetadata(getFieldElementForWriter(), variableElement);
            JavaParameterElement javaParameterElement = newParameterElement(variableElement, annotationMetadata);
            if (annotationMetadata.hasDeclaredAnnotation("org.jetbrains.annotations.Nullable")) {
                javaParameterElement.annotate("javax.annotation.Nullable").getAnnotationMetadata();
            }
            elts.add(javaParameterElement);
        }
        this.parameters = elts.toArray(new ParameterElement[0]);
    }
    return this.parameters;
}
Also used : ParameterElement(io.micronaut.inject.ast.ParameterElement) VariableElement(javax.lang.model.element.VariableElement) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata)

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