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);
   }
 }
 private MethodNode createBuildMethodForMethod(
     AnnotationNode anno, ClassNode buildee, MethodNode mNode, Parameter[] params) {
   String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
   final BlockStatement body = new BlockStatement();
   ClassNode returnType;
   if (mNode instanceof ConstructorNode) {
     returnType = newClass(buildee);
     body.addStatement(returnS(ctorX(newClass(mNode.getDeclaringClass()), args(params))));
   } else {
     body.addStatement(
         returnS(callX(newClass(mNode.getDeclaringClass()), mNode.getName(), args(params))));
     returnType = newClass(mNode.getReturnType());
   }
   return new MethodNode(buildMethodName, ACC_PUBLIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
 }
  private void createBuilderForAnnotatedMethod(
      BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno) {
    if (transform.getMemberValue(anno, "includes") != null
        || transform.getMemberValue(anno, "includes") != null) {
      transform.addError(
          "Error during "
              + BuilderASTTransformation.MY_TYPE_NAME
              + " processing: includes/excludes only allowed on classes",
          anno);
    }
    if (mNode instanceof ConstructorNode) {
      mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC);
    } else {
      if ((mNode.getModifiers() & ACC_STATIC) == 0) {
        transform.addError(
            "Error during "
                + BuilderASTTransformation.MY_TYPE_NAME
                + " processing: method builders only allowed on static methods",
            anno);
      }
      mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC);
    }
    ClassNode buildee = mNode.getDeclaringClass();
    Parameter[] parameters = mNode.getParameters();
    ClassNode builder =
        createInnerHelperClass(buildee, getBuilderClassName(buildee, anno), parameters.length);
    List<FieldNode> convertedFields = convertParamsToFields(builder, parameters);

    buildCommon(buildee, anno, convertedFields, builder);
    if (mNode instanceof ConstructorNode) {
      createBuildeeConstructors(transform, buildee, builder, convertedFields, false);
    } else {
      createBuildeeMethods(buildee, mNode, builder, convertedFields);
    }
  }
 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 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 String createMethodLabel(MethodNode node) {
    StringBuilder sb = new StringBuilder();
    sb.append(createClassLabel(node.getReturnType()));
    sb.append(" ");
    sb.append(createClassLabel(node.getDeclaringClass()));
    sb.append(".");
    sb.append(node.getName());
    sb.append("(");
    Parameter[] params = node.getParameters();
    if (params != null) {
      for (int i = 0; i < params.length; i++) {
        sb.append(createClassLabel(params[i].getType()));
        sb.append(" " + params[i].getName());
        if (i < params.length - 1) {
          sb.append(", ");
        }
      }
    }
    sb.append(")");

    return sb.toString();
  }
 public void buildMethod(
     BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno) {
   if (transform.getMemberValue(anno, "includes") != null
       || transform.getMemberValue(anno, "includes") != null) {
     transform.addError(
         "Error during "
             + BuilderASTTransformation.MY_TYPE_NAME
             + " processing: includes/excludes only allowed on classes",
         anno);
   }
   ClassNode buildee = mNode.getDeclaringClass();
   ClassNode builder = createBuilder(anno, buildee);
   createBuilderFactoryMethod(anno, buildee, builder);
   for (Parameter parameter : mNode.getParameters()) {
     builder.addField(createFieldCopy(buildee, parameter));
     builder.addMethod(
         createBuilderMethodForProp(
             builder,
             new PropertyInfo(parameter.getName(), parameter.getType()),
             getPrefix(anno)));
   }
   builder.addMethod(createBuildMethodForMethod(anno, buildee, mNode, mNode.getParameters()));
 }
 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 boolean isCustomScriptBodyMethod(MethodNode node) {
   return node != null
       && !(node.getDeclaringClass().equals(ClassHelper.SCRIPT_TYPE)
           && "run".equals(node.getName())
           && node.getParameters().length == 0);
 }
  private Set<String> getPropertyNamesToIncludeInWhiteList(
      final SourceUnit sourceUnit, final ClassNode classNode) {
    if (CLASS_NAME_TO_WHITE_LIST_PROPERTY_NAMES.containsKey(classNode)) {
      return CLASS_NAME_TO_WHITE_LIST_PROPERTY_NAMES.get(classNode);
    }
    final Set<String> propertyNamesToIncludeInWhiteList = new HashSet<String>();
    final Set<String> unbindablePropertyNames = new HashSet<String>();
    final Set<String> bindablePropertyNames = new HashSet<String>();
    if (!classNode.getSuperClass().equals(new ClassNode(Object.class))) {
      final Set<String> parentClassPropertyNames =
          getPropertyNamesToIncludeInWhiteList(sourceUnit, classNode.getSuperClass());
      bindablePropertyNames.addAll(parentClassPropertyNames);
    }

    final FieldNode constraintsFieldNode = classNode.getDeclaredField(CONSTRAINTS_FIELD_NAME);
    if (constraintsFieldNode != null && constraintsFieldNode.hasInitialExpression()) {
      final Expression constraintsInitialExpression = constraintsFieldNode.getInitialExpression();
      if (constraintsInitialExpression instanceof ClosureExpression) {

        final Map<String, Map<String, Expression>> constraintsInfo =
            GrailsASTUtils.getConstraintMetadata((ClosureExpression) constraintsInitialExpression);

        for (Entry<String, Map<String, Expression>> constraintConfig : constraintsInfo.entrySet()) {
          final String propertyName = constraintConfig.getKey();
          final Map<String, Expression> mapEntryExpressions = constraintConfig.getValue();
          for (Entry<String, Expression> entry : mapEntryExpressions.entrySet()) {
            final String constraintName = entry.getKey();
            if (BINDABLE_CONSTRAINT_NAME.equals(constraintName)) {
              final Expression valueExpression = entry.getValue();
              Boolean bindableValue = null;
              if (valueExpression instanceof ConstantExpression) {
                final Object constantValue = ((ConstantExpression) valueExpression).getValue();
                if (constantValue instanceof Boolean) {
                  bindableValue = (Boolean) constantValue;
                }
              }
              if (bindableValue != null) {
                if (Boolean.TRUE.equals(bindableValue)) {
                  unbindablePropertyNames.remove(propertyName);
                  bindablePropertyNames.add(propertyName);
                } else {
                  bindablePropertyNames.remove(propertyName);
                  unbindablePropertyNames.add(propertyName);
                }
              } else {
                final String message =
                    "The bindable constraint for property ["
                        + propertyName
                        + "] in class ["
                        + classNode.getName()
                        + "] has a value which is not a boolean literal and will be ignored.";
                GrailsASTUtils.warning(sourceUnit, valueExpression, message);
              }
            }
          }
        }
      }
    }

    final Set<String> fieldsInTransientsList = getPropertyNamesExpressedInTransientsList(classNode);

    propertyNamesToIncludeInWhiteList.addAll(bindablePropertyNames);
    final List<FieldNode> fields = classNode.getFields();
    for (FieldNode fieldNode : fields) {
      final String fieldName = fieldNode.getName();
      if ((!unbindablePropertyNames.contains(fieldName))
          && (bindablePropertyNames.contains(fieldName)
              || shouldFieldBeInWhiteList(fieldNode, fieldsInTransientsList))) {
        propertyNamesToIncludeInWhiteList.add(fieldName);
      }
    }

    final Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap();
    for (Entry<String, MethodNode> methodEntry : declaredMethodsMap.entrySet()) {
      final MethodNode value = methodEntry.getValue();
      if (value.getDeclaringClass() == classNode) {
        Parameter[] parameters = value.getParameters();
        if (parameters != null && parameters.length == 1) {
          final String methodName = value.getName();
          if (methodName.startsWith("set")) {
            final Parameter parameter = parameters[0];
            final ClassNode paramType = parameter.getType();
            if (!paramType.equals(new ClassNode(Object.class))) {
              final String restOfMethodName = methodName.substring(3);
              final String propertyName = GrailsNameUtils.getPropertyName(restOfMethodName);
              if (!unbindablePropertyNames.contains(propertyName)) {
                propertyNamesToIncludeInWhiteList.add(propertyName);
              }
            }
          }
        }
      }
    }
    CLASS_NAME_TO_WHITE_LIST_PROPERTY_NAMES.put(classNode, propertyNamesToIncludeInWhiteList);
    Map<String, ClassNode> allAssociationMap = GrailsASTUtils.getAllAssociationMap(classNode);
    for (String associationName : allAssociationMap.keySet()) {
      if (!propertyNamesToIncludeInWhiteList.contains(associationName)) {
        propertyNamesToIncludeInWhiteList.add(associationName);
      }
    }
    return propertyNamesToIncludeInWhiteList;
  }
