@Override
 public void visitField(Field obj) {
   if (!isInnerClass && obj.isPrivate() && !obj.isSynthetic()) {
     String sig = obj.getSignature();
     if (sig.startsWith(Values.SIG_QUALIFIED_CLASS_PREFIX)) {
       String type = SignatureUtils.stripSignature(sig);
       if (doesObjectNeedToBeWatched(type)) {
         fieldSpecialObjects.put(obj.getName(), obj.getSignature());
       }
     }
   }
 }
예제 #2
0
  /**
   * overrides the visitor to report on classes without toStrings that have fields
   *
   * @param classContext the context object of the currently parsed class
   */
  @Override
  public void visitClassContext(ClassContext classContext) {
    JavaClass cls = classContext.getJavaClass();

    if (cls.getPackageName().isEmpty()) {
      bugReporter.reportBug(
          new BugInstance(this, BugType.IMC_IMMATURE_CLASS_NO_PACKAGE.name(), LOW_PRIORITY)
              .addClass(cls));
    }

    if ((!cls.isAbstract())
        && (!cls.isEnum())
        && !cls.getClassName().contains("$")
        && !isTestClass(cls)) {

      try {
        boolean clsHasRuntimeAnnotation = classHasRuntimeVisibleAnnotation(cls);
        HEStatus heStatus = HEStatus.UNKNOWN;

        checkIDEGeneratedParmNames(cls);

        for (Field f : cls.getFields()) {
          if (!f.isStatic() && !f.isSynthetic()) {

            boolean fieldHasRuntimeAnnotation = fieldHasRuntimeVisibleAnnotation(f);
            if (!fieldHasRuntimeAnnotation) {
              /* only report one of these, so as not to flood the report */
              if (!hasMethodInHierarchy(cls, "toString", "()Ljava/lang/String;")) {
                bugReporter.reportBug(
                    new BugInstance(
                            this, BugType.IMC_IMMATURE_CLASS_NO_TOSTRING.name(), LOW_PRIORITY)
                        .addClass(cls));
                return;
              }
              if (heStatus != HEStatus.NOT_NEEDED) {
                String fieldSig = f.getSignature();
                if (fieldSig.startsWith("L")) {
                  if (!fieldSig.startsWith("Ljava")) {
                    JavaClass fieldClass =
                        Repository.lookupClass(fieldSig.substring(1, fieldSig.length() - 1));
                    if (!hasMethodInHierarchy(fieldClass, "equals", "(Ljava/lang/Object)Z")) {
                      heStatus = HEStatus.NOT_NEEDED;
                    }
                  } else if (!fieldSig.startsWith("Ljava/lang/")
                      && !fieldSig.startsWith("Ljava/util/")) {
                    heStatus = HEStatus.NOT_NEEDED;
                  }
                } else if (!fieldSig.startsWith("[")) {
                  heStatus = HEStatus.NEEDED;
                }
              }
            } else {
              heStatus = HEStatus.NOT_NEEDED;
            }
          }
        }

        if (!clsHasRuntimeAnnotation && (heStatus == HEStatus.NEEDED)) {
          if (!hasMethodInHierarchy(cls, "equals", "(Ljava/lang/Object;)Z")) {
            bugReporter.reportBug(
                new BugInstance(this, BugType.IMC_IMMATURE_CLASS_NO_EQUALS.name(), LOW_PRIORITY)
                    .addClass(cls));
          } else if (!hasMethodInHierarchy(cls, "hashCode", "()I")) {
            bugReporter.reportBug(
                new BugInstance(this, BugType.IMC_IMMATURE_CLASS_NO_HASHCODE.name(), LOW_PRIORITY)
                    .addClass(cls));
          }
        }

      } catch (ClassNotFoundException cnfe) {
        bugReporter.reportMissingClass(cnfe);
      }
    }
  }