CodingRulesAnalyzerPlugin.java revision 3376:4c740bddc648
1139749Simp/* 2121491Simp * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3121491Simp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4121491Simp * 5121491Simp * This code is free software; you can redistribute it and/or modify it 6121491Simp * under the terms of the GNU General Public License version 2 only, as 7121491Simp * published by the Free Software Foundation. 8121491Simp * 9121491Simp * This code is distributed in the hope that it will be useful, but WITHOUT 10121491Simp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11121491Simp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12121491Simp * version 2 for more details (a copy is included in the LICENSE file that 13121491Simp * accompanied this code). 14121491Simp * 15121491Simp * You should have received a copy of the GNU General Public License version 16121491Simp * 2 along with this work; if not, write to the Free Software Foundation, 17121491Simp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18121491Simp * 19121491Simp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20121491Simp * or visit www.oracle.com if you need additional information or have any 21121491Simp * questions. 22121491Simp */ 23121491Simp 24121491Simppackage crules; 25121491Simp 26121491Simpimport java.lang.reflect.Layer; 27121491Simpimport java.lang.reflect.Module; 28121491Simpimport java.util.ArrayList; 29121491Simpimport java.util.HashMap; 30121491Simpimport java.util.List; 31121491Simpimport java.util.Map; 32121491Simpimport java.util.Optional; 33121491Simp 34121491Simpimport javax.lang.model.element.TypeElement; 35121491Simpimport javax.tools.JavaFileObject; 36121491Simp 37121491Simpimport com.sun.source.tree.Tree; 38151014Sjhbimport com.sun.source.util.JavacTask; 39151014Sjhbimport com.sun.source.util.Plugin; 40151014Sjhbimport com.sun.source.util.TaskEvent; 41133980Sgibbsimport com.sun.source.util.TaskEvent.Kind; 42133980Sgibbsimport com.sun.source.util.TaskListener; 43133980Sgibbsimport com.sun.source.util.Trees; 44133980Sgibbsimport com.sun.tools.javac.api.BasicJavacTask; 45151014Sjhbimport com.sun.tools.javac.tree.JCTree; 46151014Sjhbimport com.sun.tools.javac.util.Context; 47151014Sjhbimport com.sun.tools.javac.util.DefinedBy; 48133980Sgibbsimport com.sun.tools.javac.util.DefinedBy.Api; 49133980Sgibbsimport com.sun.tools.javac.util.Log; 50151014Sjhb 51151014Sjhb/* 52133980Sgibbs * This code must be run in a context that provides 53151014Sjhb * access to the following javac internal packages: 54199559Sjhb * com.sun.tools.javac.api 55151014Sjhb * com.sun.tools.javac.tree 56151014Sjhb * com.sun.tools.javac.util 57199559Sjhb */ 58121491Simppublic class CodingRulesAnalyzerPlugin implements Plugin { 59121491Simp 60121491Simp protected Log log; 61151014Sjhb protected Trees trees; 62121491Simp 63151014Sjhb @DefinedBy(Api.COMPILER_TREE) 64121491Simp public void init(JavacTask task, String... args) { 65151014Sjhb BasicJavacTask impl = (BasicJavacTask)task; 66121491Simp Context context = impl.getContext(); 67121491Simp log = Log.instance(context); 68151014Sjhb trees = Trees.instance(task); 69121491Simp task.addTaskListener(new PostAnalyzeTaskListener( 70151014Sjhb new MutableFieldsAnalyzer(task), 71121491Simp new AssertCheckAnalyzer(task), 72151014Sjhb new DefinedByAnalyzer(task) 73121491Simp )); 74151014Sjhb } 75151014Sjhb 76151014Sjhb private void addExports(String moduleName, String... packageNames) { 77151014Sjhb for (String packageName : packageNames) { 78151014Sjhb try { 79151014Sjhb Layer layer = Layer.boot(); 80151014Sjhb Optional<Module> m = layer.findModule(moduleName); 81151014Sjhb if (!m.isPresent()) 82 throw new Error("module not found: " + moduleName); 83 m.get().addExports(packageName, getClass().getModule()); 84 } catch (Exception e) { 85 throw new Error("failed to add exports for " + moduleName + "/" + packageName); 86 } 87 } 88 } 89 90 public class PostAnalyzeTaskListener implements TaskListener { 91 private final Map<Kind, List<AbstractCodingRulesAnalyzer>> analyzers = new HashMap<>(); 92 93 public PostAnalyzeTaskListener(AbstractCodingRulesAnalyzer... analyzers) { 94 for (AbstractCodingRulesAnalyzer analyzer : analyzers) { 95 List<AbstractCodingRulesAnalyzer> currentAnalyzers = this.analyzers.get(analyzer.eventKind); 96 97 if (currentAnalyzers == null) { 98 this.analyzers.put(analyzer.eventKind, currentAnalyzers = new ArrayList<>()); 99 } 100 101 currentAnalyzers.add(analyzer); 102 } 103 } 104 105 @Override @DefinedBy(Api.COMPILER_TREE) 106 public void started(TaskEvent taskEvent) {} 107 108 @Override @DefinedBy(Api.COMPILER_TREE) 109 public void finished(TaskEvent taskEvent) { 110 List<AbstractCodingRulesAnalyzer> currentAnalyzers = this.analyzers.get(taskEvent.getKind()); 111 112 if (currentAnalyzers != null) { 113 TypeElement typeElem = taskEvent.getTypeElement(); 114 Tree tree = trees.getTree(typeElem); 115 if (tree != null) { 116 JavaFileObject prevSource = log.currentSourceFile(); 117 try { 118 log.useSource(taskEvent.getCompilationUnit().getSourceFile()); 119 for (AbstractCodingRulesAnalyzer analyzer : currentAnalyzers) { 120 analyzer.treeVisitor.scan((JCTree)tree); 121 } 122 } finally { 123 log.useSource(prevSource); 124 } 125 } 126 } 127 } 128 } 129 130 @Override @DefinedBy(Api.COMPILER_TREE) 131 public String getName() { 132 return "coding_rules"; 133 } 134 135} 136