Search in sources :

Example 1 with WeaklyTypeReferencingMethod

use of org.gradle.model.internal.method.WeaklyTypeReferencingMethod in project gradle by gradle.

the class DefaultStructBindingsStore method collectMethodBindings.

private static <T> Set<StructMethodBinding> collectMethodBindings(StructBindingExtractionContext<T> extractionContext, Map<String, Multimap<PropertyAccessorType, StructMethodBinding>> propertyBindings) {
    Collection<WeaklyTypeReferencingMethod<?, ?>> implementedMethods = collectImplementedMethods(extractionContext.getImplementedSchemas());
    Map<Wrapper<Method>, WeaklyTypeReferencingMethod<?, ?>> publicViewImplMethods = collectPublicViewImplMethods(extractionContext.getPublicSchema());
    Map<Wrapper<Method>, WeaklyTypeReferencingMethod<?, ?>> delegateMethods = collectDelegateMethods(extractionContext.getDelegateSchema());
    ImmutableSet.Builder<StructMethodBinding> methodBindingsBuilder = ImmutableSet.builder();
    for (WeaklyTypeReferencingMethod<?, ?> weakImplementedMethod : implementedMethods) {
        Method implementedMethod = weakImplementedMethod.getMethod();
        PropertyAccessorType accessorType = PropertyAccessorType.of(implementedMethod);
        Wrapper<Method> methodKey = SIGNATURE_EQUIVALENCE.wrap(implementedMethod);
        WeaklyTypeReferencingMethod<?, ?> weakDelegateImplMethod = delegateMethods.get(methodKey);
        WeaklyTypeReferencingMethod<?, ?> weakPublicImplMethod = publicViewImplMethods.get(methodKey);
        if (weakDelegateImplMethod != null && weakPublicImplMethod != null) {
            extractionContext.add(weakImplementedMethod, String.format("it is both implemented by the view '%s' and the delegate type '%s'", extractionContext.getPublicSchema().getType().getDisplayName(), extractionContext.getDelegateSchema().getType().getDisplayName()));
        }
        String propertyName = accessorType == null ? null : accessorType.propertyNameFor(implementedMethod);
        StructMethodBinding binding;
        if (!Modifier.isAbstract(implementedMethod.getModifiers())) {
            binding = new DirectMethodBinding(weakImplementedMethod, accessorType);
        } else if (weakPublicImplMethod != null) {
            binding = new BridgeMethodBinding(weakImplementedMethod, weakPublicImplMethod, accessorType);
        } else if (weakDelegateImplMethod != null) {
            binding = new DelegateMethodBinding(weakImplementedMethod, weakDelegateImplMethod, accessorType);
        } else if (propertyName != null) {
            binding = new ManagedPropertyMethodBinding(weakImplementedMethod, propertyName, accessorType);
        } else {
            handleNoMethodImplementation(extractionContext, weakImplementedMethod);
            continue;
        }
        methodBindingsBuilder.add(binding);
        if (accessorType != null) {
            Multimap<PropertyAccessorType, StructMethodBinding> accessorBindings = propertyBindings.get(propertyName);
            if (accessorBindings == null) {
                accessorBindings = ArrayListMultimap.create();
                propertyBindings.put(propertyName, accessorBindings);
            }
            accessorBindings.put(accessorType, binding);
        }
    }
    return methodBindingsBuilder.build();
}
Also used : Wrapper(com.google.common.base.Equivalence.Wrapper) PropertyAccessorType(org.gradle.internal.reflect.PropertyAccessorType) Method(java.lang.reflect.Method) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) ImmutableSet(com.google.common.collect.ImmutableSet)

Example 2 with WeaklyTypeReferencingMethod

use of org.gradle.model.internal.method.WeaklyTypeReferencingMethod in project gradle by gradle.

the class ManagedProxyClassGenerator method writeGetter.

