View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.rules.design;
    5
    6   import java.util.HashMap;
    7   import java.util.List;
    8   import java.util.Map;
    9
    10  import net.sourceforge.pmd.AbstractRule;
    11  import net.sourceforge.pmd.PropertyDescriptor;
    12  import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
    13  import net.sourceforge.pmd.ast.ASTCompilationUnit;
    14  import net.sourceforge.pmd.ast.ASTFieldDeclaration;
    15  import net.sourceforge.pmd.ast.SimpleNode;
    16  import net.sourceforge.pmd.properties.IntegerProperty;
    17  import net.sourceforge.pmd.util.NumericConstants;
    18
    19
    20  public class TooManyFields extends AbstractRule {
    21
    22      private static final int DEFAULT_MAXFIELDS = 15;
    23
    24      private Map<String, Integer> stats;
    25      private Map<String, ASTClassOrInterfaceDeclaration> nodes;
    26
    27      private static final PropertyDescriptor maxFieldsDescriptor = new IntegerProperty(
    28      		"maxfields",
    29      		"Maximum allowable fields per class",
    30      		DEFAULT_MAXFIELDS,
    31      		1.0f
    32      		);
    33
    34      private static final Map<String, PropertyDescriptor> propertyDescriptorsByName = asFixedMap(maxFieldsDescriptor);
    35
    36      public Object visit(ASTCompilationUnit node, Object data) {
    37
    38          int maxFields = getIntProperty(maxFieldsDescriptor);
    39
    40          stats = new HashMap<String, Integer>(5);
    41          nodes = new HashMap<String, ASTClassOrInterfaceDeclaration>(5);
    42
    43          List<ASTFieldDeclaration> l = node.findChildrenOfType(ASTFieldDeclaration.class);
    44
    45          for (ASTFieldDeclaration fd: l) {
    46              if (fd.isFinal() && fd.isStatic()) {
    47                  continue;
    48              }
    49              ASTClassOrInterfaceDeclaration clazz = fd.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
    50              if (clazz != null && !clazz.isInterface()) {
    51                  bumpCounterFor(clazz);
    52              }
    53          }
    54          for (String k : stats.keySet()) {
    55              int val = stats.get(k);
    56              SimpleNode n = nodes.get(k);
    57              if (val > maxFields) {
    58                  addViolation(data, n);
    59              }
    60          }
    61          return data;
    62      }
    63
    64      private void bumpCounterFor(ASTClassOrInterfaceDeclaration clazz) {
    65          String key = clazz.getImage();
    66          if (!stats.containsKey(key)) {
    67              stats.put(key, NumericConstants.ZERO);
    68              nodes.put(key, clazz);
    69          }
    70          Integer i = Integer.valueOf(stats.get(key) + 1);
    71          stats.put(key, i);
    72      }
    73
    74      /**
    75       * @return Map
    76       */
    77      protected Map<String, PropertyDescriptor> propertiesByName() {
    78      	return propertyDescriptorsByName;
    79      }
    80  }