/** * Snoops through the declaring class and all parents looking for methods * * <ul> * <li><code>public String getMessage(java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[])</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List)</code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.lang.String) * </code> * <li><code> * public String getMessage(java.lang.String, java.lang.Object[], java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.List, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.Map, java.lang.String, java.util.Locale) * </code> * </ul> * * If any are defined all must be defined or a compilation error results. * * @param declaringClass the class to search * @param sourceUnit the source unit, for error reporting. {@code @NotNull}. * @return true if property change support should be added */ protected static boolean needsMessageSource(ClassNode declaringClass, SourceUnit sourceUnit) { boolean found = false; ClassNode consideredClass = declaringClass; while (consideredClass != null) { for (MethodNode method : consideredClass.getMethods()) { // just check length, MOP will match it up found = method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 1; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 2; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 3; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 4; if (found) return false; } consideredClass = consideredClass.getSuperClass(); } if (found) { sourceUnit .getErrorCollector() .addErrorAndContinue( new SimpleMessage( "@MessageSourceAware cannot be processed on " + declaringClass.getName() + " because some but not all of variants of getMessage() were declared in the current class or super classes.", sourceUnit)); return false; } return true; }
/* * @see ICpuModel#setCallersCalleesTarget(IMethodNode) */ @Override public void setCallersCalleesTarget(IMethodNode targetMethod) { callers.clear(); callees.clear(); this.callersCalleesTarget = targetMethod; String thread = getThread(targetMethod); List<CallTreeNode> frameRootNodes = getFrameRootNodes(thread); if (frameRootNodes.isEmpty() || targetMethod == null) { notifyModelChanged(new CpuModelEvent(CpuModelState.CallersCalleesTargetChanged)); return; } List<String> callerNames = new ArrayList<String>(); List<String> calleeNames = new ArrayList<String>(); refreshCallersCallees(callerNames, calleeNames, frameRootNodes, targetMethod.getName()); List<MethodNode> methodNodes = getMethodNodes(thread); for (MethodNode methodNode : methodNodes) { if (callerNames.contains(methodNode.getName())) { callers.add(methodNode); } if (calleeNames.contains(methodNode.getName())) { callees.add(methodNode); } } notifyModelChanged(new CpuModelEvent(CpuModelState.CallersCalleesTargetChanged)); }
private void visitConstructorOrMethod(MethodNode node, int methodTarget) { visitAnnotations(node, methodTarget); for (int i = 0; i < node.getParameters().length; i++) { Parameter parameter = node.getParameters()[i]; visitAnnotations(parameter, AnnotationNode.PARAMETER_TARGET); } if (this.currentClass.isAnnotationDefinition() && !node.isStaticConstructor()) { ErrorCollector errorCollector = new ErrorCollector(this.source.getConfiguration()); AnnotationVisitor visitor = new AnnotationVisitor(this.source, errorCollector); visitor.setReportClass(currentClass); visitor.checkReturnType(node.getReturnType(), node); if (node.getParameters().length > 0) { addError("Annotation members may not have parameters.", node.getParameters()[0]); } if (node.getExceptions().length > 0) { addError("Annotation members may not have a throws clause.", node.getExceptions()[0]); } ReturnStatement code = (ReturnStatement) node.getCode(); if (code != null) { visitor.visitExpression(node.getName(), code.getExpression(), node.getReturnType()); visitor.checkCircularReference(currentClass, node.getReturnType(), code.getExpression()); } this.source.getErrorCollector().addCollectorContents(errorCollector); } }
public void removeMethod(MethodNode node) { ClassNode base = redirect(); if (!base.methodsList.isEmpty()) { base.methodsList.remove(node); } base.methods.remove(node.getName(), node); }
/** * Main entry point for the calling the TestForTransformation programmatically. * * @param classNode The class node that represents th test * @param ce The class expression that represents the class to test */ public void testFor(ClassNode classNode, ClassExpression ce) { boolean junit3Test = isJunit3Test(classNode); // make sure the 'log' property is not the one from GroovyTestCase FieldNode log = classNode.getField("log"); if (log == null || log.getDeclaringClass().equals(GROOVY_TEST_CASE_CLASS)) { LoggingTransformer.addLogField(classNode, classNode.getName()); } boolean isSpockTest = isSpockTest(classNode); if (!isSpockTest && !junit3Test) { // assume JUnit 4 Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap(); for (String methodName : declaredMethodsMap.keySet()) { MethodNode methodNode = declaredMethodsMap.get(methodName); if (isCandidateMethod(methodNode) && methodNode.getName().startsWith("test")) { if (methodNode.getAnnotations().size() == 0) { methodNode.addAnnotation(TEST_ANNOTATION); } } } } final MethodNode methodToAdd = weaveMock(classNode, ce, true); if (methodToAdd != null && junit3Test) { addMethodCallsToMethod(classNode, SET_UP_METHOD, Arrays.asList(methodToAdd)); } }
public void addMethod(MethodNode node) { node.setDeclaringClass(this); ClassNode base = redirect(); if (base.methodsList.isEmpty()) { base.methodsList = new ArrayList<MethodNode>(); } base.methodsList.add(node); base.methods.put(node.getName(), node); }
private void visitMethodNode(MethodNode methodNode) { if (methodNode.isSyntheticPublic()) revertVisibility(methodNode); else throw new RuntimeException( "Can't use " + MY_TYPE_NAME + " for method '" + methodNode.getName() + "' which has explicit visibility."); }
/** * This method is used to add "bridge" methods for private methods of an inner/outer class, so * that the outer class is capable of calling them. It does basically the same job as access$000 * like methods in Java. * * @param node an inner/outer class node for which to generate bridge methods */ @SuppressWarnings("unchecked") private void addPrivateBridgeMethods(final ClassNode node) { Set<ASTNode> accessedMethods = (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS); if (accessedMethods == null) return; List<MethodNode> methods = new ArrayList<MethodNode>(node.getAllDeclaredMethods()); Map<MethodNode, MethodNode> privateBridgeMethods = (Map<MethodNode, MethodNode>) node.getNodeMetaData(PRIVATE_BRIDGE_METHODS); if (privateBridgeMethods != null) { // private bridge methods already added return; } privateBridgeMethods = new HashMap<MethodNode, MethodNode>(); int i = -1; final int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC; for (MethodNode method : methods) { if (accessedMethods.contains(method)) { i++; Parameter[] methodParameters = method.getParameters(); Parameter[] newParams = new Parameter[methodParameters.length + 1]; System.arraycopy(methodParameters, 0, newParams, 1, methodParameters.length); newParams[0] = new Parameter(node.getPlainNodeReference(), "$that"); Expression arguments; if (method.getParameters() == null || method.getParameters().length == 0) { arguments = ArgumentListExpression.EMPTY_ARGUMENTS; } else { List<Expression> args = new LinkedList<Expression>(); for (Parameter parameter : methodParameters) { args.add(new VariableExpression(parameter)); } arguments = new ArgumentListExpression(args); } Expression receiver = method.isStatic() ? new ClassExpression(node) : new VariableExpression(newParams[0]); MethodCallExpression mce = new MethodCallExpression(receiver, method.getName(), arguments); mce.setMethodTarget(method); ExpressionStatement returnStatement = new ExpressionStatement(mce); MethodNode bridge = node.addMethod( "access$" + i, access, method.getReturnType(), newParams, method.getExceptions(), returnStatement); privateBridgeMethods.put(method, bridge); bridge.addAnnotation(new AnnotationNode(COMPILESTATIC_CLASSNODE)); } } if (!privateBridgeMethods.isEmpty()) { node.setNodeMetaData(PRIVATE_BRIDGE_METHODS, privateBridgeMethods); } }
private void checkRepetitiveMethod(MethodNode node) { if (isConstructor(node)) return; for (MethodNode method : currentClass.getMethods(node.getName())) { if (method == node) continue; if (!method.getDeclaringClass().equals(node.getDeclaringClass())) continue; Parameter[] p1 = node.getParameters(); Parameter[] p2 = method.getParameters(); if (p1.length != p2.length) continue; addErrorIfParamsAndReturnTypeEqual(p2, p1, node, method); } }
public MethodNode getGetterMethod(String getterName) { for (MethodNode method : getDeclaredMethods(getterName)) { if (getterName.equals(method.getName()) && ClassHelper.VOID_TYPE != method.getReturnType() && method.getParameters().length == 0) { return method; } } ClassNode parent = getSuperClass(); if (parent != null) return parent.getGetterMethod(getterName); return null; }
private void checkMethodsForOverridingFinal(ClassNode cn) { for (MethodNode method : cn.getMethods()) { Parameter[] params = method.getParameters(); for (MethodNode superMethod : cn.getSuperClass().getMethods(method.getName())) { Parameter[] superParams = superMethod.getParameters(); if (!hasEqualParameterTypes(params, superParams)) continue; if (!superMethod.isFinal()) break; addInvalidUseOfFinalError(method, params, superMethod.getDeclaringClass()); return; } } }
private void checkMethodForWeakerAccessPrivileges(MethodNode mn, ClassNode cn) { Parameter[] params = mn.getParameters(); for (MethodNode superMethod : cn.getSuperClass().getMethods(mn.getName())) { Parameter[] superParams = superMethod.getParameters(); if (!hasEqualParameterTypes(params, superParams)) continue; if ((mn.isPrivate() && !superMethod.isPrivate()) || (mn.isProtected() && superMethod.isPublic())) { addWeakerAccessError(cn, mn, params, superMethod); return; } } }
public MethodNode getSetterMethod(String setterName, boolean voidOnly) { for (MethodNode method : getDeclaredMethods(setterName)) { if (setterName.equals(method.getName()) && (!voidOnly || ClassHelper.VOID_TYPE == method.getReturnType()) && method.getParameters().length == 1) { return method; } } ClassNode parent = getSuperClass(); if (parent != null) return parent.getSetterMethod(setterName, voidOnly); return null; }
/** * Tests whether the ClassNode implements the specified method name * * @param classNode The ClassNode * @param methodName The method name * @param argTypes * @return True if it implements the method */ private static boolean implementsMethod( ClassNode classNode, String methodName, Class[] argTypes) { List methods = classNode.getMethods(); for (Iterator i = methods.iterator(); i.hasNext(); ) { MethodNode mn = (MethodNode) i.next(); final boolean isZeroArg = (argTypes == null || argTypes.length == 0); boolean methodMatch = mn.getName().equals(methodName) && isZeroArg; if (methodMatch) return true; // TODO Implement further parameter analysis } return false; }
private void checkInterfaceMethodVisibility(ClassNode node) { if (!node.isInterface()) return; for (MethodNode method : node.getMethods()) { if (method.isPrivate()) { addError( "Method '" + method.getName() + "' is private but should be public in " + getDescription(currentClass) + ".", method); } else if (method.isProtected()) { addError( "Method '" + method.getName() + "' is protected but should be public in " + getDescription(currentClass) + ".", method); } } }
protected static boolean needsMybatisContribution( ClassNode declaringClass, SourceUnit sourceUnit) { boolean found1 = false, found2 = false, found3 = false, found4 = false; ClassNode consideredClass = declaringClass; while (consideredClass != null) { for (MethodNode method : consideredClass.getMethods()) { // just check length, MOP will match it up found1 = method.getName().equals(METHOD_WITH_SQL_SESSION) && method.getParameters().length == 1; found2 = method.getName().equals(METHOD_WITH_SQL_SESSION) && method.getParameters().length == 2; found3 = method.getName().equals(METHOD_SET_MYBATIS_PROVIDER) && method.getParameters().length == 1; found4 = method.getName().equals(METHOD_GET_MYBATIS_PROVIDER) && method.getParameters().length == 0; if (found1 && found2 && found3 && found4) { return false; } } consideredClass = consideredClass.getSuperClass(); } if (found1 || found2 || found3 || found4) { sourceUnit .getErrorCollector() .addErrorAndContinue( new SimpleMessage( "@MybatisAware cannot be processed on " + declaringClass.getName() + " because some but not all of methods from " + MybatisContributionHandler.class.getName() + " were declared in the current class or super classes.", sourceUnit)); return false; } return true; }
private void printMethod(PrintWriter out, ClassNode clazz, MethodNode methodNode) { if (methodNode.getName().equals("<clinit>")) return; if (methodNode.isPrivate() || !Utilities.isJavaIdentifier(methodNode.getName())) return; if (methodNode.isSynthetic() && methodNode.getName().equals("$getStaticMetaClass")) return; printAnnotations(out, methodNode); if (!clazz.isInterface()) printModifiers(out, methodNode.getModifiers()); printGenericsBounds(out, methodNode.getGenericsTypes()); out.print(" "); printType(out, methodNode.getReturnType()); out.print(" "); out.print(methodNode.getName()); printParams(out, methodNode); ClassNode[] exceptions = methodNode.getExceptions(); for (int i = 0; i < exceptions.length; i++) { ClassNode exception = exceptions[i]; if (i == 0) { out.print("throws "); } else { out.print(", "); } printType(out, exception); } if ((methodNode.getModifiers() & Opcodes.ACC_ABSTRACT) != 0) { out.println(";"); } else { out.print(" { "); ClassNode retType = methodNode.getReturnType(); printReturn(out, retType); out.println("}"); } }
private void addWeakerAccessError( ClassNode cn, MethodNode method, Parameter[] parameters, MethodNode superMethod) { StringBuilder msg = new StringBuilder(); msg.append(method.getName()); msg.append("("); boolean needsComma = false; for (Parameter parameter : parameters) { if (needsComma) { msg.append(","); } else { needsComma = true; } msg.append(parameter.getType()); } msg.append(") in "); msg.append(cn.getName()); msg.append(" cannot override "); msg.append(superMethod.getName()); msg.append(" in "); msg.append(superMethod.getDeclaringClass().getName()); msg.append("; attempting to assign weaker access privileges; was "); msg.append(superMethod.isPublic() ? "public" : "protected"); addError(msg.toString(), method); }
private String getPropertyName(MethodNode m) { String name = m.getName(); if (!(name.startsWith("set") || name.startsWith("get"))) return null; String pname = name.substring(3); if (pname.length() == 0) return null; pname = java.beans.Introspector.decapitalize(pname); if (name.startsWith("get") && (m.getReturnType() == ClassHelper.VOID_TYPE || m.getParameters().length != 0)) { return null; } if (name.startsWith("set") && m.getParameters().length != 1) { return null; } return pname; }
public void visitMethod(MethodNode node) { visitParameters(node, node.getParameters()); String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), node.getParameters()); mv = cv.visitMethod(node.getModifiers(), node.getName(), methodType, null, null); mv.visitTypeInsn(NEW, "java/lang/RuntimeException"); mv.visitInsn(DUP); mv.visitLdcInsn("not intended for execution"); mv.visitMethodInsn( INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V", false); mv.visitInsn(ATHROW); mv.visitMaxs(0, 0); }
private void addInvalidUseOfFinalError( MethodNode method, Parameter[] parameters, ClassNode superCN) { StringBuilder msg = new StringBuilder(); msg.append("You are not allowed to override the final method ").append(method.getName()); msg.append("("); boolean needsComma = false; for (Parameter parameter : parameters) { if (needsComma) { msg.append(","); } else { needsComma = true; } msg.append(parameter.getType()); } msg.append(") from ").append(getDescription(superCN)); msg.append("."); addError(msg.toString(), method); }
private void checkOverloadingPrivateAndPublic(MethodNode node) { if (isConstructor(node)) return; boolean hasPrivate = false; boolean hasPublic = false; for (MethodNode method : currentClass.getMethods(node.getName())) { if (method == node) continue; if (!method.getDeclaringClass().equals(node.getDeclaringClass())) continue; if (method.isPublic() || method.isProtected()) { hasPublic = true; } else { hasPrivate = true; } } if (hasPrivate && hasPublic) { addError( "Mixing private and public/protected methods of the same name causes multimethods to be disabled and is forbidden to avoid surprising behaviour. Renaming the private methods will solve the problem.", node); } }
private void printMethods(PrintWriter out, ClassNode classNode, boolean isEnum) { if (!isEnum) printConstructors(out, classNode); @SuppressWarnings("unchecked") List<MethodNode> methods = (List) propertyMethods.clone(); methods.addAll(classNode.getMethods()); for (MethodNode method : methods) { if (isEnum && method.isSynthetic()) { // skip values() method and valueOf(String) String name = method.getName(); Parameter[] params = method.getParameters(); if (name.equals("values") && params.length == 0) continue; if (name.equals("valueOf") && params.length == 1 && params[0].getType().equals(ClassHelper.STRING_TYPE)) { continue; } } printMethod(out, classNode, method); } }
@SuppressWarnings("unchecked") private boolean makeGetPrivateFieldWithBridgeMethod( final Expression receiver, final ClassNode receiverType, final String fieldName, final boolean safe, final boolean implicitThis) { FieldNode field = receiverType.getField(fieldName); ClassNode classNode = controller.getClassNode(); if (field != null && Modifier.isPrivate(field.getModifiers()) && (StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(receiverType, classNode) || StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(classNode, receiverType)) && !receiverType.equals(classNode)) { Map<String, MethodNode> accessors = (Map<String, MethodNode>) receiverType .redirect() .getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_FIELDS_ACCESSORS); if (accessors != null) { MethodNode methodNode = accessors.get(fieldName); if (methodNode != null) { MethodCallExpression mce = new MethodCallExpression( receiver, methodNode.getName(), new ArgumentListExpression( field.isStatic() ? new ConstantExpression(null) : receiver)); mce.setMethodTarget(methodNode); mce.setSafe(safe); mce.setImplicitThis(implicitThis); mce.visit(controller.getAcg()); return true; } } } return false; }
private static void showDocument(Document doc) { StringBuffer content = new StringBuffer(); Node node = doc.getChildNodes().item(0); ApplicationNode appNode = new ApplicationNode(node); content.append("Application \n"); List<ClassNode> classes = appNode.getClasses(); for (int i = 0; i < classes.size(); i++) { ClassNode classNode = classes.get(i); content.append(SPACE + "Class: " + classNode.getName() + " \n"); List<MethodNode> methods = classNode.getMethods(); for (int j = 0; j < methods.size(); j++) { MethodNode methodNode = methods.get(j); content.append(SPACE + SPACE + "Method: " + methodNode.getName() + " \n"); } } System.out.println(content.toString()); }
private boolean isConstructor(MethodNode method) { return method.getName().equals("<clinit>"); }
@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); }
public static void apply(ClassNode declaringClass) { injectInterface(declaringClass, MYBATIS_CONTRIBUTION_HANDLER_CNODE); // add field: // protected MybatisProvider this$MybatisProvider = DefaultMybatisProvider.instance FieldNode providerField = declaringClass.addField( MYBATIS_PROVIDER_FIELD_NAME, ACC_PRIVATE | ACC_SYNTHETIC, MYBATIS_PROVIDER_CNODE, defaultMybatisProviderInstance()); // add method: // MybatisProvider getMybatisProvider() { // return this$MybatisProvider // } injectMethod( declaringClass, new MethodNode( METHOD_GET_MYBATIS_PROVIDER, ACC_PUBLIC, MYBATIS_PROVIDER_CNODE, Parameter.EMPTY_ARRAY, NO_EXCEPTIONS, returns(field(providerField)))); // add method: // void setMybatisProvider(MybatisProvider provider) { // this$MybatisProvider = provider ?: DefaultMybatisProvider.instance // } injectMethod( declaringClass, new MethodNode( METHOD_SET_MYBATIS_PROVIDER, ACC_PUBLIC, ClassHelper.VOID_TYPE, params(param(MYBATIS_PROVIDER_CNODE, PROVIDER)), NO_EXCEPTIONS, block( ifs_no_return( cmp(var(PROVIDER), ConstantExpression.NULL), assigns(field(providerField), defaultMybatisProviderInstance()), assigns(field(providerField), var(PROVIDER)))))); for (MethodNode method : MYBATIS_CONTRIBUTION_HANDLER_CNODE.getMethods()) { if (Arrays.binarySearch(DELEGATING_METHODS, method.getName()) < 0) continue; List<Expression> variables = new ArrayList<Expression>(); Parameter[] parameters = new Parameter[method.getParameters().length]; for (int i = 0; i < method.getParameters().length; i++) { Parameter p = method.getParameters()[i]; parameters[i] = new Parameter(makeClassSafe(p.getType()), p.getName()); parameters[i].getType().setGenericsTypes(p.getType().getGenericsTypes()); variables.add(var(p.getName())); } ClassNode returnType = makeClassSafe(method.getReturnType()); returnType.setGenericsTypes(method.getReturnType().getGenericsTypes()); returnType.setGenericsPlaceHolder(method.getReturnType().isGenericsPlaceHolder()); MethodNode newMethod = new MethodNode( method.getName(), ACC_PUBLIC, returnType, parameters, NO_EXCEPTIONS, returns(call(field(providerField), method.getName(), args(variables)))); newMethod.setGenericsTypes(method.getGenericsTypes()); injectMethod(declaringClass, newMethod); } }