/**
   * Visits a class declaration.
   *
   * @param d the declaration to visit
   */
  public void visitClassDeclaration(ClassDeclaration d) {
    d.accept(pre);

    SortedSet<Declaration> decls = new TreeSet<Declaration>(SourceOrderDeclScanner.comparator);

    for (TypeParameterDeclaration tpDecl : d.getFormalTypeParameters()) {
      decls.add(tpDecl);
    }

    for (FieldDeclaration fieldDecl : d.getFields()) {
      decls.add(fieldDecl);
    }

    for (MethodDeclaration methodDecl : d.getMethods()) {
      decls.add(methodDecl);
    }

    for (TypeDeclaration typeDecl : d.getNestedTypes()) {
      decls.add(typeDecl);
    }

    for (ConstructorDeclaration ctorDecl : d.getConstructors()) {
      decls.add(ctorDecl);
    }

    for (Declaration decl : decls) decl.accept(this);

    d.accept(post);
  }
  private void processDefaultMethods(Thing data, ClassDeclaration classDeclaration) {
    // find any methods that have default parameters
    boolean error = false;
    for (ConstructorDeclaration constructorDeclaration : classDeclaration.getConstructors()) {
      Collection<ParameterDeclaration> parameters = constructorDeclaration.getParameters();
      for (ParameterDeclaration parameterDeclaration : parameters) {
        Default annotation = parameterDeclaration.getAnnotation(Default.class);
        if (annotation != null) {
          error(parameterDeclaration, "@Default is not legal in constructor parameters");
          error = true;
        }
      }
    }
    if (error) {
      return;
    }

    boolean atLeastOneDefault = false;
    methods:
    for (MethodDeclaration methodDeclaration : classDeclaration.getMethods()) {
      Collection<ParameterDeclaration> parameters = methodDeclaration.getParameters();
      boolean seenDefault = false;
      String[] names = new String[parameters.size()];
      String[] types = new String[parameters.size()];
      String[] defaults = new String[parameters.size()];
      int n = 0;
      for (ParameterDeclaration parameterDeclaration : parameters) {
        Default annotation = parameterDeclaration.getAnnotation(Default.class);
        names[n] = parameterDeclaration.getSimpleName();
        types[n] = parameterDeclaration.getType().toString();
        if (annotation != null) {
          seenDefault = true;
          if ("java.lang.String".equals(types[n])) {
            defaults[n] = '"' + annotation.value() + '"';
          } else {
            defaults[n] = annotation.value();
          }
        } else if (seenDefault) {
          error(
              parameterDeclaration,
              "All parameters after a parameter annotated with @Default must be annotated with @Default");
          continue methods;
        }
        n++;
      }

      if (seenDefault) {
        atLeastOneDefault = true;
        if (methodDeclaration.getModifiers().contains(Modifier.PRIVATE)) {
          error(methodDeclaration, "Private methods cannot use @Default parameters");
        }
        if (methodDeclaration.getModifiers().contains(Modifier.STATIC)) {
          error(methodDeclaration, "Static methods cannot use @Default parameters");
        }
        String modifiers3 = "";
        if (methodDeclaration.getModifiers().contains(Modifier.PUBLIC)) {
          modifiers3 = "public ";
        } else if (methodDeclaration.getModifiers().contains(Modifier.PROTECTED)) {
          modifiers3 = "protected ";
        }
        String throwsClause = getThrowsClause(methodDeclaration);
        String returnType = methodDeclaration.getReturnType().toString();
        String methodName = methodDeclaration.getSimpleName();
        String argDecl = "";
        String callArgs = "";
        for (int i = 0; i < n; i++) {
          if (defaults[i] != null) {
            String callArgsWithDefaults = callArgs;
            for (int j = i; j < n; j++) {
              if (j > 0) {
                callArgsWithDefaults += ", ";
              }
              callArgsWithDefaults += defaults[j];
            }
            Thing method = new Thing("method");
            method.put("name", methodName);
            method.put("returnType", returnType);
            method.put("throwsClause", throwsClause);
            method.put("argDecls", argDecl);
            method.put("modifiers", modifiers3);
            method.put("args", callArgsWithDefaults);
            data.add("defaultMethods", method);
          }
          if (i > 0) {
            argDecl += ", ";
            callArgs += ", ";
          }
          argDecl += types[i] + ' ' + names[i];
          callArgs += names[i];
        }
        Thing method = new Thing("method");
        method.put("name", methodName);
        method.put("returnType", returnType);
        method.put("throwsClause", throwsClause);
        method.put("modifiers", modifiers3);
        method.put("abstract", true);
        method.put("argDecls", argDecl);
        data.add("defaultMethods", method);
      }
    }
    data.put("atLeastOneDefault", atLeastOneDefault);
    if (!atLeastOneDefault) {
      data.setEmpty("defaultMethods");
    }
  }