Esempio n. 11
0
  /**
   * Adds or modifies an existing constructor to delegate to the given static constructor method for
   * initialization logic.
   *
   * @param classNode The class node
   * @param constructorMethod The constructor static method
   */
  public static void addDelegateConstructor(ClassNode classNode, MethodNode constructorMethod) {
    BlockStatement constructorBody = new BlockStatement();
    Parameter[] constructorParams = getRemainingParameterTypes(constructorMethod.getParameters());
    ArgumentListExpression arguments = createArgumentListFromParameters(constructorParams, true);
    MethodCallExpression constructCallExpression =
        new MethodCallExpression(
            new ClassExpression(constructorMethod.getDeclaringClass()), "initialize", arguments);
    constructCallExpression.setMethodTarget(constructorMethod);
    ExpressionStatement constructorInitExpression =
        new ExpressionStatement(constructCallExpression);
    if (constructorParams.length > 0) {
      constructorBody.addStatement(
          new ExpressionStatement(
              new ConstructorCallExpression(
                  ClassNode.THIS, GrailsArtefactClassInjector.ZERO_ARGS)));
    }
    constructorBody.addStatement(constructorInitExpression);

    if (constructorParams.length == 0) {
      // handle default constructor

      ConstructorNode constructorNode = getDefaultConstructor(classNode);
      if (constructorNode != null) {
        List<AnnotationNode> annotations =
            constructorNode.getAnnotations(new ClassNode(GrailsDelegatingConstructor.class));
        if (annotations.size() == 0) {
          Statement existingBodyCode = constructorNode.getCode();
          if (existingBodyCode instanceof BlockStatement) {
            ((BlockStatement) existingBodyCode).addStatement(constructorInitExpression);
          } else {
            constructorNode.setCode(constructorBody);
          }
        }
      } else {
        constructorNode = new ConstructorNode(Modifier.PUBLIC, constructorBody);
        classNode.addConstructor(constructorNode);
      }
      constructorNode.addAnnotation(
          new AnnotationNode(new ClassNode(GrailsDelegatingConstructor.class)));
    } else {
      // create new constructor, restoring default constructor if there is none
      ConstructorNode cn = findConstructor(classNode, constructorParams);
      if (cn == null) {
        cn =
            new ConstructorNode(
                Modifier.PUBLIC, copyParameters(constructorParams), null, constructorBody);
        classNode.addConstructor(cn);
      } else {
        List<AnnotationNode> annotations =
            cn.getAnnotations(new ClassNode(GrailsDelegatingConstructor.class));
        if (annotations.size() == 0) {
          Statement code = cn.getCode();
          constructorBody.addStatement(code);
          cn.setCode(constructorBody);
        }
      }

      ConstructorNode defaultConstructor = getDefaultConstructor(classNode);
      if (defaultConstructor == null) {
        // add empty
        classNode.addConstructor(new ConstructorNode(Modifier.PUBLIC, new BlockStatement()));
      }
      cn.addAnnotation(new AnnotationNode(new ClassNode(GrailsDelegatingConstructor.class)));
    }
  }
Esempio n. 12
0
 /**
  * Adds a static method call to given class node that delegates to the given method
  *
  * @param classNode The class node
  * @param delegateMethod The delegate method
  * @return The added method node or null if it couldn't be added
  */
 public static MethodNode addDelegateStaticMethod(ClassNode classNode, MethodNode delegateMethod) {
   ClassExpression classExpression = new ClassExpression(delegateMethod.getDeclaringClass());
   return addDelegateStaticMethod(classExpression, classNode, delegateMethod);
 }