MutableFieldsAnalyzer.java revision 2673:bf8500822576
1/*
2 * Copyright (c) 2013, 2014, 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.List;
29import java.util.Map;
30
31import com.sun.source.util.JavacTask;
32import com.sun.source.util.TaskEvent.Kind;
33import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
34import com.sun.tools.javac.tree.TreeScanner;
35
36import static com.sun.tools.javac.code.Flags.ENUM;
37import static com.sun.tools.javac.code.Flags.FINAL;
38import static com.sun.tools.javac.code.Flags.STATIC;
39import static com.sun.tools.javac.code.Flags.SYNTHETIC;
40import static com.sun.tools.javac.code.Kinds.Kind.*;
41
42public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer {
43
44    public MutableFieldsAnalyzer(JavacTask task) {
45        super(task);
46        treeVisitor = new MutableFieldsVisitor();
47        eventKind = Kind.ANALYZE;
48    }
49
50    private boolean ignoreField(String className, String field) {
51        List<String> currentFieldsToIgnore =
52                classFieldsToIgnoreMap.get(className);
53        if (currentFieldsToIgnore != null) {
54            for (String fieldToIgnore : currentFieldsToIgnore) {
55                if (field.equals(fieldToIgnore)) {
56                    return true;
57                }
58            }
59        }
60        return false;
61    }
62
63    class MutableFieldsVisitor extends TreeScanner {
64
65        @Override
66        public void visitVarDef(JCVariableDecl tree) {
67            boolean isJavacPack = tree.sym.outermostClass().fullname.toString()
68                    .contains(packageToCheck);
69            if (isJavacPack &&
70                (tree.sym.flags() & SYNTHETIC) == 0 &&
71                tree.sym.owner.kind == TYP) {
72                if (!ignoreField(tree.sym.owner.flatName().toString(),
73                        tree.getName().toString())) {
74                    boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
75                    boolean nonFinalStaticEnumField =
76                            (tree.sym.flags() & (ENUM | FINAL)) == 0;
77                    boolean nonFinalStaticField =
78                            (tree.sym.flags() & STATIC) != 0 &&
79                            (tree.sym.flags() & FINAL) == 0;
80                    if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
81                        messages.error(tree, "crules.err.var.must.be.final", tree);
82                    }
83                }
84            }
85            super.visitVarDef(tree);
86        }
87
88    }
89
90    private static final String packageToCheck = "com.sun.tools.javac";
91
92    private static final Map<String, List<String>> classFieldsToIgnoreMap =
93                new HashMap<>();
94
95    static {
96        classFieldsToIgnoreMap.
97                put("com.sun.tools.javac.util.JCDiagnostic",
98                    Arrays.asList("fragmentFormatter"));
99        classFieldsToIgnoreMap.
100                put("com.sun.tools.javac.util.JavacMessages",
101                    Arrays.asList("defaultBundle", "defaultMessages"));
102        classFieldsToIgnoreMap.
103                put("com.sun.tools.javac.file.ZipFileIndexCache",
104                    Arrays.asList("sharedInstance"));
105        classFieldsToIgnoreMap.
106                put("com.sun.tools.javac.main.JavaCompiler",
107                    Arrays.asList("versionRB"));
108        classFieldsToIgnoreMap.
109                put("com.sun.tools.javac.code.Type",
110                    Arrays.asList("moreInfo"));
111        classFieldsToIgnoreMap.
112                put("com.sun.tools.javac.util.SharedNameTable",
113                    Arrays.asList("freelist"));
114        classFieldsToIgnoreMap.
115                put("com.sun.tools.javac.util.Log",
116                    Arrays.asList("useRawMessages"));
117    }
118
119}
120