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