private void writeGetter(ClassVisitor visitor, Type generatedType, String propertyName, Class<?> propertyClass, WeaklyTypeReferencingMethod<?, ?> weakGetter) {
    Method getter = weakGetter.getMethod();
    Type propertyType = Type.getType(propertyClass);
    MethodVisitor methodVisitor = declareMethod(visitor, getter.getName(), Type.getMethodDescriptor(propertyType), AsmClassGeneratorUtils.signature(getter));
    putStateFieldValueOnStack(methodVisitor, generatedType);
    putConstantOnStack(methodVisitor, propertyName);
    invokeStateGetMethod(methodVisitor);
    castFirstStackElement(methodVisitor, propertyClass);
    finishVisitingMethod(methodVisitor, returnCode(propertyType));
}
Also used : Type(org.objectweb.asm.Type) PropertyAccessorType(org.gradle.internal.reflect.PropertyAccessorType) ModelType(org.gradle.model.internal.type.ModelType) Method(java.lang.reflect.Method) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 3 with WeaklyTypeReferencingMethod

use of org.gradle.model.internal.method.WeaklyTypeReferencingMethod in project gradle by gradle.

the class ManagedProxyClassGenerator method writeSetter.

private void writeSetter(ClassVisitor visitor, Type generatedType, String propertyName, Class<?> propertyClass, WeaklyTypeReferencingMethod<?, ?> weakSetter) {
    Type propertyType = Type.getType(propertyClass);
    Label calledOutsideOfConstructor = new Label();
    Method setter = weakSetter.getMethod();
    // the regular typed setter
    String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, propertyType);
    MethodVisitor methodVisitor = declareMethod(visitor, setter.getName(), methodDescriptor, AsmClassGeneratorUtils.signature(setter));
    putCanCallSettersFieldValueOnStack(methodVisitor, generatedType);
    jumpToLabelIfStackEvaluatesToTrue(methodVisitor, calledOutsideOfConstructor);
    throwExceptionBecauseCalledOnItself(methodVisitor);
    methodVisitor.visitLabel(calledOutsideOfConstructor);
    putStateFieldValueOnStack(methodVisitor, generatedType);
    putConstantOnStack(methodVisitor, propertyName);
    putFirstMethodArgumentOnStack(methodVisitor, propertyType);
    if (propertyClass.isPrimitive()) {
        boxType(methodVisitor, propertyClass);
    }
    invokeStateSetMethod(methodVisitor);
    finishVisitingMethod(methodVisitor);
}
Also used : Type(org.objectweb.asm.Type) PropertyAccessorType(org.gradle.internal.reflect.PropertyAccessorType) ModelType(org.gradle.model.internal.type.ModelType) Label(org.objectweb.asm.Label) Method(java.lang.reflect.Method) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 4 with WeaklyTypeReferencingMethod

use of org.gradle.model.internal.method.WeaklyTypeReferencingMethod in project gradle by gradle.

the class ManagedProxyClassGenerator method writeViewMethods.

