@Override public void makeSingleArgumentCall( final Expression receiver, final String message, final Expression arguments) { TypeChooser typeChooser = controller.getTypeChooser(); ClassNode classNode = controller.getClassNode(); ClassNode rType = typeChooser.resolveType(receiver, classNode); ClassNode aType = typeChooser.resolveType(arguments, classNode); if (trySubscript(receiver, message, arguments, rType, aType)) { return; } // new try with flow type instead of declaration type rType = receiver.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); if (rType != null && trySubscript(receiver, message, arguments, rType, aType)) { return; } // todo: more cases throw new GroovyBugError( "At line " + receiver.getLineNumber() + " column " + receiver.getColumnNumber() + "\n" + "On receiver: " + receiver.getText() + " with message: " + message + " and arguments: " + arguments.getText() + "\n" + "This method should not have been called. Please try to create a simple example reproducing this error and file" + "a bug report at http://jira.codehaus.org/browse/GROOVY"); }
private void writeMapDotProperty( final Expression receiver, final String methodName, final MethodVisitor mv, final boolean safe) { receiver.visit(controller.getAcg()); // load receiver Label exit = new Label(); if (safe) { Label doGet = new Label(); mv.visitJumpInsn(IFNONNULL, doGet); controller.getOperandStack().remove(1); mv.visitInsn(ACONST_NULL); mv.visitJumpInsn(GOTO, exit); mv.visitLabel(doGet); receiver.visit(controller.getAcg()); } mv.visitLdcInsn(methodName); // load property name mv.visitMethodInsn( INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true); if (safe) { mv.visitLabel(exit); } controller.getOperandStack().replace(OBJECT_TYPE); }
public void visitConstructorCallExpression(ConstructorCallExpression call) { isSpecialConstructorCall = call.isSpecialCall(); super.visitConstructorCallExpression(call); isSpecialConstructorCall = false; if (!call.isUsingAnonymousInnerClass()) return; pushState(); InnerClassNode innerClass = (InnerClassNode) call.getType(); innerClass.setVariableScope(currentScope); for (MethodNode method : innerClass.getMethods()) { Parameter[] parameters = method.getParameters(); if (parameters.length == 0) parameters = null; // null means no implicit "it" ClosureExpression cl = new ClosureExpression(parameters, method.getCode()); visitClosureExpression(cl); } for (FieldNode field : innerClass.getFields()) { final Expression expression = field.getInitialExpression(); if (expression != null) { expression.visit(this); } } for (Statement statement : innerClass.getObjectInitializerStatements()) { statement.visit(this); } markClosureSharedVariables(); popState(); }
protected Expression transformPropertyExpression(PropertyExpression pe) { boolean oldInPropertyExpression = inPropertyExpression; Expression oldFoundArgs = foundArgs; Expression oldFoundConstant = foundConstant; inPropertyExpression = true; foundArgs = null; foundConstant = null; Expression objectExpression = transform(pe.getObjectExpression()); boolean candidate = false; if (objectExpression instanceof MethodCallExpression) { candidate = ((MethodCallExpression) objectExpression).isImplicitThis(); } if (foundArgs != null && foundConstant != null && candidate) { Expression result = findStaticMethodImportFromModule(foundConstant, foundArgs); if (result != null) { objectExpression = result; objectExpression.setSourcePosition(pe); } } inPropertyExpression = oldInPropertyExpression; foundArgs = oldFoundArgs; foundConstant = oldFoundConstant; pe.setObjectExpression(objectExpression); return pe; }
private Expression transformInlineConstants(Expression exp) { if (exp instanceof PropertyExpression) { PropertyExpression pe = (PropertyExpression) exp; if (pe.getObjectExpression() instanceof ClassExpression) { ClassExpression ce = (ClassExpression) pe.getObjectExpression(); ClassNode type = ce.getType(); if (type.isEnum()) return exp; Expression constant = findConstant(type.getField(pe.getPropertyAsString())); // GRECLIPSE edit // if (constant != null) return constant; if (constant != null) { String name = pe.getText().replace('$', '.'); Object alias = pe.getNodeMetaData("static.import.alias"); if (alias != null && !alias.equals(pe.getPropertyAsString())) { name += " as " + alias; } // store the qualified name to facilitate organizing static imports constant.setNodeMetaData("static.import", name); return constant; } // GRECLIPSE end } } else if (exp instanceof ListExpression) { ListExpression le = (ListExpression) exp; ListExpression result = new ListExpression(); for (Expression e : le.getExpressions()) { result.addExpression(transformInlineConstants(e)); } return result; } return exp; }
public void visitAnnotations(AnnotatedNode node) { List<AnnotationNode> annotations = node.getAnnotations(); if (annotations.isEmpty()) return; for (AnnotationNode an : annotations) { // skip built-in properties if (an.isBuiltIn()) continue; for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) { Expression annMemberValue = member.getValue(); annMemberValue.visit(this); } } }
private List createPropertiesForHasManyExpression(Expression e, ClassNode classNode) { List properties = new ArrayList(); if (e instanceof MapExpression) { MapExpression me = (MapExpression) e; List mapEntries = me.getMapEntryExpressions(); for (Iterator j = mapEntries.iterator(); j.hasNext(); ) { MapEntryExpression mee = (MapEntryExpression) j.next(); Expression keyExpression = mee.getKeyExpression(); String key = keyExpression.getText(); addAssociationForKey(key, properties, classNode); } } return properties; }
public Expression transform(Expression exp) { if (exp == null) return null; if (exp.getClass() == VariableExpression.class) { return transformVariableExpression((VariableExpression) exp); } if (exp.getClass() == BinaryExpression.class) { return transformBinaryExpression((BinaryExpression) exp); } if (exp.getClass() == PropertyExpression.class) { return transformPropertyExpression((PropertyExpression) exp); } if (exp.getClass() == MethodCallExpression.class) { return transformMethodCallExpression((MethodCallExpression) exp); } if (exp.getClass() == ClosureExpression.class) { return transformClosureExpression((ClosureExpression) exp); } if (exp.getClass() == ConstructorCallExpression.class) { return transformConstructorCallExpression((ConstructorCallExpression) exp); } if (exp.getClass() == ArgumentListExpression.class) { Expression result = exp.transformExpression(this); if (inPropertyExpression) { foundArgs = result; } return result; } if (exp instanceof ConstantExpression) { Expression result = exp.transformExpression(this); if (inPropertyExpression) { foundConstant = result; } if (inAnnotation && exp instanceof AnnotationConstantExpression) { ConstantExpression ce = (ConstantExpression) result; if (ce.getValue() instanceof AnnotationNode) { // replicate a little bit of AnnotationVisitor here // because we can't wait until later to do this AnnotationNode an = (AnnotationNode) ce.getValue(); Map<String, Expression> attributes = an.getMembers(); for (Map.Entry<String, Expression> entry : attributes.entrySet()) { Expression attrExpr = transform(entry.getValue()); entry.setValue(attrExpr); } } } return result; } return exp.transformExpression(this); }
@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; }
private void writeArrayGet( final Expression receiver, final Expression arguments, final ClassNode rType, final ClassNode aType) { OperandStack operandStack = controller.getOperandStack(); int m1 = operandStack.getStackLength(); // visit receiver receiver.visit(controller.getAcg()); // visit arguments as array index arguments.visit(controller.getAcg()); operandStack.doGroovyCast(int_TYPE); int m2 = operandStack.getStackLength(); // array access controller.getMethodVisitor().visitInsn(AALOAD); operandStack.replace(rType.getComponentType(), m2 - m1); }
private Expression transformMapEntryExpression( MapEntryExpression me, ClassNode constructorCallType) { Expression key = me.getKeyExpression(); Expression value = me.getValueExpression(); ModuleNode module = currentClass.getModule(); if (module != null && key instanceof ConstantExpression) { Map<String, ImportNode> importNodes = module.getStaticImports(); if (importNodes.containsKey(key.getText())) { ImportNode importNode = importNodes.get(key.getText()); if (importNode.getType().equals(constructorCallType)) { String newKey = importNode.getFieldName(); return new MapEntryExpression( new ConstantExpression(newKey), value.transformExpression(this)); } } } return me; }
/** * Given a method call, first checks that it's a static method call, and if it is, returns the * class node for the receiver. For example, with the following code: <code></code>Person.findAll * { ... }</code>, it would return the class node for <i>Person</i>. If it's not a static method * call, returns null. * * @param call a method call * @return null if it's not a static method call, or the class node for the receiver instead. */ public ClassNode extractStaticReceiver(MethodCall call) { if (call instanceof StaticMethodCallExpression) { return ((StaticMethodCallExpression) call).getOwnerType(); } else if (call instanceof MethodCallExpression) { Expression objectExpr = ((MethodCallExpression) call).getObjectExpression(); if (objectExpr instanceof ClassExpression && ClassHelper.CLASS_Type.equals(objectExpr.getType())) { GenericsType[] genericsTypes = objectExpr.getType().getGenericsTypes(); if (genericsTypes != null && genericsTypes.length == 1) { return genericsTypes[0].getType(); } } if (objectExpr instanceof ClassExpression) { return objectExpr.getType(); } } return null; }
private Statement createConstructorStatementCollection(FieldNode fNode) { final Expression fieldExpr = new VariableExpression(fNode); Expression initExpr = fNode.getInitialValueExpression(); if (initExpr == null) initExpr = new ConstantExpression(null); Expression collection = findArg(fNode.getName()); ClassNode fieldType = fieldExpr.getType(); return new IfStatement( equalsNullExpr(collection), new IfStatement( equalsNullExpr(initExpr), new EmptyStatement(), assignStatement(fieldExpr, cloneCollectionExpr(initExpr))), new IfStatement( isInstanceOf(collection, CLONEABLE_TYPE), assignStatement( fieldExpr, cloneCollectionExpr(cloneArrayOrCloneableExpr(collection, fieldType))), assignStatement(fieldExpr, cloneCollectionExpr(collection)))); }
@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; }
private void validateFields(BlockStatement block) { Validation.Option mode = getEnumMemberValue( getAnnotation(annotatedClass, VALIDATION_ANNOTATION), "option", Validation.Option.class, Validation.Option.IGNORE_UNMARKED); for (FieldNode fieldNode : annotatedClass.getFields()) { if (shouldFieldBeIgnoredForValidation(fieldNode)) continue; ClosureExpression validationClosure = createGroovyTruthClosureExpression(block.getVariableScope()); String message = null; AnnotationNode validateAnnotation = getAnnotation(fieldNode, VALIDATE_ANNOTATION); if (validateAnnotation != null) { message = getMemberStringValue( validateAnnotation, "message", "'" + fieldNode.getName() + "' must be set!"); Expression member = validateAnnotation.getMember("value"); if (member instanceof ClassExpression) { ClassNode memberType = member.getType(); if (memberType.equals(ClassHelper.make(Validate.Ignore.class))) continue; else if (!memberType.equals(ClassHelper.make(Validate.GroovyTruth.class))) { addError( "value of Validate must be either Validate.GroovyTruth, Validate.Ignore or a closure.", fieldNode); } } else if (member instanceof ClosureExpression) { validationClosure = (ClosureExpression) member; } } if (validateAnnotation != null || mode == Validation.Option.VALIDATE_UNMARKED) { block.addStatement( new AssertStatement( new BooleanExpression( callX(validationClosure, "call", args(varX(fieldNode.getName())))), message == null ? ConstantExpression.NULL : new ConstantExpression(message))); } } }
private List<String> getKnownImmutableClasses(AnnotationNode node) { final ArrayList<String> immutableClasses = new ArrayList<String>(); final Expression expression = node.getMember(MEMBER_KNOWN_IMMUTABLE_CLASSES); if (expression == null) return immutableClasses; if (!(expression instanceof ListExpression)) { addError( "Use the Groovy list notation [el1, el2] to specify known immutable classes via \"" + MEMBER_KNOWN_IMMUTABLE_CLASSES + "\"", node); return immutableClasses; } final ListExpression listExpression = (ListExpression) expression; for (Expression listItemExpression : listExpression.getExpressions()) { if (listItemExpression instanceof ClassExpression) { immutableClasses.add(listItemExpression.getType().getName()); } } return immutableClasses; }
protected Expression transformPropertyExpression(PropertyExpression pe) { if (currentMethod != null && currentMethod.isStatic() && pe.getObjectExpression() instanceof VariableExpression && ((VariableExpression) pe.getObjectExpression()).isSuperExpression()) { PropertyExpression pexp = new PropertyExpression( new ClassExpression(currentClass.getSuperClass()), transform(pe.getProperty())); pexp.setSourcePosition(pe); return pexp; } boolean oldInPropertyExpression = inPropertyExpression; Expression oldFoundArgs = foundArgs; Expression oldFoundConstant = foundConstant; inPropertyExpression = true; foundArgs = null; foundConstant = null; Expression objectExpression = transform(pe.getObjectExpression()); boolean candidate = false; if (objectExpression instanceof MethodCallExpression) { candidate = ((MethodCallExpression) objectExpression).isImplicitThis(); } if (foundArgs != null && foundConstant != null && candidate) { Expression result = findStaticMethodImportFromModule(foundConstant, foundArgs); if (result != null) { objectExpression = result; objectExpression.setSourcePosition(pe); } } inPropertyExpression = oldInPropertyExpression; foundArgs = oldFoundArgs; foundConstant = oldFoundConstant; pe.setObjectExpression(objectExpression); return pe; }
boolean makeGetField( final Expression receiver, final ClassNode receiverType, final String fieldName, final boolean implicitThis, final boolean samePackage) { FieldNode field = receiverType.getField(fieldName); // direct access is allowed if we are in the same class as the declaring class // or we are in an inner class if (field != null && isDirectAccessAllowed(field, controller.getClassNode(), samePackage)) { CompileStack compileStack = controller.getCompileStack(); MethodVisitor mv = controller.getMethodVisitor(); if (field.isStatic()) { mv.visitFieldInsn( GETSTATIC, BytecodeHelper.getClassInternalName(field.getOwner()), fieldName, BytecodeHelper.getTypeDescription(field.getOriginType())); controller.getOperandStack().push(field.getOriginType()); } else { if (implicitThis) { compileStack.pushImplicitThis(implicitThis); } receiver.visit(controller.getAcg()); if (implicitThis) compileStack.popImplicitThis(); if (!controller.getOperandStack().getTopOperand().isDerivedFrom(field.getOwner())) { mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(field.getOwner())); } mv.visitFieldInsn( GETFIELD, BytecodeHelper.getClassInternalName(field.getOwner()), fieldName, BytecodeHelper.getTypeDescription(field.getOriginType())); } controller.getOperandStack().replace(field.getOriginType()); return true; } ClassNode superClass = receiverType.getSuperClass(); if (superClass != null) { return makeGetField(receiver, superClass, fieldName, implicitThis, false); } return false; }
public ClosureExpression(Parameter[] parameters, Statement code) { this.parameters = parameters; this.code = code; super.setType(ClassHelper.CLOSURE_TYPE.getPlainNodeReference()); }
@Override public void makeGetPropertySite( Expression receiver, final String methodName, final boolean safe, final boolean implicitThis) { Object dynamic = receiver.getNodeMetaData(StaticCompilationMetadataKeys.RECEIVER_OF_DYNAMIC_PROPERTY); if (dynamic != null) { MethodNode target = safe ? INVOKERHELPER_GETPROPERTYSAFE_METHOD : INVOKERHELPER_GETPROPERTY_METHOD; MethodCallExpression mce = new MethodCallExpression( new ClassExpression(INVOKERHELPER_TYPE), target.getName(), new ArgumentListExpression(receiver, new ConstantExpression(methodName))); mce.setSafe(false); mce.setImplicitThis(false); mce.setMethodTarget(target); mce.visit(controller.getAcg()); return; } TypeChooser typeChooser = controller.getTypeChooser(); ClassNode classNode = controller.getClassNode(); ClassNode receiverType = (ClassNode) receiver.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER); if (receiverType == null) { receiverType = typeChooser.resolveType(receiver, classNode); } Object type = receiver.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); if (type == null && receiver instanceof VariableExpression) { Variable variable = ((VariableExpression) receiver).getAccessedVariable(); if (variable instanceof Expression) { type = ((Expression) variable).getNodeMetaData(StaticTypesMarker.INFERRED_TYPE); } } if (type != null) { // in case a "flow type" is found, it is preferred to use it instead of // the declaration type receiverType = (ClassNode) type; } boolean isClassReceiver = false; if (isClassClassNodeWrappingConcreteType(receiverType)) { isClassReceiver = true; receiverType = receiverType.getGenericsTypes()[0].getType(); } MethodVisitor mv = controller.getMethodVisitor(); if (receiverType.isArray() && methodName.equals("length")) { receiver.visit(controller.getAcg()); ClassNode arrayGetReturnType = typeChooser.resolveType(receiver, classNode); controller.getOperandStack().doGroovyCast(arrayGetReturnType); mv.visitInsn(ARRAYLENGTH); controller.getOperandStack().replace(int_TYPE); return; } else if ((receiverType.implementsInterface(COLLECTION_TYPE) || COLLECTION_TYPE.equals(receiverType)) && ("size".equals(methodName) || "length".equals(methodName))) { MethodCallExpression expr = new MethodCallExpression(receiver, "size", ArgumentListExpression.EMPTY_ARGUMENTS); expr.setMethodTarget(COLLECTION_SIZE_METHOD); expr.setImplicitThis(implicitThis); expr.setSafe(safe); expr.visit(controller.getAcg()); return; } if (makeGetPropertyWithGetter(receiver, receiverType, methodName, safe, implicitThis)) return; if (makeGetField( receiver, receiverType, methodName, implicitThis, samePackages(receiverType.getPackageName(), classNode.getPackageName()))) return; if (receiverType.isEnum()) { mv.visitFieldInsn( GETSTATIC, BytecodeHelper.getClassInternalName(receiverType), methodName, BytecodeHelper.getTypeDescription(receiverType)); controller.getOperandStack().push(receiverType); return; } if (receiver instanceof ClassExpression) { if (makeGetField( receiver, receiver.getType(), methodName, implicitThis, samePackages(receiver.getType().getPackageName(), classNode.getPackageName()))) return; if (makeGetPropertyWithGetter(receiver, receiver.getType(), methodName, safe, implicitThis)) return; if (makeGetPrivateFieldWithBridgeMethod( receiver, receiver.getType(), methodName, safe, implicitThis)) return; } if (isClassReceiver) { // we are probably looking for a property of the class if (makeGetPropertyWithGetter(receiver, CLASS_Type, methodName, safe, implicitThis)) return; if (makeGetField(receiver, CLASS_Type, methodName, false, true)) return; } if (makeGetPrivateFieldWithBridgeMethod(receiver, receiverType, methodName, safe, implicitThis)) return; // GROOVY-5580, it is still possible that we're calling a superinterface property String getterName = "get" + MetaClassHelper.capitalize(methodName); if (receiverType.isInterface()) { Set<ClassNode> allInterfaces = receiverType.getAllInterfaces(); MethodNode getterMethod = null; for (ClassNode anInterface : allInterfaces) { getterMethod = anInterface.getGetterMethod(getterName); if (getterMethod != null) break; } // GROOVY-5585 if (getterMethod == null) { getterMethod = OBJECT_TYPE.getGetterMethod(getterName); } if (getterMethod != null) { MethodCallExpression call = new MethodCallExpression(receiver, getterName, ArgumentListExpression.EMPTY_ARGUMENTS); call.setMethodTarget(getterMethod); call.setImplicitThis(false); call.setSourcePosition(receiver); call.visit(controller.getAcg()); return; } } // GROOVY-5568, we would be facing a DGM call, but instead of foo.getText(), have foo.text List<MethodNode> methods = findDGMMethodsByNameAndArguments( controller.getSourceUnit().getClassLoader(), receiverType, getterName, ClassNode.EMPTY_ARRAY); if (!methods.isEmpty()) { List<MethodNode> methodNodes = chooseBestMethod(receiverType, methods, ClassNode.EMPTY_ARRAY); if (methodNodes.size() == 1) { MethodNode getter = methodNodes.get(0); MethodCallExpression call = new MethodCallExpression(receiver, getterName, ArgumentListExpression.EMPTY_ARGUMENTS); call.setMethodTarget(getter); call.setImplicitThis(false); call.setSourcePosition(receiver); call.visit(controller.getAcg()); return; } } boolean isStaticProperty = receiver instanceof ClassExpression && (receiverType.isDerivedFrom(receiver.getType()) || receiverType.implementsInterface(receiver.getType())); if (!isStaticProperty) { if (receiverType.implementsInterface(MAP_TYPE) || MAP_TYPE.equals(receiverType)) { // for maps, replace map.foo with map.get('foo') writeMapDotProperty(receiver, methodName, mv, safe); return; } if (receiverType.implementsInterface(LIST_TYPE) || LIST_TYPE.equals(receiverType)) { writeListDotProperty(receiver, methodName, mv, safe); return; } } controller .getSourceUnit() .addError( new SyntaxException( "Access to " + (receiver instanceof ClassExpression ? receiver.getType() : receiverType) .toString(false) + "#" + methodName + " is forbidden", receiver.getLineNumber(), receiver.getColumnNumber(), receiver.getLastLineNumber(), receiver.getLastColumnNumber())); controller.getMethodVisitor().visitInsn(ACONST_NULL); controller.getOperandStack().push(OBJECT_TYPE); }
private Expression findStaticFieldOrPropAccessorImportFromModule(String name) { ModuleNode module = currentClass.getModule(); if (module == null) return null; Map<String, ImportNode> importNodes = module.getStaticImports(); Expression expression = null; String accessorName = getAccessorName(name); // look for one of these: // import static MyClass.setProp [as setOtherProp] // import static MyClass.getProp [as getOtherProp] // when resolving prop reference if (importNodes.containsKey(accessorName)) { ImportNode importNode = importNodes.get(accessorName); expression = findStaticPropertyAccessorByFullName(importNode.getType(), importNode.getFieldName()); if (expression != null) return expression; expression = findStaticPropertyAccessor( importNode.getType(), getPropNameForAccessor(importNode.getFieldName())); if (expression != null) return expression; } if (accessorName.startsWith("get")) { accessorName = "is" + accessorName.substring(3); if (importNodes.containsKey(accessorName)) { ImportNode importNode = importNodes.get(accessorName); expression = findStaticPropertyAccessorByFullName(importNode.getType(), importNode.getFieldName()); if (expression != null) return expression; expression = findStaticPropertyAccessor( importNode.getType(), getPropNameForAccessor(importNode.getFieldName())); if (expression != null) return expression; } } // look for one of these: // import static MyClass.prop [as otherProp] // when resolving prop or field reference if (importNodes.containsKey(name)) { ImportNode importNode = importNodes.get(name); // GRECLIPSE add try { if (!isReconcile) { // GRECLIPSE end expression = findStaticPropertyAccessor(importNode.getType(), importNode.getFieldName()); if (expression != null) return expression; // GRECLIPSE add } // end expression = findStaticField(importNode.getType(), importNode.getFieldName()); if (expression != null) return expression; // GRECLIPSE add } finally { // store the identifier to facilitate organizing static imports if (expression != null) expression.setNodeMetaData("static.import.alias", name); } // GRECLIPSE end } // look for one of these: // import static MyClass.* // when resolving prop or field reference for (ImportNode importNode : module.getStaticStarImports().values()) { ClassNode node = importNode.getType(); expression = findStaticPropertyAccessor(node, name); if (expression != null) return expression; expression = findStaticField(node, name); if (expression != null) return expression; } return null; }
@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; }
private void writeListDotProperty( final Expression receiver, final String methodName, final MethodVisitor mv, final boolean safe) { ClassNode componentType = (ClassNode) receiver.getNodeMetaData(StaticCompilationMetadataKeys.COMPONENT_TYPE); if (componentType == null) { componentType = OBJECT_TYPE; } // for lists, replace list.foo with: // def result = new ArrayList(list.size()) // for (e in list) { result.add (e.foo) } // result CompileStack compileStack = controller.getCompileStack(); Label exit = new Label(); if (safe) { receiver.visit(controller.getAcg()); Label doGet = new Label(); mv.visitJumpInsn(IFNONNULL, doGet); controller.getOperandStack().remove(1); mv.visitInsn(ACONST_NULL); mv.visitJumpInsn(GOTO, exit); mv.visitLabel(doGet); } Variable tmpList = new VariableExpression("tmpList", make(ArrayList.class)); int var = compileStack.defineTemporaryVariable(tmpList, false); Variable iterator = new VariableExpression("iterator", Iterator_TYPE); int it = compileStack.defineTemporaryVariable(iterator, false); Variable nextVar = new VariableExpression("next", componentType); final int next = compileStack.defineTemporaryVariable(nextVar, false); mv.visitTypeInsn(NEW, "java/util/ArrayList"); mv.visitInsn(DUP); receiver.visit(controller.getAcg()); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I", true); controller.getOperandStack().remove(1); mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "(I)V", false); mv.visitVarInsn(ASTORE, var); Label l1 = new Label(); mv.visitLabel(l1); receiver.visit(controller.getAcg()); mv.visitMethodInsn( INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;", true); controller.getOperandStack().remove(1); mv.visitVarInsn(ASTORE, it); Label l2 = new Label(); mv.visitLabel(l2); mv.visitVarInsn(ALOAD, it); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true); Label l3 = new Label(); mv.visitJumpInsn(IFEQ, l3); mv.visitVarInsn(ALOAD, it); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true); mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(componentType)); mv.visitVarInsn(ASTORE, next); Label l4 = new Label(); mv.visitLabel(l4); mv.visitVarInsn(ALOAD, var); final ClassNode finalComponentType = componentType; PropertyExpression pexp = new PropertyExpression( new BytecodeExpression() { @Override public void visit(final MethodVisitor mv) { mv.visitVarInsn(ALOAD, next); } @Override public ClassNode getType() { return finalComponentType; } }, methodName); pexp.visit(controller.getAcg()); controller.getOperandStack().box(); controller.getOperandStack().remove(1); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true); mv.visitInsn(POP); Label l5 = new Label(); mv.visitLabel(l5); mv.visitJumpInsn(GOTO, l2); mv.visitLabel(l3); mv.visitVarInsn(ALOAD, var); if (safe) { mv.visitLabel(exit); } controller.getOperandStack().push(make(ArrayList.class)); controller.getCompileStack().removeVar(next); controller.getCompileStack().removeVar(it); controller.getCompileStack().removeVar(var); }
/** * Set the source position of toSet including its property expression if it has one. * * @param toSet resulting node * @param origNode original node */ private void setSourcePosition(Expression toSet, Expression origNode) { toSet.setSourcePosition(origNode); if (toSet instanceof PropertyExpression) { ((PropertyExpression) toSet).getProperty().setSourcePosition(origNode); } }
public MethodNode getTargetMethod(final Expression expression) { return (MethodNode) expression.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET); }
protected Expression transformMethodCallExpression(MethodCallExpression mce) { Expression args = transform(mce.getArguments()); Expression method = transform(mce.getMethod()); Expression object = transform(mce.getObjectExpression()); boolean isExplicitThisOrSuper = false; if (object instanceof VariableExpression) { VariableExpression ve = (VariableExpression) object; isExplicitThisOrSuper = !mce.isImplicitThis() && (ve.getName().equals("this") || ve.getName().equals("super")); } if (mce.isImplicitThis() || isExplicitThisOrSuper) { if (mce.isImplicitThis()) { Expression ret = findStaticMethodImportFromModule(method, args); if (ret != null) { // GRECLIPSE add if (!((StaticMethodCallExpression) ret).getMethod().equals(method.getText())) { // store the identifier to facilitate organizing static imports ret.setNodeMetaData("static.import.alias", method.getText()); } // GRECLIPSE end setSourcePosition(ret, mce); return ret; } if (method instanceof ConstantExpression && !inLeftExpression) { // could be a closure field String methodName = (String) ((ConstantExpression) method).getValue(); ret = findStaticFieldOrPropAccessorImportFromModule(methodName); if (ret != null) { ret = new MethodCallExpression(ret, "call", args); setSourcePosition(ret, mce); return ret; } } } if (method instanceof ConstantExpression) { ConstantExpression ce = (ConstantExpression) method; Object value = ce.getValue(); if (value instanceof String) { String methodName = (String) value; boolean lookForPossibleStaticMethod = !methodName.equals("call"); if (currentMethod != null && !currentMethod.isStatic()) { if (currentClass.hasPossibleMethod(methodName, args)) { lookForPossibleStaticMethod = false; } } if (inSpecialConstructorCall || (lookForPossibleStaticMethod && currentClass.hasPossibleStaticMethod(methodName, args))) { StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass, methodName, args); setSourcePosition(smce, mce); return smce; } } } } MethodCallExpression result = new MethodCallExpression(object, method, args); result.setSafe(mce.isSafe()); result.setImplicitThis(mce.isImplicitThis()); result.setSpreadSafe(mce.isSpreadSafe()); result.setMethodTarget(mce.getMethodTarget()); // GROOVY-6757 result.setGenericsTypes(mce.getGenericsTypes()); setSourcePosition(result, mce); return result; }