use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.
the class BeanDefinitionWriter method pushInvokeGetBeansOfTypeForSetter.
private void pushInvokeGetBeansOfTypeForSetter(GeneratorAdapter injectMethodVisitor, String setterName, ParameterElement entry) {
// load 'this'
injectMethodVisitor.loadThis();
// 1st argument load BeanResolutionContext
injectMethodVisitor.loadArg(0);
// 2nd argument load BeanContext
injectMethodVisitor.loadArg(1);
// 3rd argument the method name
injectMethodVisitor.push(setterName);
AnnotationMetadata annotationMetadata;
if (entry.getAnnotationMetadata() instanceof MutableAnnotationMetadata) {
annotationMetadata = ((MutableAnnotationMetadata) entry.getAnnotationMetadata()).clone();
removeAnnotations(annotationMetadata, PropertySource.class.getName(), Property.class.getName());
} else {
annotationMetadata = entry.getAnnotationMetadata();
}
// 4th argument the argument
ClassElement genericType = entry.getGenericType();
if (keepConfPropInjectPoints) {
resolveMethodArgument(injectMethodVisitor, currentMethodIndex, 0);
} else {
pushCreateArgument(beanFullClassName, beanDefinitionType, classWriter, injectMethodVisitor, entry.getName(), genericType, annotationMetadata, genericType.getTypeArguments(), new HashMap<>(), loadTypeMethods);
}
int thisArgument = injectMethodVisitor.newLocal(Type.getType(Argument.class));
injectMethodVisitor.storeLocal(thisArgument);
injectMethodVisitor.loadLocal(thisArgument);
if (!resolveArgumentGenericType(injectMethodVisitor, genericType)) {
injectMethodVisitor.loadLocal(thisArgument);
resolveFirstTypeArgument(injectMethodVisitor);
resolveInnerTypeArgumentIfNeeded(injectMethodVisitor, genericType);
} else {
injectMethodVisitor.push((String) null);
}
// push qualifier
pushQualifier(injectMethodVisitor, genericType, () -> injectMethodVisitor.loadLocal(thisArgument));
pushInvokeMethodOnSuperClass(injectMethodVisitor, GET_BEANS_OF_TYPE_FOR_SETTER);
// cast the return value to the correct type
pushCastToType(injectMethodVisitor, entry);
}
use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.
the class BeanDefinitionWriter method visitBeanDefinitionEnd.
/**
* Finalize the bean definition to the given output stream.
*/
@SuppressWarnings("Duplicates")
@Override
public void visitBeanDefinitionEnd() {
if (classWriter == null) {
throw new IllegalStateException("At least one called to visitBeanDefinitionConstructor(..) is required");
}
processAllBeanElementVisitors();
if (constructor instanceof MethodElement) {
MethodElement methodElement = (MethodElement) constructor;
boolean isParametrized = Arrays.stream(methodElement.getParameters()).map(AnnotationMetadataProvider::getAnnotationMetadata).anyMatch(this::isAnnotatedWithParameter);
if (isParametrized) {
interfaceTypes.add(ParametrizedBeanFactory.class);
}
}
String[] interfaceInternalNames = new String[interfaceTypes.size()];
Iterator<Class> j = interfaceTypes.iterator();
for (int i = 0; i < interfaceInternalNames.length; i++) {
interfaceInternalNames[i] = Type.getInternalName(j.next());
}
final String beanDefSignature = generateBeanDefSig(beanType);
classWriter.visit(V1_8, ACC_SYNTHETIC, beanDefinitionInternalName, beanDefSignature, isSuperFactory ? TYPE_ABSTRACT_BEAN_DEFINITION.getInternalName() : superType.getInternalName(), interfaceInternalNames);
classWriter.visitAnnotation(TYPE_GENERATED.getDescriptor(), false);
if (buildMethodVisitor == null) {
throw new IllegalStateException("At least one call to visitBeanDefinitionConstructor() is required");
}
GeneratorAdapter staticInit = visitStaticInitializer(classWriter);
classWriter.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, FIELD_CONSTRUCTOR, Type.getType(AbstractInitializableBeanDefinition.MethodOrFieldReference.class).getDescriptor(), null, null);
int methodsLength = allMethodVisits.size();
if (!superBeanDefinition && methodsLength > 0) {
Type methodsFieldType = Type.getType(AbstractInitializableBeanDefinition.MethodReference[].class);
classWriter.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, FIELD_INJECTION_METHODS, methodsFieldType.getDescriptor(), null, null);
pushNewArray(staticInit, AbstractInitializableBeanDefinition.MethodReference.class, methodsLength);
int i = 0;
for (MethodVisitData methodVisitData : allMethodVisits) {
pushStoreInArray(staticInit, i++, methodsLength, () -> pushNewMethodReference(staticInit, JavaModelUtils.getTypeReference(methodVisitData.beanType), methodVisitData.methodElement, methodVisitData.requiresReflection, methodVisitData.isPostConstruct(), methodVisitData.isPreDestroy()));
}
staticInit.putStatic(beanDefinitionType, FIELD_INJECTION_METHODS, methodsFieldType);
}
if (!fieldInjectionPoints.isEmpty()) {
Type fieldsFieldType = Type.getType(AbstractInitializableBeanDefinition.FieldReference[].class);
classWriter.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, FIELD_INJECTION_FIELDS, fieldsFieldType.getDescriptor(), null, null);
int length = fieldInjectionPoints.size();
pushNewArray(staticInit, AbstractInitializableBeanDefinition.FieldReference.class, length);
for (int i = 0; i < length; i++) {
FieldVisitData fieldVisitData = fieldInjectionPoints.get(i);
pushStoreInArray(staticInit, i, length, () -> pushNewFieldReference(staticInit, JavaModelUtils.getTypeReference(fieldVisitData.beanType), fieldVisitData.fieldElement, fieldVisitData.requiresReflection));
}
staticInit.putStatic(beanDefinitionType, FIELD_INJECTION_FIELDS, fieldsFieldType);
}
if (!superBeanDefinition && hasTypeArguments()) {
Type typeArgumentsFieldType = Type.getType(Map.class);
classWriter.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, FIELD_TYPE_ARGUMENTS, typeArgumentsFieldType.getDescriptor(), null, null);
pushStringMapOf(staticInit, typeArguments, true, null, new Consumer<Map<String, ClassElement>>() {
@Override
public void accept(Map<String, ClassElement> stringClassElementMap) {
pushTypeArgumentElements(beanDefinitionType, classWriter, staticInit, beanDefinitionName, stringClassElementMap, defaultsStorage, loadTypeMethods);
}
});
staticInit.putStatic(beanDefinitionType, FIELD_TYPE_ARGUMENTS, typeArgumentsFieldType);
}
// first build the constructor
visitBeanDefinitionConstructorInternal(staticInit, constructor, constructorRequiresReflection);
addInnerConfigurationMethod(staticInit);
addGetExposedTypes(staticInit);
staticInit.returnValue();
staticInit.visitMaxs(DEFAULT_MAX_STACK, defaultsStorage.size() + 3);
staticInit.visitEnd();
if (buildMethodVisitor != null) {
if (isPrimitiveBean) {
pushBoxPrimitiveIfNecessary(beanType, buildMethodVisitor);
}
buildMethodVisitor.returnValue();
buildMethodVisitor.visitMaxs(DEFAULT_MAX_STACK, 10);
}
if (injectMethodVisitor != null) {
if (injectEnd != null) {
injectMethodVisitor.visitLabel(injectEnd);
}
invokeSuperInjectMethod(injectMethodVisitor, INJECT_BEAN_METHOD);
if (isPrimitiveBean) {
pushBoxPrimitiveIfNecessary(beanType, injectMethodVisitor);
}
injectMethodVisitor.returnValue();
injectMethodVisitor.visitMaxs(DEFAULT_MAX_STACK, 10);
}
if (postConstructMethodVisitor != null) {
postConstructMethodVisitor.loadLocal(postConstructInstanceLocalVarIndex);
postConstructMethodVisitor.returnValue();
postConstructMethodVisitor.visitMaxs(DEFAULT_MAX_STACK, 10);
}
if (preDestroyMethodVisitor != null) {
preDestroyMethodVisitor.loadLocal(preDestroyInstanceLocalVarIndex);
preDestroyMethodVisitor.returnValue();
preDestroyMethodVisitor.visitMaxs(DEFAULT_MAX_STACK, 10);
}
if (interceptedDisposeMethod != null) {
interceptedDisposeMethod.visitMaxs(1, 1);
interceptedDisposeMethod.visitEnd();
}
getInterceptedType().ifPresent(t -> implementInterceptedTypeMethod(t, this.classWriter));
for (GeneratorAdapter method : loadTypeMethods.values()) {
method.visitMaxs(3, 1);
method.visitEnd();
}
classWriter.visitEnd();
this.beanFinalized = true;
}
use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.
the class BeanDefinitionWriter method visitFieldInjectionPointInternal.
private void visitFieldInjectionPointInternal(TypedElement declaringType, FieldElement fieldElement, boolean requiresReflection) {
boolean requiresGenericType = false;
Method methodToInvoke;
final ClassElement genericType = fieldElement.getGenericType();
boolean isArray = genericType.isArray();
boolean isCollection = genericType.isAssignable(Collection.class);
if (isCollection || isArray) {
requiresGenericType = 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_FIELD;
} else {
methodToInvoke = GET_BEANS_OF_TYPE_FOR_FIELD;
}
} else {
requiresGenericType = false;
methodToInvoke = GET_BEAN_FOR_FIELD;
}
} else if (genericType.isAssignable(Stream.class)) {
requiresGenericType = true;
methodToInvoke = GET_STREAM_OF_TYPE_FOR_FIELD;
} else if (genericType.isAssignable(Optional.class)) {
requiresGenericType = true;
methodToInvoke = FIND_BEAN_FOR_FIELD;
} else if (genericType.isAssignable(BeanRegistration.class)) {
requiresGenericType = true;
methodToInvoke = GET_BEAN_REGISTRATION_FOR_FIELD;
} else {
methodToInvoke = GET_BEAN_FOR_FIELD;
}
visitFieldInjectionPointInternal(declaringType, fieldElement, requiresReflection, methodToInvoke, isArray, requiresGenericType);
}
use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.
the class BeanDefinitionWriter method pushMethodParameterValue.
private void pushMethodParameterValue(GeneratorAdapter injectMethodVisitor, int i, ParameterElement entry) {
AnnotationMetadata argMetadata = entry.getAnnotationMetadata();
if (entry.getGenericType().isAssignable(BeanResolutionContext.class)) {
injectMethodVisitor.loadArg(0);
} else if (entry.getGenericType().isAssignable(BeanContext.class)) {
injectMethodVisitor.loadArg(1);
} else {
boolean requiresGenericType = false;
final ClassElement genericType = entry.getGenericType();
Method methodToInvoke;
boolean isCollection = genericType.isAssignable(Collection.class);
boolean isArray = genericType.isArray();
if (isValueType(argMetadata) && !isInnerType(entry.getGenericType())) {
Optional<String> property = argMetadata.stringValue(Property.class, "name");
if (property.isPresent()) {
pushInvokeGetPropertyValueForMethod(injectMethodVisitor, i, entry, property.get());
} else {
Optional<String> valueValue = entry.getAnnotationMetadata().stringValue(Value.class);
if (valueValue.isPresent()) {
pushInvokeGetPropertyPlaceholderValueForMethod(injectMethodVisitor, i, entry, valueValue.get());
}
}
return;
} else if (isCollection || isArray) {
requiresGenericType = 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_METHOD_ARGUMENT;
} else {
methodToInvoke = GET_BEANS_OF_TYPE_FOR_METHOD_ARGUMENT;
}
} else {
methodToInvoke = GET_BEAN_FOR_METHOD_ARGUMENT;
requiresGenericType = false;
}
} else if (genericType.isAssignable(Stream.class)) {
requiresGenericType = true;
methodToInvoke = GET_STREAM_OF_TYPE_FOR_METHOD_ARGUMENT;
} else if (genericType.isAssignable(Optional.class)) {
requiresGenericType = true;
methodToInvoke = FIND_BEAN_FOR_METHOD_ARGUMENT;
} else if (genericType.isAssignable(BeanRegistration.class)) {
requiresGenericType = true;
methodToInvoke = GET_BEAN_REGISTRATION_FOR_METHOD_ARGUMENT;
} else {
methodToInvoke = GET_BEAN_FOR_METHOD_ARGUMENT;
}
// first get the value of the field by calling AbstractBeanDefinition.getBeanForMethod(..)
// load 'this'
injectMethodVisitor.loadThis();
// 1st argument load BeanResolutionContext
injectMethodVisitor.loadArg(0);
// 2nd argument load BeanContext
injectMethodVisitor.loadArg(1);
// 3rd argument the method index
injectMethodVisitor.push(currentMethodIndex);
// 4th argument the argument index
injectMethodVisitor.push(i);
// invoke getBeanForField
if (requiresGenericType) {
resolveMethodArgumentGenericType(injectMethodVisitor, genericType, currentMethodIndex, i);
}
pushQualifier(injectMethodVisitor, entry, () -> resolveMethodArgument(injectMethodVisitor, currentMethodIndex, i));
pushInvokeMethodOnSuperClass(injectMethodVisitor, methodToInvoke);
if (isArray && requiresGenericType) {
convertToArray(genericType.fromArray(), injectMethodVisitor);
}
// cast the return value to the correct type
pushCastToType(injectMethodVisitor, entry);
}
}
use of io.micronaut.inject.ast.ClassElement in project micronaut-core by micronaut-projects.
the class AbstractBeanDefinitionBuilder method build.
/**
* Build the bean definition writer.
* @return The writer, possibly null if it wasn't possible to build it
*/
@Nullable
public BeanDefinitionWriter build() {
if (exposedTypes != null) {
final AnnotationClassValue[] annotationClassValues = Arrays.stream(exposedTypes).map(ce -> new AnnotationClassValue<>(ce.getName())).toArray(AnnotationClassValue[]::new);
annotate(Bean.class, (builder) -> builder.member("typed", annotationClassValues));
}
final BeanDefinitionWriter beanDefinitionWriter = createBeanDefinitionWriter();
if (typeArguments != null) {
beanDefinitionWriter.visitTypeArguments(this.typeArguments);
}
if (constructorElement == null) {
constructorElement = initConstructor(beanType);
}
if (constructorElement == null) {
visitorContext.fail("Cannot create associated bean with no accessible primary constructor. Consider supply the constructor with createWith(..)", originatingElement);
return null;
} else {
beanDefinitionWriter.visitBeanDefinitionConstructor(constructorElement, !constructorElement.isPublic(), visitorContext);
}
Map<ClassElement, List<MemberElement>> sortedInjections = new LinkedHashMap<>();
List<MemberElement> allInjected = new ArrayList<>();
allInjected.addAll(injectedFields);
allInjected.addAll(injectedMethods);
allInjected.sort(SORTER);
for (MemberElement memberElement : allInjected) {
final List<MemberElement> list = sortedInjections.computeIfAbsent(memberElement.getDeclaringType(), classElement -> new ArrayList<>());
list.add(memberElement);
}
for (List<MemberElement> members : sortedInjections.values()) {
members.sort((o1, o2) -> {
if (o1 instanceof FieldElement && o2 instanceof MethodElement) {
return 1;
} else if (o1 instanceof MethodElement && o1 instanceof FieldElement) {
return -1;
}
return 0;
});
}
for (List<MemberElement> list : sortedInjections.values()) {
for (MemberElement memberElement : list) {
if (memberElement instanceof FieldElement) {
InternalBeanElementField ibf = (InternalBeanElementField) memberElement;
ibf.<InternalBeanElementField>with((element) -> visitField(beanDefinitionWriter, element, element));
} else {
InternalBeanElementMethod ibm = (InternalBeanElementMethod) memberElement;
ibm.<InternalBeanElementMethod>with((element) -> beanDefinitionWriter.visitMethodInjectionPoint(ibm.getDeclaringType(), ibm, ibm.isRequiresReflection(), visitorContext));
}
}
}
for (BeanMethodElement executableMethod : executableMethods) {
beanDefinitionWriter.visitExecutableMethod(beanType, executableMethod, visitorContext);
}
for (BeanMethodElement postConstructMethod : postConstructMethods) {
if (postConstructMethod.getDeclaringType().equals(beanType)) {
beanDefinitionWriter.visitPostConstructMethod(beanType, postConstructMethod, ((InternalBeanElementMethod) postConstructMethod).isRequiresReflection(), visitorContext);
}
}
for (BeanMethodElement preDestroyMethod : preDestroyMethods) {
if (preDestroyMethod.getDeclaringType().equals(beanType)) {
beanDefinitionWriter.visitPreDestroyMethod(beanType, preDestroyMethod, ((InternalBeanElementMethod) preDestroyMethod).isRequiresReflection(), visitorContext);
}
}
beanDefinitionWriter.visitBeanDefinitionEnd();
return beanDefinitionWriter;
}
Aggregations