1 package net.sourceforge.pmd;
2
3 import java.io.InputStream;
4 import java.io.InputStreamReader;
5 import java.io.Reader;
6 import java.io.UnsupportedEncodingException;
7 import java.util.ArrayList;
8 import java.util.List;
9
10 import net.sourceforge.pmd.benchmark.Benchmark;
11 import net.sourceforge.pmd.benchmark.Benchmarker;
12 import net.sourceforge.pmd.lang.Language;
13 import net.sourceforge.pmd.lang.LanguageVersion;
14 import net.sourceforge.pmd.lang.LanguageVersionHandler;
15 import net.sourceforge.pmd.lang.Parser;
16 import net.sourceforge.pmd.lang.ast.Node;
17 import net.sourceforge.pmd.lang.java.ast.ParseException;
18 import net.sourceforge.pmd.lang.xpath.Initializer;
19 import net.sourceforge.pmd.util.IOUtil;
20
21 public class SourceCodeProcessor {
22
23 private final PMDConfiguration configuration;
24
25 public SourceCodeProcessor(PMDConfiguration configuration) {
26 this.configuration = configuration;
27 }
28
29
30
31
32
33
34
35
36
37
38
39
40 public void processSourceCode(InputStream sourceCode, RuleSets ruleSets, RuleContext ctx) throws PMDException {
41 try {
42 processSourceCode(new InputStreamReader(sourceCode, configuration.getSourceEncoding()), ruleSets, ctx);
43 } catch (UnsupportedEncodingException uee) {
44 throw new PMDException("Unsupported encoding exception: " + uee.getMessage());
45 }
46 }
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public void processSourceCode(Reader sourceCode, RuleSets ruleSets, RuleContext ctx) throws PMDException {
66 determineLanguage(ctx);
67
68
69 Initializer.initialize();
70
71
72 if (ruleSets.applies(ctx.getSourceCodeFile())) {
73
74 try {
75 processSource(sourceCode, ruleSets,ctx);
76
77 } catch (ParseException pe) {
78 throw new PMDException("Error while parsing " + ctx.getSourceCodeFilename(), pe);
79 } catch (Exception e) {
80 throw new PMDException("Error while processing " + ctx.getSourceCodeFilename(), e);
81 } finally {
82 IOUtil.closeQuietly(sourceCode);
83 }
84 }
85 }
86
87
88 private Node parse(RuleContext ctx, Reader sourceCode, Parser parser) {
89 long start = System.nanoTime();
90 Node rootNode = parser.parse(ctx.getSourceCodeFilename(), sourceCode);
91 ctx.getReport().suppress(parser.getSuppressMap());
92 long end = System.nanoTime();
93 Benchmarker.mark(Benchmark.Parser, end - start, 0);
94 return rootNode;
95 }
96
97 private void symbolFacade(Node rootNode, LanguageVersionHandler languageVersionHandler) {
98 long start = System.nanoTime();
99 languageVersionHandler.getSymbolFacade().start(rootNode);
100 long end = System.nanoTime();
101 Benchmarker.mark(Benchmark.SymbolTable, end - start, 0);
102 }
103
104
105
106
107
108
109
110
111 private void usesDFA(LanguageVersion languageVersion, Node rootNode, RuleSets ruleSets, Language language ) {
112
113 if (ruleSets.usesDFA(language)) {
114 long start = System.nanoTime();
115 languageVersion.getLanguageVersionHandler().getDataFlowFacade().start(rootNode);
116 long end = System.nanoTime();
117 Benchmarker.mark(Benchmark.DFA, end - start, 0);
118 }
119 }
120
121 private void usesTypeResolution(LanguageVersion languageVersion, Node rootNode, RuleSets ruleSets, Language language) {
122
123 if (ruleSets.usesTypeResolution(language)) {
124 long start = System.nanoTime();
125 languageVersion.getLanguageVersionHandler().getTypeResolutionFacade(configuration.getClassLoader()).start(rootNode);
126 long end = System.nanoTime();
127 Benchmarker.mark(Benchmark.TypeResolution, end - start, 0);
128 }
129 }
130
131 private void processSource(Reader sourceCode, RuleSets ruleSets, RuleContext ctx) {
132 LanguageVersion languageVersion = ctx.getLanguageVersion();
133 LanguageVersionHandler languageVersionHandler = languageVersion.getLanguageVersionHandler();
134 Parser parser = PMD.parserFor(languageVersion, configuration);
135
136 Node rootNode = parse(ctx, sourceCode, parser);
137 symbolFacade(rootNode, languageVersionHandler);
138 Language language = languageVersion.getLanguage();
139 usesDFA(languageVersion, rootNode, ruleSets, language);
140 usesTypeResolution(languageVersion, rootNode, ruleSets,language);
141
142 List<Node> acus = new ArrayList<Node>();
143 acus.add(rootNode);
144 ruleSets.apply(acus, ctx, language);
145 }
146
147
148
149 private void determineLanguage(RuleContext ctx) {
150
151 if (ctx.getLanguageVersion() == null) {
152 LanguageVersion languageVersion = configuration.getLanguageVersionOfFile(ctx.getSourceCodeFilename());
153 ctx.setLanguageVersion(languageVersion);
154 }
155 }
156 }