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); } }
/** * 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; }
private void memorizeInitialExpressions(final MethodNode node) { // add node metadata for default parameters because they are erased by the Verifier if (node.getParameters() != null) { for (Parameter parameter : node.getParameters()) { parameter.putNodeMetaData( StaticTypesMarker.INITIAL_EXPRESSION, parameter.getInitialExpression()); } } }
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); } }
/** * 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 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; } } }
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; } } }
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 void visitConstructorOrMethod(MethodNode node, boolean isConstructor) { visitAnnotations(node); visitClassCodeContainer(node.getCode()); for (Parameter param : node.getParameters()) { visitAnnotations(param); } }
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; }
protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) { pushState(node.isStatic()); inConstructor = isConstructor; node.setVariableScope(currentScope); visitAnnotations(node); // GROOVY-2156 Parameter[] parameters = node.getParameters(); for (Parameter parameter : parameters) { visitAnnotations(parameter); } declare(node.getParameters(), node); visitClassCodeContainer(node.getCode()); popState(); }
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); }
/** * Finds a method matching the given name and parameters in this class or any parent class. * * @return the method matching the given name and parameters or null */ public MethodNode getMethod(String name, Parameter[] parameters) { for (MethodNode method : getMethods(name)) { if (parametersEqual(method.getParameters(), parameters)) { return method; } } return null; }
public MethodNode tryFindPossibleMethod(String name, Expression arguments) { int count = 0; if (arguments instanceof TupleExpression) { TupleExpression tuple = (TupleExpression) arguments; // TODO this won't strictly be true when using list expansion in argument calls count = tuple.getExpressions().size(); } else return null; MethodNode res = null; ClassNode node = this; TupleExpression args = (TupleExpression) arguments; do { for (MethodNode method : node.getMethods(name)) { if (method.getParameters().length == count) { boolean match = true; for (int i = 0; i != count; ++i) if (!args.getType().isDerivedFrom(method.getParameters()[i].getType())) { match = false; break; } if (match) { if (res == null) res = method; else { if (res.getParameters().length != count) return null; if (node.equals(this)) return null; match = true; for (int i = 0; i != count; ++i) if (!res.getParameters()[i].getType().equals(method.getParameters()[i].getType())) { match = false; break; } if (!match) return null; } } } } node = node.getSuperClass(); } while (node != null); return res; }
public void visitMethod(MethodNode node) { inConstructor = false; inStaticConstructor = node.isStaticConstructor(); checkAbstractDeclaration(node); checkRepetitiveMethod(node); checkOverloadingPrivateAndPublic(node); checkMethodModifiers(node); checkGenericsUsage(node, node.getParameters()); checkGenericsUsage(node, node.getReturnType()); super.visitMethod(node); }
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; }
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; }
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; }
/** * Returns true if the given method has a possibly matching instance method with the given name * and arguments. * * @param name the name of the method of interest * @param arguments the arguments to match against * @return true if a matching method was found */ public boolean hasPossibleMethod(String name, Expression arguments) { int count = 0; if (arguments instanceof TupleExpression) { TupleExpression tuple = (TupleExpression) arguments; // TODO this won't strictly be true when using list expansion in argument calls count = tuple.getExpressions().size(); } ClassNode node = this; do { for (MethodNode method : getMethods(name)) { if (method.getParameters().length == count && !method.isStatic()) { return true; } } node = node.getSuperClass(); } while (node != null); return false; }
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); } }
private void printParams(PrintWriter out, MethodNode methodNode) { out.print("("); Parameter[] parameters = methodNode.getParameters(); if (parameters != null && parameters.length != 0) { int lastIndex = parameters.length - 1; boolean vararg = parameters[lastIndex].getType().isArray(); for (int i = 0; i != parameters.length; ++i) { if (i == lastIndex && vararg) { printType(out, parameters[i].getType().getComponentType()); out.print("..."); } else { printType(out, parameters[i].getType()); } out.print(" "); out.print(parameters[i].getName()); if (i + 1 < parameters.length) { out.print(", "); } } } out.print(")"); }
public static String getGenericsMethodSignature(MethodNode node) { GenericsType[] generics = node.getGenericsTypes(); Parameter[] param = node.getParameters(); ClassNode returnType = node.getReturnType(); if (generics == null && !hasGenerics(param) && !hasGenerics(returnType)) return null; StringBuffer ret = new StringBuffer(100); getGenericsTypeSpec(ret, generics); GenericsType[] paramTypes = new GenericsType[param.length]; for (int i = 0; i < param.length; i++) { ClassNode pType = param[i].getType(); if (pType.getGenericsTypes() == null || !pType.isGenericsPlaceHolder()) { paramTypes[i] = new GenericsType(pType); } else { paramTypes[i] = pType.getGenericsTypes()[0]; } } addSubTypes(ret, paramTypes, "(", ")"); addSubTypes(ret, new GenericsType[] {new GenericsType(returnType)}, "", ""); return ret.toString(); }
/** * Returns true if the given method has a possibly matching static method with the given name and * arguments. * * @param name the name of the method of interest * @param arguments the arguments to match against * @return true if a matching method was found */ public boolean hasPossibleStaticMethod(String name, Expression arguments) { int count = 0; if (arguments instanceof TupleExpression) { TupleExpression tuple = (TupleExpression) arguments; // TODO this won't strictly be true when using list expansion in argument calls count = tuple.getExpressions().size(); } else if (arguments instanceof MapExpression) { count = 1; } for (MethodNode method : getMethods(name)) { if (method.isStatic()) { Parameter[] parameters = method.getParameters(); if (parameters.length == count) return true; // handle varargs case if (parameters.length > 0 && parameters[parameters.length - 1].getType().isArray()) { if (count >= parameters.length - 1) return true; } // handle parameters with default values int nonDefaultParameters = 0; for (Parameter parameter : parameters) { if (!parameter.hasInitialExpression()) { nonDefaultParameters++; } } if (count < parameters.length && nonDefaultParameters <= count) { return true; } } } return false; }
/** * Returns a method descriptor for the given {@link org.codehaus.groovy.ast.MethodNode}. * * @param methodNode the method node for which to create the descriptor * @return a method descriptor as defined in section JVMS section 4.3.3 */ public static String getMethodDescriptor(MethodNode methodNode) { return getMethodDescriptor(methodNode.getReturnType(), methodNode.getParameters()); }
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); } }
private ClassNode getPropertyType(MethodNode m) { if (m.getReturnType() != ClassHelper.VOID_TYPE) { return m.getReturnType(); } return m.getParameters()[0].getType(); }