docs: Violation areFieldsImmutable(
        Optional<ClassTree> tree,
        ImmutableSet<String> immutableTyParams,
        ClassType classType,
        ViolationReporter reporter) {
      ClassSymbol classSym = (ClassSymbol) classType.tsym;
      if (classSym.members() == null) {
        return Violation.absent();
      }
      Filter<Symbol> instanceFieldFilter =
          new Filter<Symbol>() {
            @Override
            public boolean accepts(Symbol symbol) {
              return symbol.getKind() == ElementKind.FIELD && !symbol.isStatic();
            }
          };
      Map<Symbol, Tree> declarations = new HashMap<>();
      if (tree.isPresent()) {
        for (Tree member : tree.get().getMembers()) {
          Symbol sym = ASTHelpers.getSymbol(member);
          if (sym != null) {
            declarations.put(sym, member);
          }
        }
      }
      // javac gives us members in reverse declaration order
      // handling them in declaration order leads to marginally better diagnostics
      List<Symbol> members =
          ImmutableList.copyOf(classSym.members().getSymbols(instanceFieldFilter)).reverse();
      for (Symbol member : members) {
        Optional<Tree> memberTree = Optional.ofNullable(declarations.get(member));
        Violation info =
            isFieldImmutable(
                memberTree, immutableTyParams, classSym, classType, (VarSymbol) member, reporter);
        if (info.isPresent()) {
          return info;
        }
      }
      return Violation.absent();
    }