private void writeViewMethods(ClassVisitor visitor, Type generatedType, Collection<ModelType<?>> viewTypes, StructBindings<?> bindings) {
    Type delegateType;
    StructSchema<?> delegateSchema = bindings.getDelegateSchema();
    if (delegateSchema != null) {
        Class<?> delegateClass = delegateSchema.getType().getRawClass();
        declareDelegateField(visitor, delegateClass);
        delegateType = Type.getType(delegateClass);
    } else {
        delegateType = null;
    }
    Multimap<String, ModelProperty<?>> viewPropertiesByNameBuilder = ArrayListMultimap.create();
    Set<Wrapper<Method>> viewMethods = Sets.newLinkedHashSet();
    for (StructSchema<?> viewSchema : bindings.getImplementedViewSchemas()) {
        for (ModelType<?> viewType : viewTypes) {
            if (viewType.equals(viewSchema.getType())) {
                for (ModelProperty<?> property : viewSchema.getProperties()) {
                    String propertyName = property.getName();
                    viewPropertiesByNameBuilder.put(propertyName, property);
                }
                for (WeaklyTypeReferencingMethod<?, ?> viewMethod : viewSchema.getAllMethods()) {
                    viewMethods.add(SIGNATURE_EQUIVALENCE.wrap(viewMethod.getMethod()));
                }
                break;
            }
        }
    }
    Class<?> viewClass = bindings.getPublicSchema().getType().getConcreteClass();
    for (Collection<ModelProperty<?>> viewProperties : viewPropertiesByNameBuilder.asMap().values()) {
        writeViewPropertyDslMethods(visitor, generatedType, viewProperties, viewClass);
    }
    for (StructMethodBinding methodBinding : bindings.getMethodBindings()) {
        WeaklyTypeReferencingMethod<?, ?> weakViewMethod = methodBinding.getViewMethod();
        Method viewMethod = weakViewMethod.getMethod();
        // Don't generate method if it's not part of the view schema
        Wrapper<Method> methodKey = SIGNATURE_EQUIVALENCE.wrap(viewMethod);
        if (!viewMethods.contains(methodKey)) {
            continue;
        }
        if (methodBinding instanceof DirectMethodBinding) {
            // TODO:LPTR What is with the "metaClass" property here?
            boolean isGetterMethod = methodBinding.getAccessorType() == GET_GETTER || methodBinding.getAccessorType() == IS_GETTER;
            if (isGetterMethod && !Modifier.isFinal(viewMethod.getModifiers()) && !viewMethod.getName().equals("getMetaClass")) {
                writeNonAbstractMethodWrapper(visitor, generatedType, viewClass, viewMethod);
            }
        } else if (methodBinding instanceof BridgeMethodBinding) {
            writeBridgeMethod(visitor, generatedType, viewMethod);
        } else if (methodBinding instanceof DelegateMethodBinding) {
            writeDelegatingMethod(visitor, generatedType, delegateType, viewMethod);
        } else if (methodBinding instanceof ManagedPropertyMethodBinding) {
            ManagedPropertyMethodBinding propertyBinding = (ManagedPropertyMethodBinding) methodBinding;
            ManagedProperty<?> managedProperty = bindings.getManagedProperty(propertyBinding.getPropertyName());
            String propertyName = managedProperty.getName();
            Class<?> propertyClass = managedProperty.getType().getRawClass();
            WeaklyTypeReferencingMethod<?, ?> propertyAccessor = propertyBinding.getViewMethod();
            switch(propertyBinding.getAccessorType()) {
                case GET_GETTER:
                case IS_GETTER:
                    writeGetter(visitor, generatedType, propertyName, propertyClass, propertyAccessor);
                    break;
                case SETTER:
                    writeSetter(visitor, generatedType, propertyName, propertyClass, propertyAccessor);
                    break;
                default:
                    throw new AssertionError();
            }
        } else {
            throw new AssertionError();
        }
    }
}
Also used : Wrapper(com.google.common.base.Equivalence.Wrapper) DirectMethodBinding(org.gradle.model.internal.manage.binding.DirectMethodBinding) Method(java.lang.reflect.Method) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) BridgeMethodBinding(org.gradle.model.internal.manage.binding.BridgeMethodBinding) ManagedPropertyMethodBinding(org.gradle.model.internal.manage.binding.ManagedPropertyMethodBinding) DelegateMethodBinding(org.gradle.model.internal.manage.binding.DelegateMethodBinding) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) ManagedProperty(org.gradle.model.internal.manage.binding.ManagedProperty) Type(org.objectweb.asm.Type) PropertyAccessorType(org.gradle.internal.reflect.PropertyAccessorType) ModelType(org.gradle.model.internal.type.ModelType) StructMethodBinding(org.gradle.model.internal.manage.binding.StructMethodBinding) ModelProperty(org.gradle.model.internal.manage.schema.ModelProperty)

Example 5 with WeaklyTypeReferencingMethod

use of org.gradle.model.internal.method.WeaklyTypeReferencingMethod in project gradle by gradle.

the class ManagedProxyClassGenerator method writeTypeConvertingSetter.

