Exemplo n.º 1
0
  protected MethodNode addClassUnderTestMethod(
      ClassNode classNode, ClassExpression targetClass, String type) {

    String methodName = "setup" + type + "UnderTest";
    String fieldName = GrailsNameUtils.getPropertyName(type);
    String getterName = GrailsNameUtils.getGetterName(fieldName);
    fieldName = '$' + fieldName;

    if (classNode.getField(fieldName) == null) {
      classNode.addField(fieldName, Modifier.PRIVATE, targetClass.getType(), null);
    }

    MethodNode methodNode =
        classNode.getMethod(methodName, GrailsArtefactClassInjector.ZERO_PARAMETERS);

    VariableExpression fieldExpression = new VariableExpression(fieldName);
    if (methodNode == null) {
      BlockStatement setupMethodBody = new BlockStatement();
      addMockCollaborator(type, targetClass, setupMethodBody);

      methodNode =
          new MethodNode(
              methodName,
              Modifier.PUBLIC,
              ClassHelper.VOID_TYPE,
              GrailsArtefactClassInjector.ZERO_PARAMETERS,
              null,
              setupMethodBody);
      methodNode.addAnnotation(BEFORE_ANNOTATION);
      methodNode.addAnnotation(MIXIN_METHOD_ANNOTATION);
      classNode.addMethod(methodNode);
    }

    MethodNode getter =
        classNode.getMethod(getterName, GrailsArtefactClassInjector.ZERO_PARAMETERS);
    if (getter == null) {
      BlockStatement getterBody = new BlockStatement();
      getter =
          new MethodNode(
              getterName,
              Modifier.PUBLIC,
              targetClass.getType().getPlainNodeReference(),
              GrailsArtefactClassInjector.ZERO_PARAMETERS,
              null,
              getterBody);

      BinaryExpression testTargetAssignment =
          new BinaryExpression(
              fieldExpression,
              ASSIGN,
              new ConstructorCallExpression(
                  targetClass.getType(), GrailsArtefactClassInjector.ZERO_ARGS));

      IfStatement autowiringIfStatement =
          getAutowiringIfStatement(targetClass, fieldExpression, testTargetAssignment);
      getterBody.addStatement(autowiringIfStatement);

      getterBody.addStatement(new ReturnStatement(fieldExpression));
      classNode.addMethod(getter);
    }

    return methodNode;
  }
  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;
  }