@Override public Description matchClass(ClassTree classTree, VisitorState state) { TypeSymbol symbol = ASTHelpers.getSymbol(classTree); if (symbol.getKind() != ElementKind.CLASS) { return Description.NO_MATCH; } MethodTree equals = null; for (Tree member : classTree.getMembers()) { if (!(member instanceof MethodTree)) { continue; } MethodTree methodTree = (MethodTree) member; if (EQUALS_MATCHER.matches(methodTree, state)) { equals = methodTree; } } if (equals == null) { return Description.NO_MATCH; } MethodSymbol hashCodeSym = ASTHelpers.resolveExistingMethod( state, symbol, state.getName("hashCode"), ImmutableList.<Type>of(), ImmutableList.<Type>of()); if (hashCodeSym.owner.equals(state.getSymtab().objectType.tsym)) { return describeMatch(equals); } return Description.NO_MATCH; }
/** @return all values of the given enum type, in declaration order. */ public static LinkedHashSet<String> enumValues(TypeSymbol enumType) { if (enumType.getKind() != ElementKind.ENUM) { throw new IllegalStateException(); } Scope scope = enumType.members(); Deque<String> values = new ArrayDeque<>(); for (Symbol sym : scope.getSymbols()) { if (sym instanceof VarSymbol) { VarSymbol var = (VarSymbol) sym; if ((var.flags() & Flags.ENUM) != 0) { /** * Javac gives us the members backwards, apparently. It's worth making an effort to * preserve declaration order because it's useful for diagnostics (e.g. in {@link * MissingCasesInEnumSwitch}). */ values.push(sym.name.toString()); } } } return new LinkedHashSet<>(values); }