// the overload of type Object for Groovy coercions:  public void setFoo(Object foo)
private void writeTypeConvertingSetter(ClassVisitor visitor, Type generatedType, Class<?> viewClass, ModelProperty<?> property) {
    WeaklyTypeReferencingMethod<?, ?> weakSetter = property.getAccessor(SETTER);
    // There is no setter for this property
    if (weakSetter == null) {
        return;
    }
    if (!(property.getSchema() instanceof ScalarValueSchema)) {
        return;
    }
    Class<?> propertyClass = property.getType().getConcreteClass();
    Type propertyType = Type.getType(propertyClass);
    Class<?> boxedClass = propertyClass.isPrimitive() ? BOXED_TYPES.get(propertyClass) : propertyClass;
    Type boxedType = Type.getType(boxedClass);
    Method setter = weakSetter.getMethod();
    MethodVisitor methodVisitor = declareMethod(visitor, setter.getName(), SET_OBJECT_PROPERTY_DESCRIPTOR, SET_OBJECT_PROPERTY_DESCRIPTOR);
    putThisOnStack(methodVisitor);
    putTypeConverterFieldValueOnStack(methodVisitor, generatedType);
    // Object converted = $typeConverter.convert(foo, Float.class, false);
    // put var #1 ('foo') on the stack
    methodVisitor.visitVarInsn(ALOAD, 1);
    // push the constant Class onto the stack
    methodVisitor.visitLdcInsn(boxedType);
    // push int 1 or 0 (interpreted as true or false) onto the stack
    methodVisitor.visitInsn(propertyClass.isPrimitive() ? ICONST_1 : ICONST_0);
    Label startTry = new Label();
    methodVisitor.visitLabel(startTry);
    methodVisitor.visitMethodInsn(INVOKEINTERFACE, TYPE_CONVERTER_TYPE.getInternalName(), "convert", COERCE_TO_SCALAR_DESCRIPTOR, true);
    Label endTry = new Label();
    methodVisitor.visitLabel(endTry);
    methodVisitor.visitTypeInsn(CHECKCAST, boxedType.getInternalName());
    if (propertyClass.isPrimitive()) {
        unboxType(methodVisitor, propertyClass);
    }
    // invoke the typed setter
    methodVisitor.visitMethodInsn(INVOKEVIRTUAL, generatedType.getInternalName(), setter.getName(), Type.getMethodDescriptor(Type.VOID_TYPE, propertyType), false);
    methodVisitor.visitInsn(RETURN);
    // catch(TypeConversionException e) { throw ... }
    Label startCatch = new Label();
    methodVisitor.visitLabel(startCatch);
    methodVisitor.visitTryCatchBlock(startTry, endTry, startCatch, TYPE_CONVERSION_EXCEPTION_TYPE.getInternalName());
    // store thrown exception
    methodVisitor.visitVarInsn(ASTORE, 2);
    putClassOnStack(methodVisitor, viewClass);
    methodVisitor.visitLdcInsn(property.getName());
    putFirstMethodArgumentOnStack(methodVisitor);
    methodVisitor.visitVarInsn(ALOAD, 2);
    methodVisitor.visitMethodInsn(INVOKESTATIC, Type.getInternalName(ManagedProxyClassGenerator.class), "propertyValueConvertFailure", Type.getMethodDescriptor(Type.VOID_TYPE, CLASS_TYPE, STRING_TYPE, OBJECT_TYPE, TYPE_CONVERSION_EXCEPTION_TYPE), false);
    finishVisitingMethod(methodVisitor);
}
Also used : Type(org.objectweb.asm.Type) PropertyAccessorType(org.gradle.internal.reflect.PropertyAccessorType) ModelType(org.gradle.model.internal.type.ModelType) Label(org.objectweb.asm.Label) ScalarValueSchema(org.gradle.model.internal.manage.schema.ScalarValueSchema) Method(java.lang.reflect.Method) WeaklyTypeReferencingMethod(org.gradle.model.internal.method.WeaklyTypeReferencingMethod) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

Method (java.lang.reflect.Method)6 WeaklyTypeReferencingMethod (org.gradle.model.internal.method.WeaklyTypeReferencingMethod)6 PropertyAccessorType (org.gradle.internal.reflect.PropertyAccessorType)5 ModelType (org.gradle.model.internal.type.ModelType)4 Type (org.objectweb.asm.Type)4 MethodVisitor (org.objectweb.asm.MethodVisitor)3 Wrapper (com.google.common.base.Equivalence.Wrapper)2 ModelProperty (org.gradle.model.internal.manage.schema.ModelProperty)2 ScalarValueSchema (org.gradle.model.internal.manage.schema.ScalarValueSchema)2 Label (org.objectweb.asm.Label)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 TreeSet (java.util.TreeSet)1 InvalidModelRuleDeclarationException (org.gradle.model.InvalidModelRuleDeclarationException)1 BridgeMethodBinding (org.gradle.model.internal.manage.binding.BridgeMethodBinding)1 DelegateMethodBinding (org.gradle.model.internal.manage.binding.DelegateMethodBinding)1 DirectMethodBinding (org.gradle.model.internal.manage.binding.DirectMethodBinding)1 ManagedProperty (org.gradle.model.internal.manage.binding.ManagedProperty)1 ManagedPropertyMethodBinding (org.gradle.model.internal.manage.binding.ManagedPropertyMethodBinding)1 StructMethodBinding (org.gradle.model.internal.manage.binding.StructMethodBinding)1