Search in sources :

Example 46 with CachedClass

use of org.codehaus.groovy.reflection.CachedClass in project groovy-core by groovy.

the class MetaClassImpl method addNewInstanceMethod.

/**
     *Adds an instance method to this metaclass.
     *
     * @param method The method to be added
     */
public void addNewInstanceMethod(Method method) {
    final CachedMethod cachedMethod = CachedMethod.find(method);
    NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(cachedMethod);
    final CachedClass declaringClass = newMethod.getDeclaringClass();
    addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 47 with CachedClass

use of org.codehaus.groovy.reflection.CachedClass in project groovy-core by groovy.

the class MetaClassImpl method replaceWithMOPCalls.

private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
    // no MOP methods if not a child of GroovyObject
    if (!isGroovyObject)
        return;
    class MOPIter extends MethodIndexAction {

        boolean useThis;

        public boolean skipClass(CachedClass clazz) {
            return !useThis && clazz == theCachedClass;
        }

        public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
            if (useThis) {
                if (e.methods == null)
                    return;
                if (e.methods instanceof FastArray) {
                    FastArray methods = (FastArray) e.methods;
                    processFastArray(methods);
                } else {
                    MetaMethod method = (MetaMethod) e.methods;
                    if (method instanceof NewMetaMethod)
                        return;
                    if (useThis ^ Modifier.isPrivate(method.getModifiers()))
                        return;
                    String mopName = method.getMopName();
                    int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                    if (index >= 0) {
                        int from = index;
                        while (from > 0 && mopMethods[from - 1].getName().equals(mopName)) from--;
                        int to = index;
                        while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName)) to++;
                        int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                        if (matchingMethod != -1) {
                            e.methods = mopMethods[matchingMethod];
                        }
                    }
                }
            } else {
                if (e.methodsForSuper == null)
                    return;
                if (e.methodsForSuper instanceof FastArray) {
                    FastArray methods = (FastArray) e.methodsForSuper;
                    processFastArray(methods);
                } else {
                    MetaMethod method = (MetaMethod) e.methodsForSuper;
                    if (method instanceof NewMetaMethod)
                        return;
                    if (useThis ^ Modifier.isPrivate(method.getModifiers()))
                        return;
                    String mopName = method.getMopName();
                    // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
                    // with the highest number. If we don't, no method may be found, leading to a stack overflow
                    String[] decomposedMopName = decomposeMopName(mopName);
                    int distance = Integer.parseInt(decomposedMopName[1]);
                    while (distance > 0) {
                        String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
                        int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                        if (index >= 0) {
                            int from = index;
                            while (from > 0 && mopMethods[from - 1].getName().equals(fixedMopName)) from--;
                            int to = index;
                            while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(fixedMopName)) to++;
                            int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                            if (matchingMethod != -1) {
                                e.methodsForSuper = mopMethods[matchingMethod];
                                distance = 0;
                            }
                        }
                        distance--;
                    }
                }
            }
        }

        private String[] decomposeMopName(final String mopName) {
            int idx = mopName.indexOf("$");
            if (idx > 0) {
                int eidx = mopName.indexOf("$", idx + 1);
                if (eidx > 0) {
                    return new String[] { mopName.substring(0, idx + 1), mopName.substring(idx + 1, eidx), mopName.substring(eidx) };
                }
            }
            return new String[] { "", "0", mopName };
        }

        private void processFastArray(FastArray methods) {
            final int len = methods.size();
            final Object[] data = methods.getArray();
            for (int i = 0; i != len; ++i) {
                MetaMethod method = (MetaMethod) data[i];
                if (method instanceof NewMetaMethod)
                    continue;
                boolean isPrivate = Modifier.isPrivate(method.getModifiers());
                if (useThis ^ isPrivate)
                    continue;
                String mopName = method.getMopName();
                int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                if (index >= 0) {
                    int from = index;
                    while (from > 0 && mopMethods[from - 1].getName().equals(mopName)) from--;
                    int to = index;
                    while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName)) to++;
                    int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                    if (matchingMethod != -1) {
                        methods.set(i, mopMethods[matchingMethod]);
                    }
                }
            }
        }
    }
    MOPIter iter = new MOPIter();
    // replace all calls for super with the correct MOP method
    iter.useThis = false;
    iter.iterate();
    // replace all calls for this with the correct MOP method
    iter.useThis = true;
    iter.iterate();
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass) FastArray(org.codehaus.groovy.util.FastArray) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 48 with CachedClass

use of org.codehaus.groovy.reflection.CachedClass in project groovy-core by groovy.

the class MetaClassImpl method setupProperties.

/**
     * This will build up the property map (Map of MetaProperty objects, keyed on
     * property name).
     *
     * @param propertyDescriptors
     */
