28
import java.util.Arrays;
29
import java.util.HashMap;
30
import java.util.HashSet;
35
import com.sun.source.util.JavacTask;
36
import com.sun.source.util.TaskEvent.Kind;
37
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
38
import com.sun.tools.javac.tree.TreeScanner;
40
import static com.sun.tools.javac.code.Flags.ENUM;
41
import static com.sun.tools.javac.code.Flags.FINAL;
42
import static com.sun.tools.javac.code.Flags.STATIC;
43
import static com.sun.tools.javac.code.Flags.SYNTHETIC;
44
import static com.sun.tools.javac.code.Kinds.Kind.*;
47
public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer {
49
public MutableFieldsAnalyzer(JavacTask task) {
51
treeVisitor = new MutableFieldsVisitor();
52
eventKind = Kind.ANALYZE;
55
private boolean ignoreField(String className, String field) {
56
Set<String> fieldsToIgnore = classFieldsToIgnoreMap.get(className);
57
return (fieldsToIgnore) != null && fieldsToIgnore.contains(field);
60
class MutableFieldsVisitor extends TreeScanner {
63
public void visitVarDef(JCVariableDecl tree) {
64
boolean isJavacPack = tree.sym.outermostClass().fullname.toString()
65
.contains(packageToCheck);
67
(tree.sym.flags() & SYNTHETIC) == 0 &&
68
tree.sym.owner.kind == TYP) {
69
if (!ignoreField(tree.sym.owner.flatName().toString(),
70
tree.getName().toString())) {
71
boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
72
boolean nonFinalStaticEnumField =
73
(tree.sym.flags() & (ENUM | FINAL)) == 0;
74
boolean nonFinalStaticField =
75
(tree.sym.flags() & STATIC) != 0 &&
76
(tree.sym.flags() & FINAL) == 0;
77
if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
78
messages.error(tree, "crules.err.var.must.be.final", tree);
82
super.visitVarDef(tree);
87
private static final String packageToCheck = "com.sun.tools.javac";
89
private static final Map<String, Set<String>> classFieldsToIgnoreMap =
92
private static void ignoreFields(String className, String... fieldNames) {
93
classFieldsToIgnoreMap.put(className, new HashSet<>(Arrays.asList(fieldNames)));
97
ignoreFields("com.sun.tools.javac.util.JCDiagnostic", "fragmentFormatter");
98
ignoreFields("com.sun.tools.javac.util.JavacMessages", "defaultBundle", "defaultMessages");
99
ignoreFields("com.sun.tools.javac.file.JRTIndex", "sharedInstance");
100
ignoreFields("com.sun.tools.javac.main.JavaCompiler", "versionRB");
101
ignoreFields("com.sun.tools.javac.code.Type", "moreInfo");
102
ignoreFields("com.sun.tools.javac.util.SharedNameTable", "freelist");
103
ignoreFields("com.sun.tools.javac.util.Log", "useRawMessages");
104
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ModuleFinder",
105
"moduleFinderClass", "ofMethod");
106
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Configuration",
107
"configurationClass", "resolveAndBindMethod");
108
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Layer",
109
"layerClass", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod");
110
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Module",
111
"addExportsMethod", "addUsesMethod", "getModuleMethod", "getUnnamedModuleMethod");
112
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ModuleDescriptor$Version",
113
"versionClass", "parseMethod");
114
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ServiceLoaderHelper",
116
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$VMHelper",
117
"vmClass", "getRuntimeArgumentsMethod");
118
ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$JmodFile",
119
"jmodFileClass", "checkMagicMethod");