@Override protected boolean existsProperty( final PropertyExpression pexp, final boolean checkForReadOnly, final ClassCodeVisitorSupport visitor) { Expression objectExpression = pexp.getObjectExpression(); ClassNode objectExpressionType = getType(objectExpression); final Reference<ClassNode> rType = new Reference<ClassNode>(objectExpressionType); ClassCodeVisitorSupport receiverMemoizer = new ClassCodeVisitorSupport() { @Override protected SourceUnit getSourceUnit() { return null; } public void visitField(final FieldNode node) { if (visitor != null) visitor.visitField(node); ClassNode declaringClass = node.getDeclaringClass(); if (declaringClass != null) rType.set(declaringClass); } public void visitMethod(final MethodNode node) { if (visitor != null) visitor.visitMethod(node); ClassNode declaringClass = node.getDeclaringClass(); if (declaringClass != null) rType.set(declaringClass); } @Override public void visitProperty(final PropertyNode node) { if (visitor != null) visitor.visitProperty(node); ClassNode declaringClass = node.getDeclaringClass(); if (declaringClass != null) rType.set(declaringClass); } }; boolean exists = super.existsProperty(pexp, checkForReadOnly, receiverMemoizer); if (exists) { if (objectExpression.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER) == null) { objectExpression.putNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER, rType.get()); } if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf( objectExpressionType, ClassHelper.LIST_TYPE)) { objectExpression.putNodeMetaData( COMPONENT_TYPE, inferComponentType(objectExpressionType, ClassHelper.int_TYPE)); } } return exists; }
@Override protected MethodNode findMethodOrFail( final Expression expr, final ClassNode receiver, final String name, final ClassNode... args) { MethodNode methodNode = super.findMethodOrFail(expr, receiver, name, args); if (expr instanceof BinaryExpression && methodNode != null) { expr.putNodeMetaData(BINARY_EXP_TARGET, new Object[] {methodNode, name}); } return methodNode; }
@Override public void makeGroovyObjectGetPropertySite( final Expression receiver, final String methodName, final boolean safe, final boolean implicitThis) { TypeChooser typeChooser = controller.getTypeChooser(); ClassNode classNode = controller.getClassNode(); ClassNode receiverType = typeChooser.resolveType(receiver, classNode); if (receiver instanceof VariableExpression && ((VariableExpression) receiver).isThisExpression() && !controller.isInClosure()) { receiverType = classNode; } String property = methodName; if (implicitThis) { if (controller.getInvocationWriter() instanceof StaticInvocationWriter) { MethodCallExpression currentCall = ((StaticInvocationWriter) controller.getInvocationWriter()).getCurrentCall(); if (currentCall != null && currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) != null) { property = (String) currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER); String[] props = property.split("\\."); BytecodeExpression thisLoader = new BytecodeExpression() { @Override public void visit(final MethodVisitor mv) { mv.visitVarInsn(ALOAD, 0); // load this } }; thisLoader.setType(CLOSURE_TYPE); Expression pexp = new PropertyExpression(thisLoader, new ConstantExpression(props[0]), safe); for (int i = 1, propsLength = props.length; i < propsLength; i++) { final String prop = props[i]; pexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, CLOSURE_TYPE); pexp = new PropertyExpression(pexp, prop); } pexp.visit(controller.getAcg()); return; } } } if (makeGetPropertyWithGetter(receiver, receiverType, property, safe, implicitThis)) return; if (makeGetField( receiver, receiverType, property, implicitThis, samePackages(receiverType.getPackageName(), classNode.getPackageName()))) return; MethodCallExpression call = new MethodCallExpression( receiver, "getProperty", new ArgumentListExpression(new ConstantExpression(property))); call.setImplicitThis(implicitThis); call.setSafe(safe); call.setMethodTarget(GROOVYOBJECT_GETPROPERTY_METHOD); call.visit(controller.getAcg()); return; }