MutableFieldsAnalyzer.java revision 3376:4c740bddc648
1/*
2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24package crules;
25
26import java.util.Arrays;
27import java.util.HashMap;
28import java.util.HashSet;
29import java.util.List;
30import java.util.Map;
31import java.util.Set;
32
33import com.sun.source.util.JavacTask;
34import com.sun.source.util.TaskEvent.Kind;
35import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
36import com.sun.tools.javac.tree.TreeScanner;
37
38import static com.sun.tools.javac.code.Flags.ENUM;
39import static com.sun.tools.javac.code.Flags.FINAL;
40import static com.sun.tools.javac.code.Flags.STATIC;
41import static com.sun.tools.javac.code.Flags.SYNTHETIC;
42import static com.sun.tools.javac.code.Kinds.Kind.*;
43
44public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer {
45
46    public MutableFieldsAnalyzer(JavacTask task) {
47        super(task);
48        treeVisitor = new MutableFieldsVisitor();
49        eventKind = Kind.ANALYZE;
50    }
51
52    private boolean ignoreField(String className, String field) {
53        Set<String> fieldsToIgnore = classFieldsToIgnoreMap.get(className);
54        return (fieldsToIgnore) != null && fieldsToIgnore.contains(field);
55    }
56
57    class MutableFieldsVisitor extends TreeScanner {
58
59        @Override
60        public void visitVarDef(JCVariableDecl tree) {
61            boolean isJavacPack = tree.sym.outermostClass().fullname.toString()
62                    .contains(packageToCheck);
63            if (isJavacPack &&
64                (tree.sym.flags() & SYNTHETIC) == 0 &&
65                tree.sym.owner.kind == TYP) {
66                if (!ignoreField(tree.sym.owner.flatName().toString(),
67                        tree.getName().toString())) {
68                    boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
69                    boolean nonFinalStaticEnumField =
70                            (tree.sym.flags() & (ENUM | FINAL)) == 0;
71                    boolean nonFinalStaticField =
72                            (tree.sym.flags() & STATIC) != 0 &&
73                            (tree.sym.flags() & FINAL) == 0;
74                    if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
75                        messages.error(tree, "crules.err.var.must.be.final", tree);
76                    }
77                }
78            }
79            super.visitVarDef(tree);
80        }
81
82    }
83
84    private static final String packageToCheck = "com.sun.tools.javac";
85
86    private static final Map<String, Set<String>> classFieldsToIgnoreMap =
87                new HashMap<>();
88
89    private static void ignoreFields(String className, String... fieldNames) {
90        classFieldsToIgnoreMap.put(className, new HashSet<>(Arrays.asList(fieldNames)));
91    };
92
93    static {
94        ignoreFields("com.sun.tools.javac.util.JCDiagnostic", "fragmentFormatter");
95        ignoreFields("com.sun.tools.javac.util.JavacMessages", "defaultBundle", "defaultMessages");
96        ignoreFields("com.sun.tools.javac.file.JRTIndex", "sharedInstance");
97        ignoreFields("com.sun.tools.javac.main.JavaCompiler", "versionRB");
98        ignoreFields("com.sun.tools.javac.code.Type", "moreInfo");
99        ignoreFields("com.sun.tools.javac.util.SharedNameTable", "freelist");
100        ignoreFields("com.sun.tools.javac.util.Log", "useRawMessages");
101        ignoreFields("com.sun.tools.javac.util.ModuleWrappers$ModuleFinderHelper",
102                "moduleFinderInterface", "ofMethod", "emptyMethod");
103        ignoreFields("com.sun.tools.javac.util.ModuleWrappers$ConfigurationHelper",
104                "configurationClass", "resolveRequiresAndUsesMethod");
105        ignoreFields("com.sun.tools.javac.util.ModuleWrappers$LayerHelper",
106                "layerClass", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod");
107        ignoreFields("com.sun.tools.javac.util.ModuleHelper",
108                "addExportsMethod", "getUnnamedModuleMethod", "getModuleMethod");
109    }
110
111}
112