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