CodingRulesAnalyzerPlugin.java revision 4202:2bd34895dda2
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.ArrayList; 27import java.util.HashMap; 28import java.util.List; 29import java.util.Map; 30import java.util.Optional; 31 32import javax.lang.model.element.TypeElement; 33import javax.tools.JavaFileObject; 34 35import com.sun.source.tree.Tree; 36import com.sun.source.util.JavacTask; 37import com.sun.source.util.Plugin; 38import com.sun.source.util.TaskEvent; 39import com.sun.source.util.TaskEvent.Kind; 40import com.sun.source.util.TaskListener; 41import com.sun.source.util.Trees; 42import com.sun.tools.javac.api.BasicJavacTask; 43import com.sun.tools.javac.tree.JCTree; 44import com.sun.tools.javac.util.Context; 45import com.sun.tools.javac.util.DefinedBy; 46import com.sun.tools.javac.util.DefinedBy.Api; 47import com.sun.tools.javac.util.Log; 48 49/* 50 * This code must be run in a context that provides 51 * access to the following javac internal packages: 52 * com.sun.tools.javac.api 53 * com.sun.tools.javac.tree 54 * com.sun.tools.javac.util 55 */ 56public class CodingRulesAnalyzerPlugin implements Plugin { 57 58 protected Log log; 59 protected Trees trees; 60 61 @DefinedBy(Api.COMPILER_TREE) 62 public void init(JavacTask task, String... args) { 63 BasicJavacTask impl = (BasicJavacTask)task; 64 Context context = impl.getContext(); 65 log = Log.instance(context); 66 trees = Trees.instance(task); 67 task.addTaskListener(new PostAnalyzeTaskListener( 68 new MutableFieldsAnalyzer(task), 69 new AssertCheckAnalyzer(task), 70 new DefinedByAnalyzer(task), 71 new LegacyLogMethodAnalyzer(task) 72 )); 73 } 74 75 private void addExports(String moduleName, String... packageNames) { 76 for (String packageName : packageNames) { 77 try { 78 ModuleLayer layer = ModuleLayer.boot(); 79 Optional<Module> m = layer.findModule(moduleName); 80 if (!m.isPresent()) 81 throw new Error("module not found: " + moduleName); 82 m.get().addExports(packageName, getClass().getModule()); 83 } catch (Exception e) { 84 throw new Error("failed to add exports for " + moduleName + "/" + packageName); 85 } 86 } 87 } 88 89 public class PostAnalyzeTaskListener implements TaskListener { 90 private final Map<Kind, List<AbstractCodingRulesAnalyzer>> analyzers = new HashMap<>(); 91 92 public PostAnalyzeTaskListener(AbstractCodingRulesAnalyzer... analyzers) { 93 for (AbstractCodingRulesAnalyzer analyzer : analyzers) { 94 List<AbstractCodingRulesAnalyzer> currentAnalyzers = this.analyzers.get(analyzer.eventKind); 95 96 if (currentAnalyzers == null) { 97 this.analyzers.put(analyzer.eventKind, currentAnalyzers = new ArrayList<>()); 98 } 99 100 currentAnalyzers.add(analyzer); 101 } 102 } 103 104 @Override @DefinedBy(Api.COMPILER_TREE) 105 public void started(TaskEvent taskEvent) {} 106 107 @Override @DefinedBy(Api.COMPILER_TREE) 108 public void finished(TaskEvent taskEvent) { 109 List<AbstractCodingRulesAnalyzer> currentAnalyzers = this.analyzers.get(taskEvent.getKind()); 110 111 if (currentAnalyzers != null) { 112 TypeElement typeElem = taskEvent.getTypeElement(); 113 Tree tree = trees.getTree(typeElem); 114 if (tree != null) { 115 JavaFileObject prevSource = log.currentSourceFile(); 116 try { 117 log.useSource(taskEvent.getCompilationUnit().getSourceFile()); 118 for (AbstractCodingRulesAnalyzer analyzer : currentAnalyzers) { 119 analyzer.treeVisitor.scan((JCTree)tree); 120 } 121 } finally { 122 log.useSource(prevSource); 123 } 124 } 125 } 126 } 127 } 128 129 @Override @DefinedBy(Api.COMPILER_TREE) 130 public String getName() { 131 return "coding_rules"; 132 } 133 134} 135