use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class StaticInvocationWriter method tryBridgeMethod.
/**
* Attempts to make a direct method call on a bridge method, if it exists.
*/
protected boolean tryBridgeMethod(MethodNode target, Expression receiver, boolean implicitThis, TupleExpression args) {
ClassNode lookupClassNode;
if (target.isProtected()) {
lookupClassNode = controller.getClassNode();
if (controller.isInClosure()) {
lookupClassNode = lookupClassNode.getOuterClass();
}
} else {
lookupClassNode = target.getDeclaringClass().redirect();
}
Map<MethodNode, MethodNode> bridges = lookupClassNode.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
MethodNode bridge = bridges == null ? null : bridges.get(target);
if (bridge != null) {
Expression fixedReceiver = receiver;
ClassNode classNode = implicitThis ? controller.getClassNode() : null;
ClassNode declaringClass = bridge.getDeclaringClass();
if (implicitThis && !controller.isInClosure() && !classNode.isDerivedFrom(declaringClass) && !classNode.implementsInterface(declaringClass) && classNode instanceof InnerClassNode) {
fixedReceiver = new PropertyExpression(new ClassExpression(classNode.getOuterClass()), "this");
}
ArgumentListExpression newArgs = new ArgumentListExpression(target.isStatic() ? new ConstantExpression(null) : fixedReceiver);
for (Expression expression : args.getExpressions()) {
newArgs.addExpression(expression);
}
return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, newArgs);
}
return false;
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method visitClass.
@Override
public void visitClass(final ClassNode node) {
if (shouldSkipClassNode(node))
return;
if (extension.beforeVisitClass(node)) {
extension.afterVisitClass(node);
return;
}
Object type = node.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
if (type != null) {
// transformation has already been run on this class node
// so we'll use a silent collector in order not to duplicate errors
typeCheckingContext.pushErrorCollector();
}
typeCheckingContext.pushEnclosingClassNode(node);
Set<MethodNode> oldVisitedMethod = typeCheckingContext.alreadyVisitedMethods;
typeCheckingContext.alreadyVisitedMethods = new LinkedHashSet<MethodNode>();
super.visitClass(node);
Iterator<InnerClassNode> innerClasses = node.getInnerClasses();
while (innerClasses.hasNext()) {
InnerClassNode innerClassNode = innerClasses.next();
visitClass(innerClassNode);
}
typeCheckingContext.alreadyVisitedMethods = oldVisitedMethod;
node.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, node);
// works in a two pass sequence and we don't want to skip the second pass
for (MethodNode methodNode : node.getMethods()) {
methodNode.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
}
for (ConstructorNode constructorNode : node.getDeclaredConstructors()) {
constructorNode.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
}
extension.afterVisitClass(node);
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method findMethod.
protected List<MethodNode> findMethod(ClassNode receiver, String name, ClassNode... args) {
if (isPrimitiveType(receiver))
receiver = getWrapper(receiver);
List<MethodNode> methods;
if (!receiver.isInterface() && "<init>".equals(name)) {
methods = addGeneratedMethods(receiver, new ArrayList<MethodNode>(receiver.getDeclaredConstructors()));
if (methods.isEmpty()) {
MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
node.setDeclaringClass(receiver);
return Collections.singletonList(node);
}
} else {
methods = findMethodsWithGenerated(receiver, name);
if (receiver.isInterface()) {
collectAllInterfaceMethodsByName(receiver, name, methods);
methods.addAll(OBJECT_TYPE.getMethods(name));
}
if (typeCheckingContext.getEnclosingClosure() == null) {
// not in a closure
ClassNode parent = receiver;
while (parent instanceof InnerClassNode && !parent.isStaticClass()) {
parent = parent.getOuterClass();
methods.addAll(findMethodsWithGenerated(parent, name));
}
}
if (methods.isEmpty()) {
addArrayMethods(methods, receiver, name, args);
}
if (methods.isEmpty() && (args == null || args.length == 0)) {
// check if it's a property
String pname = extractPropertyNameFromMethodName("get", name);
if (pname == null) {
pname = extractPropertyNameFromMethodName("is", name);
}
if (pname != null) {
// we don't use property exists there because findMethod is called on super clases recursively
PropertyNode property = null;
ClassNode curNode = receiver;
while (property == null && curNode != null) {
property = curNode.getProperty(pname);
ClassNode svCur = curNode;
while (property == null && svCur instanceof InnerClassNode && !svCur.isStaticClass()) {
svCur = svCur.getOuterClass();
property = svCur.getProperty(pname);
if (property != null) {
receiver = svCur;
break;
}
}
curNode = curNode.getSuperClass();
}
if (property != null) {
MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
if (property.isStatic()) {
node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
}
node.setDeclaringClass(receiver);
return Collections.singletonList(node);
}
}
} else if (methods.isEmpty() && args != null && args.length == 1) {
// maybe we are looking for a setter ?
String pname = extractPropertyNameFromMethodName("set", name);
if (pname != null) {
ClassNode curNode = receiver;
PropertyNode property = null;
while (property == null && curNode != null) {
property = curNode.getProperty(pname);
curNode = curNode.getSuperClass();
}
if (property != null) {
ClassNode type = property.getOriginType();
if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) {
MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[] { new Parameter(type, "arg") }, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
if (property.isStatic()) {
node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
}
node.setDeclaringClass(receiver);
return Collections.singletonList(node);
}
}
}
}
}
if (methods.isEmpty()) {
// look at the interfaces, there's a chance that a method is not implemented and we should not hide the
// error from the compiler
collectAllInterfaceMethodsByName(receiver, name, methods);
}
// lookup in DGM methods too
findDGMMethodsByNameAndArguments(getTransformLoader(), receiver, name, args, methods);
List<MethodNode> chosen = chooseBestMethod(receiver, methods, args);
if (!chosen.isEmpty())
return chosen;
// GROOVY-5566
if (receiver instanceof InnerClassNode && ((InnerClassNode) receiver).isAnonymous() && methods.size() == 1 && args != null && "<init>".equals(name)) {
MethodNode constructor = methods.get(0);
if (constructor.getParameters().length == args.length) {
return methods;
}
}
if (receiver.equals(CLASS_Type) && receiver.getGenericsTypes() != null) {
List<MethodNode> result = findMethod(receiver.getGenericsTypes()[0].getType(), name, args);
if (!result.isEmpty())
return result;
}
if (ClassHelper.GSTRING_TYPE.equals(receiver))
return findMethod(ClassHelper.STRING_TYPE, name, args);
if (isBeingCompiled(receiver)) {
chosen = findMethod(GROOVY_OBJECT_TYPE, name, args);
if (!chosen.isEmpty())
return chosen;
}
return EMPTY_METHODNODE_LIST;
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class Traits method findHelpers.
static TraitHelpersTuple findHelpers(final ClassNode trait) {
ClassNode helperClassNode = null;
ClassNode fieldHelperClassNode = null;
Iterator<InnerClassNode> innerClasses = trait.redirect().getInnerClasses();
if (innerClasses != null && innerClasses.hasNext()) {
// trait defined in same source unit
while (innerClasses.hasNext()) {
ClassNode icn = innerClasses.next();
if (icn.getName().endsWith(Traits.FIELD_HELPER)) {
fieldHelperClassNode = icn;
} else if (icn.getName().endsWith(Traits.TRAIT_HELPER)) {
helperClassNode = icn;
}
}
} else {
// precompiled trait
try {
final ClassLoader classLoader = trait.getTypeClass().getClassLoader();
String helperClassName = Traits.helperClassName(trait);
helperClassNode = ClassHelper.make(classLoader.loadClass(helperClassName));
try {
fieldHelperClassNode = ClassHelper.make(classLoader.loadClass(Traits.fieldHelperClassName(trait)));
} catch (ClassNotFoundException e) {
// not a problem, the field helper may be absent
}
} catch (ClassNotFoundException e) {
throw new GroovyBugError("Couldn't find trait helper classes on compile classpath!", e);
}
}
return new TraitHelpersTuple(helperClassNode, fieldHelperClassNode);
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class InitializerStrategy method createInnerHelperClass.
private ClassNode createInnerHelperClass(ClassNode buildee, String builderClassName, int fieldsSize) {
final String fullName = buildee.getName() + "$" + builderClassName;
ClassNode builder = new InnerClassNode(buildee, fullName, PUBLIC_STATIC, OBJECT_TYPE);
GenericsType[] gtypes = new GenericsType[fieldsSize];
for (int i = 0; i < gtypes.length; i++) {
gtypes[i] = makePlaceholder(i);
}
builder.setGenericsTypes(gtypes);
return builder;
}
Aggregations