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