aoqi@0: /* aoqi@0: * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package crules; aoqi@0: aoqi@0: import java.util.Arrays; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.List; aoqi@0: import java.util.Map; aoqi@0: aoqi@0: import com.sun.tools.javac.code.Kinds; aoqi@0: import com.sun.tools.javac.tree.TreeScanner; aoqi@0: aoqi@0: import static com.sun.source.util.TaskEvent.Kind; aoqi@0: import static com.sun.tools.javac.code.Flags.*; aoqi@0: import static com.sun.tools.javac.tree.JCTree.JCVariableDecl; aoqi@0: aoqi@0: public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { aoqi@0: aoqi@0: public MutableFieldsAnalyzer() { aoqi@0: treeVisitor = new MutableFieldsVisitor(); aoqi@0: eventKind = Kind.ANALYZE; aoqi@0: } aoqi@0: aoqi@0: public String getName() { aoqi@0: return "mutable_fields_analyzer"; aoqi@0: } aoqi@0: aoqi@0: private boolean ignoreField(String className, String field) { aoqi@0: List currentFieldsToIgnore = aoqi@0: classFieldsToIgnoreMap.get(className); aoqi@0: if (currentFieldsToIgnore != null) { aoqi@0: for (String fieldToIgnore : currentFieldsToIgnore) { aoqi@0: if (field.equals(fieldToIgnore)) { aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: class MutableFieldsVisitor extends TreeScanner { aoqi@0: aoqi@0: @Override aoqi@0: public void visitVarDef(JCVariableDecl tree) { aoqi@0: boolean isJavacPack = tree.sym.outermostClass().fullname.toString() aoqi@0: .contains(packageToCheck); aoqi@0: if (isJavacPack && aoqi@0: (tree.sym.flags() & SYNTHETIC) == 0 && aoqi@0: tree.sym.owner.kind == Kinds.TYP) { aoqi@0: if (!ignoreField(tree.sym.owner.flatName().toString(), aoqi@0: tree.getName().toString())) { aoqi@0: boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0; aoqi@0: boolean nonFinalStaticEnumField = aoqi@0: (tree.sym.flags() & (ENUM | FINAL)) == 0; aoqi@0: boolean nonFinalStaticField = aoqi@0: (tree.sym.flags() & STATIC) != 0 && aoqi@0: (tree.sym.flags() & FINAL) == 0; aoqi@0: if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) { aoqi@0: messages.error(tree, "crules.err.var.must.be.final", tree); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: super.visitVarDef(tree); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: private static final String packageToCheck = "com.sun.tools.javac"; aoqi@0: aoqi@0: private static final Map> classFieldsToIgnoreMap = aoqi@0: new HashMap>(); aoqi@0: aoqi@0: static { aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.util.JCDiagnostic", aoqi@0: Arrays.asList("fragmentFormatter")); aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.util.JavacMessages", aoqi@0: Arrays.asList("defaultBundle", "defaultMessages")); aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.file.ZipFileIndexCache", aoqi@0: Arrays.asList("sharedInstance")); aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.main.JavaCompiler", aoqi@0: Arrays.asList("versionRB")); aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.code.Type", aoqi@0: Arrays.asList("moreInfo")); aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.util.SharedNameTable", aoqi@0: Arrays.asList("freelist")); aoqi@0: classFieldsToIgnoreMap. aoqi@0: put("com.sun.tools.javac.util.Log", aoqi@0: Arrays.asList("useRawMessages")); aoqi@0: } aoqi@0: aoqi@0: }