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();
}
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);
}
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);
}
}
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);
}
}
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;
}
Aggregations