make/langtools/tools/crules/MutableFieldsAnalyzer.java
changeset 47216 71c04702a3d5
parent 43767 9cff98a149cb
child 49158 f62d1d1c2d9c
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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 
       
    24 package crules;
       
    25 
       
    26 import java.util.Arrays;
       
    27 import java.util.HashMap;
       
    28 import java.util.HashSet;
       
    29 import java.util.List;
       
    30 import java.util.Map;
       
    31 import java.util.Set;
       
    32 
       
    33 import com.sun.source.util.JavacTask;
       
    34 import com.sun.source.util.TaskEvent.Kind;
       
    35 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
       
    36 import com.sun.tools.javac.tree.TreeScanner;
       
    37 
       
    38 import static com.sun.tools.javac.code.Flags.ENUM;
       
    39 import static com.sun.tools.javac.code.Flags.FINAL;
       
    40 import static com.sun.tools.javac.code.Flags.STATIC;
       
    41 import static com.sun.tools.javac.code.Flags.SYNTHETIC;
       
    42 import static com.sun.tools.javac.code.Kinds.Kind.*;
       
    43 
       
    44 /**This analyzer guards against non-final static fields.*/
       
    45 public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer {
       
    46 
       
    47     public MutableFieldsAnalyzer(JavacTask task) {
       
    48         super(task);
       
    49         treeVisitor = new MutableFieldsVisitor();
       
    50         eventKind = Kind.ANALYZE;
       
    51     }
       
    52 
       
    53     private boolean ignoreField(String className, String field) {
       
    54         Set<String> fieldsToIgnore = classFieldsToIgnoreMap.get(className);
       
    55         return (fieldsToIgnore) != null && fieldsToIgnore.contains(field);
       
    56     }
       
    57 
       
    58     class MutableFieldsVisitor extends TreeScanner {
       
    59 
       
    60         @Override
       
    61         public void visitVarDef(JCVariableDecl tree) {
       
    62             boolean isJavacPack = tree.sym.outermostClass().fullname.toString()
       
    63                     .contains(packageToCheck);
       
    64             if (isJavacPack &&
       
    65                 (tree.sym.flags() & SYNTHETIC) == 0 &&
       
    66                 tree.sym.owner.kind == TYP) {
       
    67                 if (!ignoreField(tree.sym.owner.flatName().toString(),
       
    68                         tree.getName().toString())) {
       
    69                     boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
       
    70                     boolean nonFinalStaticEnumField =
       
    71                             (tree.sym.flags() & (ENUM | FINAL)) == 0;
       
    72                     boolean nonFinalStaticField =
       
    73                             (tree.sym.flags() & STATIC) != 0 &&
       
    74                             (tree.sym.flags() & FINAL) == 0;
       
    75                     if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
       
    76                         messages.error(tree, "crules.err.var.must.be.final", tree);
       
    77                     }
       
    78                 }
       
    79             }
       
    80             super.visitVarDef(tree);
       
    81         }
       
    82 
       
    83     }
       
    84 
       
    85     private static final String packageToCheck = "com.sun.tools.javac";
       
    86 
       
    87     private static final Map<String, Set<String>> classFieldsToIgnoreMap =
       
    88                 new HashMap<>();
       
    89 
       
    90     private static void ignoreFields(String className, String... fieldNames) {
       
    91         classFieldsToIgnoreMap.put(className, new HashSet<>(Arrays.asList(fieldNames)));
       
    92     };
       
    93 
       
    94     static {
       
    95         ignoreFields("com.sun.tools.javac.util.JCDiagnostic", "fragmentFormatter");
       
    96         ignoreFields("com.sun.tools.javac.util.JavacMessages", "defaultBundle", "defaultMessages");
       
    97         ignoreFields("com.sun.tools.javac.file.JRTIndex", "sharedInstance");
       
    98         ignoreFields("com.sun.tools.javac.main.JavaCompiler", "versionRB");
       
    99         ignoreFields("com.sun.tools.javac.code.Type", "moreInfo");
       
   100         ignoreFields("com.sun.tools.javac.util.SharedNameTable", "freelist");
       
   101         ignoreFields("com.sun.tools.javac.util.Log", "useRawMessages");
       
   102         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ModuleFinder",
       
   103                 "moduleFinderClass", "ofMethod");
       
   104         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Configuration",
       
   105                 "configurationClass", "resolveAndBindMethod");
       
   106         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Layer",
       
   107                 "layerClass", "bootMethod", "defineModulesWithOneLoaderMethod", "configurationMethod");
       
   108         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$Module",
       
   109                 "addExportsMethod", "addUsesMethod", "getModuleMethod", "getUnnamedModuleMethod");
       
   110         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ModuleDescriptor$Version",
       
   111                 "versionClass", "parseMethod");
       
   112         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$ServiceLoaderHelper",
       
   113                 "loadMethod");
       
   114         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$VMHelper",
       
   115                 "vmClass", "getRuntimeArgumentsMethod");
       
   116         ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$JmodFile",
       
   117                 "jmodFileClass", "checkMagicMethod");
       
   118     }
       
   119 
       
   120 }