Example #3
0
 // Check for default constructor.
 // 4997614: visitConstructionDeclaration reports info when there is no ctor
 @Test(result = {"NestedClass()"})
 Collection<ConstructorDeclaration> getConstructors2() {
   return nested.getConstructors();
 }
  private void processSuperclass(Thing data, Map<String, AnnotationValue> beanValues) {
    AnnotationValue value = beanValues.get("superclass");
    data.put("superclass", null);
    data.put("genericDecls", "");
    data.put("classModifiers", "");
    data.put("propertyNameConstantsInherited", false);
    data.put("getPropertyChangeSupportInherited", false);
    data.put("getPropertyChangeSupportModifiers", "protected");
    data.put("paramStringInherited", false);
    data.put("paramStringModifiers", "protected");
    data.put("createPropertyMapInherited", false);
    data.put("createPropertyMapModifiers", "public");
    data.put("atLeastOneDouble", false);
    data.put("atLeastOneBound", false);
    data.put("atLeastOneObject", false);
    data.put("atLeastOneDefault", false);

    if (value == null) {
      data.setEmpty("superclassConstructors");
    } else {
      if (!(value.getValue() instanceof ClassDeclaration)) {
        error(value, "superclass must be a class");
        return;
      }
      ClassDeclaration superclass = (ClassDeclaration) value.getValue();
      data.put("superclass", superclass.getQualifiedName());
      boolean hasProperties = !l(beanValues, "properties").isEmpty();
      // check if getPropertyChangeSupport or some superclass defines bound properties in @Bean
      checkInheritedMethod(
          data,
          "getPropertyChangeSupport",
          "java.beans.PropertyChangeSupport",
          superclass,
          true,
          new InheritCheck() {
            @Override
            public boolean isInherited(Thing d, ClassDeclaration classDeclaration) {
              Bean beanAnn = classDeclaration.getAnnotation(Bean.class);
              if (beanAnn != null) {
                Property[] properties = beanAnn.properties();
                for (Property property : properties) {
                  if (property.bound()) {
                    d.put("getPropertyChangeSupportInherited", true);
                    d.put("getPropertyChangeSupportModifiers", "protected");
                    return true;
                  }
                }
              }
              return false;
            }
          });
      // check if paramString inherited or some superclass has @Bean
      checkInheritedMethod(
          data,
          "paramString",
          "java.lang.String",
          superclass,
          !hasProperties,
          new InheritCheck() {
            @Override
            public boolean isInherited(Thing d, ClassDeclaration classDeclaration) {
              if (classDeclaration.getAnnotation(Bean.class) != null) {
                d.put("paramStringInherited", true);
                d.put("paramStringModifiers", "protected");
                return true;
              }
              return false;
            }
          });
      // check if createPropertyMap inherited or some superclass has @Bean with
      // defineCreatePropertyMap
      checkInheritedMethod(
          data,
          "createPropertyMap",
          "java.lang.String",
          superclass,
          !hasProperties,
          new InheritCheck() {
            @Override
            public boolean isInherited(Thing d, ClassDeclaration classDeclaration) {
              Bean beanAnn = classDeclaration.getAnnotation(Bean.class);
              if (beanAnn != null && beanAnn.defineCreatePropertyMap()) {
                d.put("createPropertyMapInherited", true);
                d.put("createPropertyMapModifiers", "public");
                return true;
              }
              return false;
            }
          });

      String genericDecls = null;
      Collection<TypeParameterDeclaration> formalTypeParameters2 =
          superclass.getFormalTypeParameters();
      for (TypeParameterDeclaration typeParameterDeclaration : formalTypeParameters2) {
        genericDecls = addWithCommasBetween(genericDecls, typeParameterDeclaration);
      }
      if (genericDecls == null) {
        genericDecls = "";
      } else {
        genericDecls = '<' + genericDecls + '>';
      }
      data.put("genericDecls", genericDecls);

      String classModifiers = "";
      for (Modifier modifier : superclass.getModifiers()) {
        if (!"abstract".equals(modifier.toString())) {
          classModifiers += modifier.toString() + ' ';
        }
      }
      data.put("classModifiers", classModifiers);

      Collection<ConstructorDeclaration> constructors = superclass.getConstructors();
      if (constructors.isEmpty()) {
        data.setEmpty("superclassConstructors");
      } else {
        for (ConstructorDeclaration constructorDeclaration : constructors) {
          data.add("superclassConstructors", setupMethod(constructorDeclaration, false));
        }
      }

      boolean extendPropertyNameConstants = false;
      if (b(beanValues, "definePropertyNameConstants")) {
        // if superclass has a PropertyNameConstants interface or a Bean annotation with
        //     definePropertyNameConstants=true, we need to have our PropertyNameConstants
        //     extend it
        Collection<TypeDeclaration> nestedTypes = superclass.getNestedTypes();
        for (TypeDeclaration typeDeclaration : nestedTypes) {
          if ("PropertyNames".equals(typeDeclaration.getSimpleName())
              && (typeDeclaration instanceof InterfaceDeclaration)) {
            extendPropertyNameConstants = true;
          }
        }
        if (!extendPropertyNameConstants) {
          // check if the superclass is annotated with Bean
          Bean annotation = superclass.getAnnotation(Bean.class);
          if (annotation != null) {
            extendPropertyNameConstants = annotation.definePropertyNameConstants();
          }
        }
      }
      data.put("propertyNameConstantsInherited", extendPropertyNameConstants);
    }
  }