@SuppressWarnings("unchecked")
private void setupProperties(PropertyDescriptor[] propertyDescriptors) {
    if (theCachedClass.isInterface) {
        LinkedList<CachedClass> superClasses = new LinkedList<CachedClass>();
        superClasses.add(ReflectionCache.OBJECT_CLASS);
        Set interfaces = theCachedClass.getInterfaces();
        LinkedList<CachedClass> superInterfaces = new LinkedList<CachedClass>(interfaces);
        // ambiguous fields (class implementing two interfaces using the same field)
        if (superInterfaces.size() > 1) {
            Collections.sort(superInterfaces, CACHED_CLASS_NAME_COMPARATOR);
        }
        SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(theCachedClass);
        for (CachedClass iclass : superInterfaces) {
            SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(iclass);
            copyNonPrivateFields(sPropertyIndex, iPropertyIndex);
            addFields(iclass, iPropertyIndex);
        }
        addFields(theCachedClass, iPropertyIndex);
        applyPropertyDescriptors(propertyDescriptors);
        applyStrayPropertyMethods(superClasses, classPropertyIndex, true);
        makeStaticPropertyIndex();
    } else {
        LinkedList<CachedClass> superClasses = getSuperClasses();
        LinkedList<CachedClass> interfaces = new LinkedList<CachedClass>(theCachedClass.getInterfaces());
        // ambiguous fields (class implementing two interfaces using the same field)
        if (interfaces.size() > 1) {
            Collections.sort(interfaces, CACHED_CLASS_NAME_COMPARATOR);
        }
        // if this an Array, then add the special read-only "length" property
        if (theCachedClass.isArray) {
            SingleKeyHashMap map = new SingleKeyHashMap();
            map.put("length", arrayLengthProperty);
            classPropertyIndex.put(theCachedClass, map);
        }
        inheritStaticInterfaceFields(superClasses, new LinkedHashSet(interfaces));
        inheritFields(superClasses);
        applyPropertyDescriptors(propertyDescriptors);
        applyStrayPropertyMethods(superClasses, classPropertyIndex, true);
        applyStrayPropertyMethods(superClasses, classPropertyIndexForSuper, false);
        copyClassPropertyIndexForSuper(classPropertyIndexForSuper);
        makeStaticPropertyIndex();
    }
}
Also used : SingleKeyHashMap(org.codehaus.groovy.util.SingleKeyHashMap) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 49 with CachedClass

use of org.codehaus.groovy.reflection.CachedClass in project groovy-core by groovy.

the class MetaClassImpl method getCategoryMethodSetter.

private MetaMethod getCategoryMethodSetter(Class sender, String name, boolean useLongVersion) {
    List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(name);
    if (possibleGenericMethods != null) {
        for (Iterator iter = possibleGenericMethods.iterator(); iter.hasNext(); ) {
            MetaMethod mmethod = (MetaMethod) iter.next();
            if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender))
                continue;
            CachedClass[] paramTypes = mmethod.getParameterTypes();
            if (useLongVersion) {
                if (paramTypes.length == 2 && paramTypes[0].getTheClass() == String.class) {
                    return mmethod;
                }
            } else {
                if (paramTypes.length == 1)
                    return mmethod;
            }
        }
    }
    return null;
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 50 with CachedClass

use of org.codehaus.groovy.reflection.CachedClass in project groovy-core by groovy.

the class MetaClassImpl method addNewStaticMethod.

/**
     *Adds a static method to this metaclass.
     *
     * @param method The method to be added
     */
public void addNewStaticMethod(Method method) {
    final CachedMethod cachedMethod = CachedMethod.find(method);
    NewStaticMetaMethod newMethod = new NewStaticMetaMethod(cachedMethod);
    final CachedClass declaringClass = newMethod.getDeclaringClass();
    addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
}
Also used : NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Aggregations

CachedClass (org.codehaus.groovy.reflection.CachedClass)68 NewInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod)17 NewStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod)17 GeneratedMetaMethod (org.codehaus.groovy.reflection.GeneratedMetaMethod)15 ClosureMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod)15 MixinInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod)15 CachedMethod (org.codehaus.groovy.reflection.CachedMethod)13 NewMetaMethod (org.codehaus.groovy.runtime.metaclass.NewMetaMethod)13 TransformMetaMethod (org.codehaus.groovy.runtime.metaclass.TransformMetaMethod)13 SingleKeyHashMap (org.codehaus.groovy.util.SingleKeyHashMap)10 MetaMethodIndex (org.codehaus.groovy.runtime.metaclass.MetaMethodIndex)8 ClassWriter (org.objectweb.asm.ClassWriter)6 ParameterTypes (org.codehaus.groovy.reflection.ParameterTypes)4 GetBeanMethodMetaProperty (org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty)4 GetMethodMetaProperty (org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty)4 MetaMethod (groovy.lang.MetaMethod)3 FastArray (org.codehaus.groovy.util.FastArray)3 MixinInMetaClass (org.codehaus.groovy.reflection.MixinInMetaClass)2 ConvertedClosure (org.codehaus.groovy.runtime.ConvertedClosure)2 CurriedClosure (org.codehaus.groovy.runtime.CurriedClosure)2