jlahoda@0
|
1 |
/*
|
jlahoda@0
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
jlahoda@0
|
3 |
*
|
jlahoda@297
|
4 |
* Copyright 2008-2010 Sun Microsystems, Inc. All rights reserved.
|
jlahoda@0
|
5 |
*
|
jlahoda@0
|
6 |
* The contents of this file are subject to the terms of either the GNU
|
jlahoda@0
|
7 |
* General Public License Version 2 only ("GPL") or the Common
|
jlahoda@0
|
8 |
* Development and Distribution License("CDDL") (collectively, the
|
jlahoda@0
|
9 |
* "License"). You may not use this file except in compliance with the
|
jlahoda@0
|
10 |
* License. You can obtain a copy of the License at
|
jlahoda@0
|
11 |
* http://www.netbeans.org/cddl-gplv2.html
|
jlahoda@0
|
12 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
jlahoda@0
|
13 |
* specific language governing permissions and limitations under the
|
jlahoda@0
|
14 |
* License. When distributing the software, include this License Header
|
jlahoda@0
|
15 |
* Notice in each file and include the License file at
|
jlahoda@0
|
16 |
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
|
jlahoda@0
|
17 |
* particular file as subject to the "Classpath" exception as provided
|
jlahoda@0
|
18 |
* by Sun in the GPL Version 2 section of the License file that
|
jlahoda@0
|
19 |
* accompanied this code. If applicable, add the following below the
|
jlahoda@0
|
20 |
* License Header, with the fields enclosed by brackets [] replaced by
|
jlahoda@0
|
21 |
* your own identifying information:
|
jlahoda@0
|
22 |
* "Portions Copyrighted [year] [name of copyright owner]"
|
jlahoda@0
|
23 |
*
|
jlahoda@0
|
24 |
* If you wish your version of this file to be governed by only the CDDL
|
jlahoda@0
|
25 |
* or only the GPL Version 2, indicate your decision by adding
|
jlahoda@0
|
26 |
* "[Contributor] elects to include this software in this distribution
|
jlahoda@0
|
27 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a
|
jlahoda@0
|
28 |
* single choice of license, a recipient has the option to distribute
|
jlahoda@0
|
29 |
* your version of this file under either the CDDL, the GPL Version 2 or
|
jlahoda@0
|
30 |
* to extend the choice of license to its licensees as provided above.
|
jlahoda@0
|
31 |
* However, if you add GPL Version 2 code and therefore, elected the GPL
|
jlahoda@0
|
32 |
* Version 2 license, then the option applies only if the new code is
|
jlahoda@0
|
33 |
* made subject to such option by the copyright holder.
|
jlahoda@0
|
34 |
*
|
jlahoda@0
|
35 |
* Contributor(s):
|
jlahoda@0
|
36 |
*
|
jlahoda@297
|
37 |
* Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
|
jlahoda@0
|
38 |
*/
|
jlahoda@0
|
39 |
|
jlahoda@23
|
40 |
package org.netbeans.modules.jackpot30.impl.hints;
|
jlahoda@0
|
41 |
|
jlahoda@0
|
42 |
import com.sun.source.tree.Tree;
|
jlahoda@0
|
43 |
import java.util.Stack;
|
jlahoda@0
|
44 |
import java.util.concurrent.atomic.AtomicBoolean;
|
jlahoda@0
|
45 |
import javax.lang.model.element.AnnotationMirror;
|
jlahoda@0
|
46 |
import javax.lang.model.element.AnnotationValue;
|
jlahoda@0
|
47 |
import javax.lang.model.element.Element;
|
jlahoda@0
|
48 |
import javax.lang.model.element.ExecutableElement;
|
jlahoda@0
|
49 |
import javax.lang.model.element.TypeElement;
|
jlahoda@0
|
50 |
import javax.swing.text.Document;
|
jlahoda@0
|
51 |
import org.netbeans.api.java.source.support.CancellableTreePathScanner;
|
jlahoda@0
|
52 |
import org.netbeans.editor.GuardedDocument;
|
jlahoda@0
|
53 |
import org.netbeans.editor.MarkBlock;
|
jlahoda@0
|
54 |
import org.netbeans.editor.MarkBlockChain;
|
jlahoda@0
|
55 |
import org.openide.filesystems.FileObject;
|
jlahoda@0
|
56 |
|
jlahoda@0
|
57 |
import com.sun.source.tree.Tree.Kind;
|
jlahoda@0
|
58 |
import com.sun.source.util.TreePath;
|
jlahoda@0
|
59 |
import com.sun.source.util.Trees;
|
jlahoda@0
|
60 |
import java.io.IOException;
|
jlahoda@297
|
61 |
import java.util.ArrayList;
|
jlahoda@23
|
62 |
import java.util.Collection;
|
jlahoda@23
|
63 |
import java.util.Collections;
|
jlahoda@297
|
64 |
import java.util.Comparator;
|
jlahoda@0
|
65 |
import java.util.HashMap;
|
jlahoda@0
|
66 |
import java.util.HashSet;
|
jlahoda@522
|
67 |
import java.util.Iterator;
|
jlahoda@0
|
68 |
import java.util.LinkedList;
|
jlahoda@0
|
69 |
import java.util.List;
|
jlahoda@0
|
70 |
import java.util.Map;
|
jlahoda@0
|
71 |
import java.util.Map.Entry;
|
jlahoda@0
|
72 |
import java.util.Set;
|
jlahoda@0
|
73 |
import javax.annotation.processing.ProcessingEnvironment;
|
jlahoda@10
|
74 |
import javax.lang.model.type.TypeMirror;
|
jlahoda@0
|
75 |
import org.netbeans.api.java.source.CompilationInfo;
|
jlahoda@213
|
76 |
import org.netbeans.modules.jackpot30.impl.MessageImpl;
|
jlahoda@23
|
77 |
import org.netbeans.modules.jackpot30.impl.RulesManager;
|
jlahoda@214
|
78 |
import org.netbeans.modules.jackpot30.impl.Utilities;
|
jlahoda@23
|
79 |
import org.netbeans.modules.jackpot30.impl.pm.BulkSearch;
|
jlahoda@23
|
80 |
import org.netbeans.modules.jackpot30.impl.pm.BulkSearch.BulkPattern;
|
jlahoda@23
|
81 |
import org.netbeans.modules.jackpot30.impl.pm.CopyFinder;
|
jlahoda@81
|
82 |
import org.netbeans.modules.jackpot30.impl.pm.CopyFinder.VariableAssignments;
|
jlahoda@23
|
83 |
import org.netbeans.modules.jackpot30.impl.pm.Pattern;
|
jlahoda@269
|
84 |
import org.netbeans.modules.jackpot30.spi.Hacks;
|
jlahoda@23
|
85 |
import org.netbeans.modules.jackpot30.spi.HintContext;
|
jlahoda@23
|
86 |
import org.netbeans.modules.jackpot30.spi.HintDescription;
|
jlahoda@553
|
87 |
import org.netbeans.modules.jackpot30.spi.HintDescription.Condition;
|
jlahoda@553
|
88 |
import org.netbeans.modules.jackpot30.spi.HintDescription.CustomCondition;
|
jlahoda@522
|
89 |
import org.netbeans.modules.jackpot30.spi.HintDescription.DeclarativeFixDescription;
|
jlahoda@554
|
90 |
import org.netbeans.modules.jackpot30.spi.HintDescription.ErrorDescriptionAcceptor;
|
jlahoda@554
|
91 |
import org.netbeans.modules.jackpot30.spi.HintDescription.FixAcceptor;
|
jlahoda@522
|
92 |
import org.netbeans.modules.jackpot30.spi.HintDescription.Literal;
|
jlahoda@522
|
93 |
import org.netbeans.modules.jackpot30.spi.HintDescription.MarkCondition;
|
jlahoda@522
|
94 |
import org.netbeans.modules.jackpot30.spi.HintDescription.MarksWorker;
|
jlahoda@522
|
95 |
import org.netbeans.modules.jackpot30.spi.HintDescription.Operator;
|
jlahoda@553
|
96 |
import org.netbeans.modules.jackpot30.spi.HintDescription.OtherwiseCondition;
|
jlahoda@23
|
97 |
import org.netbeans.modules.jackpot30.spi.HintDescription.PatternDescription;
|
jlahoda@522
|
98 |
import org.netbeans.modules.jackpot30.spi.HintDescription.Selector;
|
jlahoda@522
|
99 |
import org.netbeans.modules.jackpot30.spi.HintDescription.Value;
|
jlahoda@297
|
100 |
import org.netbeans.modules.jackpot30.spi.HintMetadata;
|
jlahoda@297
|
101 |
import org.netbeans.modules.jackpot30.spi.HintMetadata.HintSeverity;
|
jlahoda@555
|
102 |
import org.netbeans.modules.jackpot30.spi.support.FixFactory;
|
jlahoda@0
|
103 |
import org.netbeans.spi.editor.hints.ErrorDescription;
|
jlahoda@554
|
104 |
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
|
jlahoda@522
|
105 |
import org.netbeans.spi.editor.hints.Fix;
|
jlahoda@554
|
106 |
import org.netbeans.spi.editor.hints.Severity;
|
jlahoda@0
|
107 |
import org.openide.util.Exceptions;
|
jlahoda@0
|
108 |
|
jlahoda@0
|
109 |
/**
|
jlahoda@0
|
110 |
*
|
jlahoda@0
|
111 |
* @author lahvac
|
jlahoda@0
|
112 |
*/
|
jlahoda@297
|
113 |
public class HintsInvoker {
|
jlahoda@0
|
114 |
|
jlahoda@107
|
115 |
private final Map<String, Long> timeLog = new HashMap<String, Long>();
|
jlahoda@0
|
116 |
|
jlahoda@297
|
117 |
private final CompilationInfo info;
|
jlahoda@297
|
118 |
private final int caret;
|
jlahoda@297
|
119 |
private final int from;
|
jlahoda@297
|
120 |
private final int to;
|
jlahoda@297
|
121 |
private final AtomicBoolean cancel;
|
jlahoda@0
|
122 |
|
jlahoda@297
|
123 |
public HintsInvoker(CompilationInfo info, AtomicBoolean cancel) {
|
jlahoda@297
|
124 |
this(info, -1, cancel);
|
jlahoda@0
|
125 |
}
|
jlahoda@0
|
126 |
|
jlahoda@297
|
127 |
public HintsInvoker(CompilationInfo info, int caret, AtomicBoolean cancel) {
|
jlahoda@297
|
128 |
this(info, caret, -1, -1, cancel);
|
jlahoda@297
|
129 |
}
|
jlahoda@297
|
130 |
|
jlahoda@297
|
131 |
public HintsInvoker(CompilationInfo info, int from, int to, AtomicBoolean cancel) {
|
jlahoda@297
|
132 |
this(info, -1, from, to, cancel);
|
jlahoda@297
|
133 |
}
|
jlahoda@297
|
134 |
|
jlahoda@297
|
135 |
private HintsInvoker(CompilationInfo info, int caret, int from, int to, AtomicBoolean cancel) {
|
jlahoda@297
|
136 |
this.info = info;
|
jlahoda@297
|
137 |
this.caret = caret;
|
jlahoda@297
|
138 |
this.from = from;
|
jlahoda@297
|
139 |
this.to = to;
|
jlahoda@297
|
140 |
this.cancel = cancel;
|
jlahoda@0
|
141 |
}
|
jlahoda@0
|
142 |
|
jlahoda@0
|
143 |
public List<ErrorDescription> computeHints(CompilationInfo info) {
|
jlahoda@0
|
144 |
return computeHints(info, new TreePath(info.getCompilationUnit()));
|
jlahoda@0
|
145 |
}
|
jlahoda@0
|
146 |
|
jlahoda@0
|
147 |
private List<ErrorDescription> computeHints(CompilationInfo info, TreePath startAt) {
|
jlahoda@297
|
148 |
List<HintDescription> descs = new LinkedList<HintDescription>();
|
jlahoda@297
|
149 |
for (Entry<HintMetadata, Collection<? extends HintDescription>> e : RulesManager.getInstance().allHints.entrySet()) {
|
jlahoda@297
|
150 |
HintMetadata m = e.getKey();
|
jlahoda@297
|
151 |
|
jlahoda@297
|
152 |
if (!RulesManager.getInstance().isHintEnabled(m)) {
|
jlahoda@297
|
153 |
continue;
|
jlahoda@297
|
154 |
}
|
jlahoda@297
|
155 |
|
jlahoda@297
|
156 |
if (caret != -1) {
|
jlahoda@297
|
157 |
if (m.kind == HintMetadata.Kind.SUGGESTION || m.kind == HintMetadata.Kind.SUGGESTION_NON_GUI) {
|
jlahoda@297
|
158 |
descs.addAll(e.getValue());
|
jlahoda@297
|
159 |
} else {
|
jlahoda@297
|
160 |
if (RulesManager.getInstance().getHintSeverity(m) == HintSeverity.CURRENT_LINE_WARNING) {
|
jlahoda@297
|
161 |
descs.addAll(e.getValue());
|
jlahoda@297
|
162 |
}
|
jlahoda@297
|
163 |
}
|
jlahoda@297
|
164 |
} else {
|
jlahoda@297
|
165 |
if (m.kind == HintMetadata.Kind.HINT || m.kind == HintMetadata.Kind.HINT_NON_GUI) {
|
jlahoda@297
|
166 |
if (RulesManager.getInstance().getHintSeverity(m) != HintSeverity.CURRENT_LINE_WARNING || from != (-1)) {
|
jlahoda@297
|
167 |
descs.addAll(e.getValue());
|
jlahoda@297
|
168 |
}
|
jlahoda@297
|
169 |
}
|
jlahoda@297
|
170 |
}
|
jlahoda@297
|
171 |
}
|
jlahoda@297
|
172 |
|
jlahoda@45
|
173 |
Map<Kind, List<HintDescription>> kindHints = new HashMap<Kind, List<HintDescription>>();
|
jlahoda@45
|
174 |
Map<PatternDescription, List<HintDescription>> patternHints = new HashMap<PatternDescription, List<HintDescription>>();
|
jlahoda@45
|
175 |
|
jlahoda@297
|
176 |
RulesManager.sortOut(descs, kindHints, patternHints);
|
jlahoda@32
|
177 |
|
jlahoda@107
|
178 |
long elementBasedStart = System.currentTimeMillis();
|
jlahoda@107
|
179 |
|
jlahoda@32
|
180 |
RulesManager.computeElementBasedHintsXXX(info, cancel, kindHints, patternHints);
|
jlahoda@297
|
181 |
|
jlahoda@107
|
182 |
long elementBasedEnd = System.currentTimeMillis();
|
jlahoda@107
|
183 |
|
jlahoda@297
|
184 |
timeLog.put("Computing Element Based Hints", elementBasedEnd - elementBasedStart);
|
jlahoda@107
|
185 |
|
jlahoda@330
|
186 |
List<ErrorDescription> errors = join(computeHints(info, startAt, kindHints, patternHints, new LinkedList<MessageImpl>()));
|
jlahoda@297
|
187 |
|
jlahoda@297
|
188 |
dumpTimeSpentInHints();
|
jlahoda@297
|
189 |
|
jlahoda@297
|
190 |
return errors;
|
jlahoda@10
|
191 |
}
|
jlahoda@0
|
192 |
|
jlahoda@32
|
193 |
public List<ErrorDescription> computeHints(CompilationInfo info,
|
jlahoda@32
|
194 |
Map<Kind, List<HintDescription>> hints,
|
jlahoda@32
|
195 |
Map<PatternDescription, List<HintDescription>> patternHints) {
|
jlahoda@213
|
196 |
return computeHints(info, hints, patternHints, new LinkedList<MessageImpl>());
|
jlahoda@213
|
197 |
}
|
jlahoda@213
|
198 |
|
jlahoda@213
|
199 |
public List<ErrorDescription> computeHints(CompilationInfo info,
|
jlahoda@213
|
200 |
Map<Kind, List<HintDescription>> hints,
|
jlahoda@213
|
201 |
Map<PatternDescription, List<HintDescription>> patternHints,
|
jlahoda@213
|
202 |
Collection<? super MessageImpl> problems) {
|
jlahoda@330
|
203 |
return join(computeHints(info, new TreePath(info.getCompilationUnit()), hints, patternHints, problems));
|
jlahoda@297
|
204 |
}
|
jlahoda@297
|
205 |
|
jlahoda@330
|
206 |
public Map<HintDescription, List<ErrorDescription>> computeHints(CompilationInfo info,
|
jlahoda@297
|
207 |
TreePath startAt,
|
jlahoda@297
|
208 |
Map<Kind, List<HintDescription>> hints,
|
jlahoda@297
|
209 |
Map<PatternDescription, List<HintDescription>> patternHints,
|
jlahoda@297
|
210 |
Collection<? super MessageImpl> problems) {
|
jlahoda@297
|
211 |
if (caret != -1) {
|
jlahoda@297
|
212 |
TreePath tp = info.getTreeUtilities().pathFor(caret);
|
jlahoda@297
|
213 |
return computeSuggestions(info, tp, hints, patternHints, problems);
|
jlahoda@297
|
214 |
} else {
|
jlahoda@297
|
215 |
if (from != (-1) && to != (-1)) {
|
jlahoda@297
|
216 |
return computeHintsInSpan(info, hints, patternHints, problems);
|
jlahoda@297
|
217 |
} else {
|
jlahoda@330
|
218 |
return computeHintsImpl(info, startAt, hints, patternHints, problems);
|
jlahoda@297
|
219 |
}
|
jlahoda@297
|
220 |
}
|
jlahoda@32
|
221 |
}
|
jlahoda@32
|
222 |
|
jlahoda@330
|
223 |
Map<HintDescription, List<ErrorDescription>> computeHintsImpl(CompilationInfo info,
|
jlahoda@10
|
224 |
TreePath startAt,
|
jlahoda@23
|
225 |
Map<Kind, List<HintDescription>> hints,
|
jlahoda@213
|
226 |
Map<PatternDescription, List<HintDescription>> patternHints,
|
jlahoda@213
|
227 |
Collection<? super MessageImpl> problems) {
|
jlahoda@330
|
228 |
Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
|
jlahoda@0
|
229 |
|
jlahoda@297
|
230 |
long kindCount = 0;
|
jlahoda@297
|
231 |
|
jlahoda@297
|
232 |
for (Entry<Kind, List<HintDescription>> e : hints.entrySet()) {
|
jlahoda@297
|
233 |
kindCount += e.getValue().size();
|
jlahoda@297
|
234 |
}
|
jlahoda@297
|
235 |
|
jlahoda@297
|
236 |
timeLog.put("[C] Kind Based Hints", kindCount);
|
jlahoda@297
|
237 |
|
jlahoda@10
|
238 |
if (!hints.isEmpty()) {
|
jlahoda@107
|
239 |
long kindStart = System.currentTimeMillis();
|
jlahoda@107
|
240 |
|
jlahoda@10
|
241 |
new ScannerImpl(info, cancel, hints).scan(startAt, errors);
|
jlahoda@107
|
242 |
|
jlahoda@107
|
243 |
long kindEnd = System.currentTimeMillis();
|
jlahoda@107
|
244 |
|
jlahoda@297
|
245 |
timeLog.put("Kind Based Hints", kindEnd - kindStart);
|
jlahoda@10
|
246 |
}
|
jlahoda@107
|
247 |
|
jlahoda@297
|
248 |
timeLog.put("[C] Pattern Based Hints", (long) patternHints.size());
|
jlahoda@297
|
249 |
|
jlahoda@107
|
250 |
long patternStart = System.currentTimeMillis();
|
jlahoda@297
|
251 |
|
jlahoda@47
|
252 |
Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
|
jlahoda@47
|
253 |
|
jlahoda@297
|
254 |
long bulkPatternStart = System.currentTimeMillis();
|
jlahoda@297
|
255 |
|
jlahoda@297
|
256 |
BulkPattern bulkPattern = BulkSearch.getDefault().create(info, patternTests.keySet());
|
jlahoda@297
|
257 |
|
jlahoda@297
|
258 |
long bulkPatternEnd = System.currentTimeMillis();
|
jlahoda@297
|
259 |
|
jlahoda@297
|
260 |
timeLog.put("Bulk Pattern preparation", bulkPatternEnd - bulkPatternStart);
|
jlahoda@297
|
261 |
|
jlahoda@107
|
262 |
long bulkStart = System.currentTimeMillis();
|
jlahoda@297
|
263 |
|
jlahoda@297
|
264 |
Map<String, Collection<TreePath>> occurringPatterns = BulkSearch.getDefault().match(info, startAt, bulkPattern, timeLog);
|
jlahoda@297
|
265 |
|
jlahoda@107
|
266 |
long bulkEnd = System.currentTimeMillis();
|
jlahoda@107
|
267 |
|
jlahoda@297
|
268 |
timeLog.put("Bulk Search", bulkEnd - bulkStart);
|
jlahoda@297
|
269 |
|
jlahoda@330
|
270 |
mergeAll(errors, doComputeHints(info, occurringPatterns, patternTests, patternHints, problems));
|
jlahoda@47
|
271 |
|
jlahoda@107
|
272 |
long patternEnd = System.currentTimeMillis();
|
jlahoda@107
|
273 |
|
jlahoda@297
|
274 |
timeLog.put("Pattern Based Hints", patternEnd - patternStart);
|
jlahoda@297
|
275 |
|
jlahoda@297
|
276 |
return errors;
|
jlahoda@297
|
277 |
}
|
jlahoda@297
|
278 |
|
jlahoda@330
|
279 |
Map<HintDescription, List<ErrorDescription>> computeHintsInSpan(CompilationInfo info,
|
jlahoda@297
|
280 |
Map<Kind, List<HintDescription>> hints,
|
jlahoda@297
|
281 |
Map<PatternDescription, List<HintDescription>> patternHints,
|
jlahoda@297
|
282 |
Collection<? super MessageImpl> problems) {
|
jlahoda@297
|
283 |
|
jlahoda@297
|
284 |
TreePath path = info.getTreeUtilities().pathFor((from + to) / 2);
|
jlahoda@297
|
285 |
|
jlahoda@297
|
286 |
while (path.getLeaf().getKind() != Kind.COMPILATION_UNIT) {
|
jlahoda@297
|
287 |
int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), path.getLeaf());
|
jlahoda@297
|
288 |
int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), path.getLeaf());
|
jlahoda@297
|
289 |
|
jlahoda@297
|
290 |
if (start <= from && end >= to) {
|
jlahoda@297
|
291 |
break;
|
jlahoda@297
|
292 |
}
|
jlahoda@297
|
293 |
|
jlahoda@297
|
294 |
path = path.getParentPath();
|
jlahoda@297
|
295 |
}
|
jlahoda@297
|
296 |
|
jlahoda@330
|
297 |
Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
|
jlahoda@297
|
298 |
|
jlahoda@297
|
299 |
if (!hints.isEmpty()) {
|
jlahoda@297
|
300 |
long kindStart = System.currentTimeMillis();
|
jlahoda@297
|
301 |
|
jlahoda@297
|
302 |
new ScannerImpl(info, cancel, hints).scan(path, errors);
|
jlahoda@297
|
303 |
|
jlahoda@297
|
304 |
long kindEnd = System.currentTimeMillis();
|
jlahoda@297
|
305 |
|
jlahoda@297
|
306 |
timeLog.put("Kind Based Hints", kindEnd - kindStart);
|
jlahoda@297
|
307 |
}
|
jlahoda@297
|
308 |
|
jlahoda@297
|
309 |
if (!patternHints.isEmpty()) {
|
jlahoda@297
|
310 |
long patternStart = System.currentTimeMillis();
|
jlahoda@297
|
311 |
|
jlahoda@297
|
312 |
Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
|
jlahoda@297
|
313 |
|
jlahoda@297
|
314 |
long bulkStart = System.currentTimeMillis();
|
jlahoda@297
|
315 |
|
jlahoda@297
|
316 |
BulkPattern bulkPattern = BulkSearch.getDefault().create(info, patternTests.keySet());
|
jlahoda@297
|
317 |
Map<String, Collection<TreePath>> occurringPatterns = BulkSearch.getDefault().match(info, path, bulkPattern, timeLog);
|
jlahoda@297
|
318 |
|
jlahoda@297
|
319 |
long bulkEnd = System.currentTimeMillis();
|
jlahoda@297
|
320 |
|
jlahoda@297
|
321 |
timeLog.put("Bulk Search", bulkEnd - bulkStart);
|
jlahoda@297
|
322 |
|
jlahoda@330
|
323 |
mergeAll(errors, doComputeHints(info, occurringPatterns, patternTests, patternHints, problems));
|
jlahoda@297
|
324 |
|
jlahoda@297
|
325 |
long patternEnd = System.currentTimeMillis();
|
jlahoda@297
|
326 |
|
jlahoda@297
|
327 |
timeLog.put("Pattern Based Hints", patternEnd - patternStart);
|
jlahoda@297
|
328 |
}
|
jlahoda@297
|
329 |
|
jlahoda@297
|
330 |
return errors;
|
jlahoda@297
|
331 |
}
|
jlahoda@297
|
332 |
|
jlahoda@330
|
333 |
Map<HintDescription, List<ErrorDescription>> computeSuggestions(CompilationInfo info,
|
jlahoda@297
|
334 |
TreePath workOn,
|
jlahoda@297
|
335 |
Map<Kind, List<HintDescription>> hints,
|
jlahoda@297
|
336 |
Map<PatternDescription, List<HintDescription>> patternHints,
|
jlahoda@297
|
337 |
Collection<? super MessageImpl> problems) {
|
jlahoda@330
|
338 |
Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
|
jlahoda@297
|
339 |
|
jlahoda@297
|
340 |
if (!hints.isEmpty()) {
|
jlahoda@297
|
341 |
long kindStart = System.currentTimeMillis();
|
jlahoda@297
|
342 |
|
jlahoda@297
|
343 |
TreePath proc = workOn;
|
jlahoda@297
|
344 |
|
jlahoda@297
|
345 |
while (proc != null) {
|
jlahoda@297
|
346 |
new ScannerImpl(info, cancel, hints).scanDoNotGoDeeper(proc, errors);
|
jlahoda@297
|
347 |
proc = proc.getParentPath();
|
jlahoda@297
|
348 |
}
|
jlahoda@297
|
349 |
|
jlahoda@297
|
350 |
long kindEnd = System.currentTimeMillis();
|
jlahoda@297
|
351 |
|
jlahoda@297
|
352 |
timeLog.put("Kind Based Suggestions", kindEnd - kindStart);
|
jlahoda@297
|
353 |
}
|
jlahoda@297
|
354 |
|
jlahoda@297
|
355 |
if (!patternHints.isEmpty()) {
|
jlahoda@323
|
356 |
long patternStart = System.currentTimeMillis();
|
jlahoda@323
|
357 |
|
jlahoda@323
|
358 |
Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
|
jlahoda@323
|
359 |
|
jlahoda@323
|
360 |
//pretend that all the patterns occur on all treepaths from the current path
|
jlahoda@323
|
361 |
//up (probably faster than using BulkSearch over whole file)
|
jlahoda@323
|
362 |
//TODO: what about machint trees under the current path?
|
jlahoda@323
|
363 |
Set<TreePath> paths = new HashSet<TreePath>();
|
jlahoda@323
|
364 |
|
jlahoda@323
|
365 |
TreePath tp = workOn;
|
jlahoda@323
|
366 |
|
jlahoda@323
|
367 |
while (tp != null) {
|
jlahoda@323
|
368 |
paths.add(tp);
|
jlahoda@323
|
369 |
tp = tp.getParentPath();
|
jlahoda@323
|
370 |
}
|
jlahoda@323
|
371 |
|
jlahoda@323
|
372 |
Map<String, Collection<TreePath>> occurringPatterns = new HashMap<String, Collection<TreePath>>();
|
jlahoda@323
|
373 |
|
jlahoda@323
|
374 |
for (String p : patternTests.keySet()) {
|
jlahoda@323
|
375 |
occurringPatterns.put(p, paths);
|
jlahoda@323
|
376 |
}
|
jlahoda@323
|
377 |
|
jlahoda@297
|
378 |
// long bulkStart = System.currentTimeMillis();
|
jlahoda@297
|
379 |
//
|
jlahoda@297
|
380 |
// BulkPattern bulkPattern = BulkSearch.getDefault().create(info, patternTests.keySet());
|
jlahoda@323
|
381 |
// Map<String, Collection<TreePath>> occurringPatterns = BulkSearch.getDefault().match(info, new TreePath(info.getCompilationUnit()), bulkPattern, timeLog);
|
jlahoda@297
|
382 |
//
|
jlahoda@297
|
383 |
// long bulkEnd = System.currentTimeMillis();
|
jlahoda@297
|
384 |
//
|
jlahoda@323
|
385 |
// Set<Tree> acceptedLeafs = new HashSet<Tree>();
|
jlahoda@323
|
386 |
//
|
jlahoda@323
|
387 |
// TreePath tp = workOn;
|
jlahoda@323
|
388 |
//
|
jlahoda@323
|
389 |
// while (tp != null) {
|
jlahoda@323
|
390 |
// acceptedLeafs.add(tp.getLeaf());
|
jlahoda@323
|
391 |
// tp = tp.getParentPath();
|
jlahoda@323
|
392 |
// }
|
jlahoda@323
|
393 |
//
|
jlahoda@323
|
394 |
// for (Entry<String, Collection<TreePath>> e : occurringPatterns.entrySet()) {
|
jlahoda@323
|
395 |
// for (Iterator<TreePath> it = e.getValue().iterator(); it.hasNext(); ) {
|
jlahoda@323
|
396 |
// if (!acceptedLeafs.contains(it.next().getLeaf())) {
|
jlahoda@323
|
397 |
// it.remove();
|
jlahoda@323
|
398 |
// }
|
jlahoda@323
|
399 |
// }
|
jlahoda@323
|
400 |
// }
|
jlahoda@323
|
401 |
//
|
jlahoda@297
|
402 |
// timeLog.put("Bulk Search", bulkEnd - bulkStart);
|
jlahoda@323
|
403 |
|
jlahoda@330
|
404 |
mergeAll(errors, doComputeHints(info, occurringPatterns, patternTests, patternHints, problems));
|
jlahoda@323
|
405 |
|
jlahoda@323
|
406 |
long patternEnd = System.currentTimeMillis();
|
jlahoda@323
|
407 |
|
jlahoda@323
|
408 |
timeLog.put("Pattern Based Hints", patternEnd - patternStart);
|
jlahoda@297
|
409 |
}
|
jlahoda@107
|
410 |
|
jlahoda@47
|
411 |
return errors;
|
jlahoda@47
|
412 |
}
|
jlahoda@47
|
413 |
|
jlahoda@330
|
414 |
public Map<HintDescription, List<ErrorDescription>> doComputeHints(CompilationInfo info, Map<String, Collection<TreePath>> occurringPatterns, Map<String, List<PatternDescription>> patterns, Map<PatternDescription, List<HintDescription>> patternHints) throws IllegalStateException {
|
jlahoda@323
|
415 |
return doComputeHints(info, occurringPatterns, patterns, patternHints, new LinkedList<MessageImpl>());
|
jlahoda@47
|
416 |
}
|
jlahoda@47
|
417 |
|
jlahoda@47
|
418 |
public static Map<String, List<PatternDescription>> computePatternTests(Map<PatternDescription, List<HintDescription>> patternHints) {
|
jlahoda@10
|
419 |
Map<String, List<PatternDescription>> patternTests = new HashMap<String, List<PatternDescription>>();
|
jlahoda@23
|
420 |
for (Entry<PatternDescription, List<HintDescription>> e : patternHints.entrySet()) {
|
jlahoda@10
|
421 |
String p = e.getKey().getPattern();
|
jlahoda@10
|
422 |
List<PatternDescription> descs = patternTests.get(p);
|
jlahoda@10
|
423 |
if (descs == null) {
|
jlahoda@10
|
424 |
patternTests.put(p, descs = new LinkedList<PatternDescription>());
|
jlahoda@10
|
425 |
}
|
jlahoda@10
|
426 |
descs.add(e.getKey());
|
jlahoda@10
|
427 |
}
|
jlahoda@47
|
428 |
return patternTests;
|
jlahoda@47
|
429 |
}
|
jlahoda@297
|
430 |
|
jlahoda@330
|
431 |
private Map<HintDescription, List<ErrorDescription>> doComputeHints(CompilationInfo info, Map<String, Collection<TreePath>> occurringPatterns, Map<String, List<PatternDescription>> patterns, Map<PatternDescription, List<HintDescription>> patternHints, Collection<? super MessageImpl> problems) throws IllegalStateException {
|
jlahoda@330
|
432 |
Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
|
jlahoda@522
|
433 |
List<HintEvaluationData> evaluationData = new LinkedList<HintEvaluationData>();
|
jlahoda@297
|
434 |
|
jlahoda@67
|
435 |
for (Entry<String, Collection<TreePath>> occ : occurringPatterns.entrySet()) {
|
jlahoda@67
|
436 |
for (PatternDescription d : patterns.get(occ.getKey())) {
|
jlahoda@10
|
437 |
Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
|
jlahoda@10
|
438 |
|
jlahoda@10
|
439 |
for (Entry<String, String> e : d.getConstraints().entrySet()) {
|
jlahoda@269
|
440 |
constraints.put(e.getKey(), Hacks.parseFQNType(info, e.getValue()));
|
jlahoda@10
|
441 |
}
|
jlahoda@10
|
442 |
|
jlahoda@220
|
443 |
Pattern p = Pattern.compile(info, occ.getKey(), constraints, d.getImports());
|
jlahoda@10
|
444 |
TreePath toplevel = new TreePath(info.getCompilationUnit());
|
jlahoda@10
|
445 |
TreePath patt = new TreePath(toplevel, p.getPattern());
|
jlahoda@10
|
446 |
|
jlahoda@67
|
447 |
for (TreePath candidate : occ.getValue()) {
|
jlahoda@81
|
448 |
VariableAssignments verified = CopyFinder.computeVariables(info, patt, candidate, cancel, p.getConstraints());
|
jlahoda@67
|
449 |
|
jlahoda@67
|
450 |
if (verified == null) {
|
jlahoda@67
|
451 |
continue;
|
jlahoda@67
|
452 |
}
|
jlahoda@297
|
453 |
|
jlahoda@214
|
454 |
Set<String> suppressedWarnings = new HashSet<String>(Utilities.findSuppressedWarnings(info, candidate));
|
jlahoda@47
|
455 |
|
jlahoda@23
|
456 |
for (HintDescription hd : patternHints.get(d)) {
|
jlahoda@297
|
457 |
HintMetadata hm = hd.getMetadata();
|
jlahoda@455
|
458 |
HintContext c = new HintContext(info, hm, candidate, verified.variables, verified.multiVariables, verified.variables2Names, constraints, problems);
|
jlahoda@297
|
459 |
|
jlahoda@297
|
460 |
if (!Collections.disjoint(suppressedWarnings, hm.suppressWarnings))
|
jlahoda@214
|
461 |
continue;
|
jlahoda@297
|
462 |
|
jlahoda@522
|
463 |
if (hd.getWorker() instanceof MarksWorker) {
|
jlahoda@527
|
464 |
HintContext workerContext = new HintContext(c);
|
jlahoda@527
|
465 |
|
jlahoda@527
|
466 |
workerContext.enterScope();
|
jlahoda@527
|
467 |
|
jlahoda@522
|
468 |
MarksWorker mw = (MarksWorker) hd.getWorker();
|
jlahoda@522
|
469 |
List<FixEvaluationData> fixData = new LinkedList<FixEvaluationData>();
|
jlahoda@522
|
470 |
|
jlahoda@522
|
471 |
for (DeclarativeFixDescription fd : mw.fixes) {
|
jlahoda@527
|
472 |
HintContext fixContext = new HintContext(workerContext);
|
jlahoda@527
|
473 |
|
jlahoda@527
|
474 |
fixContext.enterScope();
|
jlahoda@554
|
475 |
fixData.add(new FixEvaluationData(fixContext, new LinkedList<Condition>(fd.marks), fd.acceptor));
|
jlahoda@522
|
476 |
}
|
jlahoda@522
|
477 |
|
jlahoda@553
|
478 |
HintEvaluationData data = new HintEvaluationData(workerContext, hd, new LinkedList<Condition>(mw.marks), mw.acceptor, fixData);
|
jlahoda@522
|
479 |
|
jlahoda@522
|
480 |
evaluationData.add(data);
|
jlahoda@522
|
481 |
continue;
|
jlahoda@522
|
482 |
}
|
jlahoda@522
|
483 |
|
jlahoda@297
|
484 |
Collection<? extends ErrorDescription> workerErrors = runHint(hd, c);
|
jlahoda@23
|
485 |
|
jlahoda@23
|
486 |
if (workerErrors != null) {
|
jlahoda@330
|
487 |
merge(errors, hd, workerErrors);
|
jlahoda@23
|
488 |
}
|
jlahoda@10
|
489 |
}
|
jlahoda@10
|
490 |
}
|
jlahoda@10
|
491 |
}
|
jlahoda@10
|
492 |
}
|
jlahoda@0
|
493 |
|
jlahoda@522
|
494 |
Map<Tree, Map<String, Object>> marks = new HashMap<Tree, Map<String, Object>>();
|
jlahoda@522
|
495 |
|
jlahoda@522
|
496 |
for (HintEvaluationData hed : evaluationData) {
|
jlahoda@522
|
497 |
enterSpeculativeAssignments(hed.ctx, hed.marks, marks);
|
jlahoda@522
|
498 |
|
jlahoda@522
|
499 |
for (FixEvaluationData fed : hed.fixDescriptions) {
|
jlahoda@522
|
500 |
//XXX: there is currently no test that would test this: (seee testSpeculativeAssignmentForFixes)
|
jlahoda@522
|
501 |
enterSpeculativeAssignments(hed.ctx, fed.marks, marks);
|
jlahoda@522
|
502 |
}
|
jlahoda@522
|
503 |
}
|
jlahoda@522
|
504 |
|
jlahoda@522
|
505 |
boolean wasChange = true;
|
jlahoda@522
|
506 |
|
jlahoda@522
|
507 |
while (wasChange /*!evaluationData.isEmpty()*/) {
|
jlahoda@522
|
508 |
boolean currentWasChange = false;
|
jlahoda@522
|
509 |
|
jlahoda@522
|
510 |
for (Iterator<HintEvaluationData> it = evaluationData.iterator(); it.hasNext(); ) {
|
jlahoda@522
|
511 |
HintEvaluationData hed = it.next();
|
jlahoda@522
|
512 |
int origMarksSize = hed.marks.size();
|
jlahoda@522
|
513 |
|
jlahoda@553
|
514 |
Boolean hres = processConditions(hed.ctx, marks, hed.marks, -1, -1);
|
jlahoda@522
|
515 |
|
jlahoda@522
|
516 |
currentWasChange |= origMarksSize != hed.marks.size();
|
jlahoda@522
|
517 |
|
jlahoda@522
|
518 |
if (hres == null) {
|
jlahoda@522
|
519 |
//XXX???
|
jlahoda@522
|
520 |
continue;
|
jlahoda@522
|
521 |
}
|
jlahoda@522
|
522 |
|
jlahoda@522
|
523 |
if (hres != null && !hres) {
|
jlahoda@522
|
524 |
currentWasChange = true;
|
jlahoda@527
|
525 |
clearSpeculativeAssignments(hed.ctx, hed.marks, marks);
|
jlahoda@522
|
526 |
for (FixEvaluationData fed : hed.fixDescriptions) {
|
jlahoda@527
|
527 |
clearSpeculativeAssignments(hed.ctx, fed.marks, marks);
|
jlahoda@522
|
528 |
}
|
jlahoda@522
|
529 |
it.remove();
|
jlahoda@522
|
530 |
continue;
|
jlahoda@522
|
531 |
}
|
jlahoda@522
|
532 |
|
jlahoda@522
|
533 |
for (Iterator<FixEvaluationData> fixes = hed.fixDescriptions.iterator(); fixes.hasNext(); ) {
|
jlahoda@522
|
534 |
FixEvaluationData fed = fixes.next();
|
jlahoda@522
|
535 |
int o = fed.marks.size();
|
jlahoda@553
|
536 |
Boolean res = processConditions(fed.ctx, marks, fed.marks, hed.fixDescriptions.size(), hed.createdFixes.size());
|
jlahoda@522
|
537 |
|
jlahoda@522
|
538 |
currentWasChange |= o != fed.marks.size();
|
jlahoda@522
|
539 |
|
jlahoda@522
|
540 |
if (res == null) continue;
|
jlahoda@522
|
541 |
|
jlahoda@522
|
542 |
if (res) {
|
jlahoda@554
|
543 |
Fix fix = fed.acceptor.accept(fed.ctx);
|
jlahoda@522
|
544 |
|
jlahoda@554
|
545 |
if (fix != null) {
|
jlahoda@522
|
546 |
hed.createdFixes.add(fix);
|
jlahoda@522
|
547 |
}
|
jlahoda@522
|
548 |
} else {
|
jlahoda@527
|
549 |
clearSpeculativeAssignments(fed.ctx, fed.marks, marks);
|
jlahoda@522
|
550 |
}
|
jlahoda@522
|
551 |
|
jlahoda@522
|
552 |
fixes.remove();
|
jlahoda@522
|
553 |
currentWasChange = true;
|
jlahoda@522
|
554 |
}
|
jlahoda@522
|
555 |
|
jlahoda@522
|
556 |
if (!wasChange && !currentWasChange) {
|
jlahoda@522
|
557 |
hed.fixDescriptions.clear();
|
jlahoda@522
|
558 |
}
|
jlahoda@522
|
559 |
|
jlahoda@522
|
560 |
if (hed.fixDescriptions.isEmpty()) {
|
jlahoda@554
|
561 |
//XXX: @SuppressWarnings!
|
jlahoda@554
|
562 |
ErrorDescription ed = hed.acceptor.accept(hed.ctx);
|
jlahoda@555
|
563 |
List<String> swKeys = new ArrayList<String>();
|
jlahoda@522
|
564 |
|
jlahoda@555
|
565 |
for (String key : hed.hd.getSuppressWarnings()) {
|
jlahoda@555
|
566 |
if (key == null) break;
|
jlahoda@555
|
567 |
swKeys.add(key);
|
jlahoda@555
|
568 |
}
|
jlahoda@555
|
569 |
|
jlahoda@555
|
570 |
List<Fix> fixes = new ArrayList<Fix>();
|
jlahoda@555
|
571 |
|
jlahoda@555
|
572 |
fixes.addAll(hed.createdFixes);
|
jlahoda@555
|
573 |
|
jlahoda@555
|
574 |
if (!swKeys.isEmpty()) {
|
jlahoda@555
|
575 |
fixes.addAll(FixFactory.createSuppressWarnings(info, hed.ctx.getPath(), swKeys.toArray(new String[0])));
|
jlahoda@555
|
576 |
}
|
jlahoda@555
|
577 |
|
jlahoda@555
|
578 |
ed = ErrorDescriptionFactory.createErrorDescription(ed.getSeverity(), ed.getDescription(), fixes, ed.getFile(), ed.getRange().getBegin().getOffset(), ed.getRange().getEnd().getOffset());
|
jlahoda@554
|
579 |
|
jlahoda@554
|
580 |
if (ed != null) {
|
jlahoda@522
|
581 |
merge(errors, hed.hd, ed);
|
jlahoda@522
|
582 |
}
|
jlahoda@522
|
583 |
it.remove();
|
jlahoda@522
|
584 |
}
|
jlahoda@522
|
585 |
}
|
jlahoda@522
|
586 |
|
jlahoda@522
|
587 |
wasChange = currentWasChange;
|
jlahoda@522
|
588 |
}
|
jlahoda@522
|
589 |
|
jlahoda@0
|
590 |
return errors;
|
jlahoda@0
|
591 |
}
|
jlahoda@297
|
592 |
|
jlahoda@23
|
593 |
// public static void computeHints(URI file, ProcessingEnvironment env, CompilationUnitTree cut, RulesManager m) {
|
jlahoda@23
|
594 |
// Map<Kind, HintDescription> hints = m.getKindBasedHints();
|
jlahoda@23
|
595 |
//
|
jlahoda@23
|
596 |
// if (hints.isEmpty()) {
|
jlahoda@23
|
597 |
// return ;
|
jlahoda@23
|
598 |
// }
|
jlahoda@23
|
599 |
//
|
jlahoda@23
|
600 |
// List<ErrorDescription> errors = new LinkedList<ErrorDescription>();
|
jlahoda@23
|
601 |
//
|
jlahoda@23
|
602 |
// File af = new File(file.getPath());
|
jlahoda@23
|
603 |
// FileObject f = FileUtil.toFileObject(af);
|
jlahoda@23
|
604 |
//
|
jlahoda@23
|
605 |
// new ScannerImpl(f, env, hints).scan(cut, errors);
|
jlahoda@23
|
606 |
//
|
jlahoda@23
|
607 |
// for (ErrorDescription ed : errors) {
|
jlahoda@23
|
608 |
// Diagnostic.Kind k;
|
jlahoda@23
|
609 |
//
|
jlahoda@23
|
610 |
// switch (ed.getSeverity()) {
|
jlahoda@23
|
611 |
// case ERROR:
|
jlahoda@23
|
612 |
// k = Diagnostic.Kind.ERROR;
|
jlahoda@23
|
613 |
// break;
|
jlahoda@23
|
614 |
// default:
|
jlahoda@23
|
615 |
// k = Diagnostic.Kind.WARNING;
|
jlahoda@23
|
616 |
// break;
|
jlahoda@23
|
617 |
// }
|
jlahoda@23
|
618 |
//
|
jlahoda@23
|
619 |
// env.getMessager().printMessage(k, ed.getDescription());
|
jlahoda@23
|
620 |
// }
|
jlahoda@23
|
621 |
// }
|
jlahoda@297
|
622 |
|
jlahoda@297
|
623 |
public Map<String, Long> getTimeLog() {
|
jlahoda@297
|
624 |
return timeLog;
|
jlahoda@297
|
625 |
}
|
jlahoda@297
|
626 |
|
jlahoda@330
|
627 |
private final class ScannerImpl extends CancellableTreePathScanner<Void, Map<HintDescription, List<ErrorDescription>>> {
|
jlahoda@0
|
628 |
|
jlahoda@0
|
629 |
private final Stack<Set<String>> suppresWarnings = new Stack<Set<String>>();
|
jlahoda@0
|
630 |
private final CompilationInfo info;
|
jlahoda@0
|
631 |
private final FileObject file;
|
jlahoda@0
|
632 |
private final ProcessingEnvironment env;
|
jlahoda@23
|
633 |
private final Map<Kind, List<HintDescription>> hints;
|
jlahoda@0
|
634 |
|
jlahoda@23
|
635 |
public ScannerImpl(CompilationInfo info, AtomicBoolean cancel, Map<Kind, List<HintDescription>> hints) {
|
jlahoda@0
|
636 |
super(cancel);
|
jlahoda@0
|
637 |
this.info = info;
|
jlahoda@0
|
638 |
this.file = null;
|
jlahoda@0
|
639 |
this.env = null;
|
jlahoda@0
|
640 |
this.hints = hints;
|
jlahoda@0
|
641 |
}
|
jlahoda@0
|
642 |
|
jlahoda@23
|
643 |
public ScannerImpl(FileObject file, ProcessingEnvironment env, Map<Kind, List<HintDescription>> hints) {
|
jlahoda@0
|
644 |
super(new AtomicBoolean());
|
jlahoda@0
|
645 |
this.info = null;
|
jlahoda@0
|
646 |
this.file = file;
|
jlahoda@0
|
647 |
this.env = env;
|
jlahoda@0
|
648 |
this.hints = hints;
|
jlahoda@0
|
649 |
}
|
jlahoda@0
|
650 |
|
jlahoda@330
|
651 |
private void runAndAdd(TreePath path, List<HintDescription> rules, Map<HintDescription, List<ErrorDescription>> d) {
|
jlahoda@0
|
652 |
if (rules != null && !isInGuarded(info, path)) {
|
jlahoda@297
|
653 |
OUTER: for (HintDescription hd : rules) {
|
jlahoda@0
|
654 |
if (isCanceled()) {
|
jlahoda@0
|
655 |
return ;
|
jlahoda@0
|
656 |
}
|
jlahoda@0
|
657 |
|
jlahoda@297
|
658 |
HintMetadata hm = hd.getMetadata();
|
jlahoda@0
|
659 |
|
jlahoda@297
|
660 |
for (String wname : hm.suppressWarnings) {
|
jlahoda@297
|
661 |
if( !suppresWarnings.empty() && suppresWarnings.peek().contains(wname)) {
|
jlahoda@297
|
662 |
continue OUTER;
|
jlahoda@0
|
663 |
}
|
jlahoda@0
|
664 |
}
|
jlahoda@0
|
665 |
|
jlahoda@297
|
666 |
HintContext c = new HintContext(info, hm, path, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap());
|
jlahoda@297
|
667 |
Collection<? extends ErrorDescription> errors = runHint(hd, c);
|
jlahoda@0
|
668 |
|
jlahoda@297
|
669 |
if (errors != null) {
|
jlahoda@330
|
670 |
merge(d, hd, errors);
|
jlahoda@0
|
671 |
}
|
jlahoda@0
|
672 |
}
|
jlahoda@0
|
673 |
}
|
jlahoda@0
|
674 |
}
|
jlahoda@0
|
675 |
|
jlahoda@0
|
676 |
@Override
|
jlahoda@330
|
677 |
public Void scan(Tree tree, Map<HintDescription, List<ErrorDescription>> p) {
|
jlahoda@0
|
678 |
if (tree == null)
|
jlahoda@0
|
679 |
return null;
|
jlahoda@0
|
680 |
|
jlahoda@0
|
681 |
TreePath tp = new TreePath(getCurrentPath(), tree);
|
jlahoda@0
|
682 |
Kind k = tree.getKind();
|
jlahoda@0
|
683 |
|
jlahoda@297
|
684 |
boolean b = pushSuppressWarrnings(tp);
|
jlahoda@297
|
685 |
try {
|
jlahoda@297
|
686 |
runAndAdd(tp, hints.get(k), p);
|
jlahoda@0
|
687 |
|
jlahoda@297
|
688 |
if (isCanceled()) {
|
jlahoda@297
|
689 |
return null;
|
jlahoda@297
|
690 |
}
|
jlahoda@297
|
691 |
|
jlahoda@297
|
692 |
return super.scan(tree, p);
|
jlahoda@297
|
693 |
} finally {
|
jlahoda@297
|
694 |
if (b) {
|
jlahoda@297
|
695 |
suppresWarnings.pop();
|
jlahoda@297
|
696 |
}
|
jlahoda@0
|
697 |
}
|
jlahoda@0
|
698 |
}
|
jlahoda@0
|
699 |
|
jlahoda@0
|
700 |
@Override
|
jlahoda@330
|
701 |
public Void scan(TreePath path, Map<HintDescription, List<ErrorDescription>> p) {
|
jlahoda@0
|
702 |
Kind k = path.getLeaf().getKind();
|
jlahoda@297
|
703 |
boolean b = pushSuppressWarrnings(path);
|
jlahoda@297
|
704 |
try {
|
jlahoda@297
|
705 |
runAndAdd(path, hints.get(k), p);
|
jlahoda@0
|
706 |
|
jlahoda@297
|
707 |
if (isCanceled()) {
|
jlahoda@297
|
708 |
return null;
|
jlahoda@297
|
709 |
}
|
jlahoda@297
|
710 |
|
jlahoda@297
|
711 |
return super.scan(path, p);
|
jlahoda@297
|
712 |
} finally {
|
jlahoda@297
|
713 |
if (b) {
|
jlahoda@297
|
714 |
suppresWarnings.pop();
|
jlahoda@297
|
715 |
}
|
jlahoda@0
|
716 |
}
|
jlahoda@0
|
717 |
}
|
jlahoda@0
|
718 |
|
jlahoda@330
|
719 |
public void scanDoNotGoDeeper(TreePath path, Map<HintDescription, List<ErrorDescription>> p) {
|
jlahoda@297
|
720 |
Kind k = path.getLeaf().getKind();
|
jlahoda@297
|
721 |
runAndAdd(path, hints.get(k), p);
|
jlahoda@0
|
722 |
}
|
jlahoda@0
|
723 |
|
jlahoda@297
|
724 |
private boolean pushSuppressWarrnings(TreePath path) {
|
jlahoda@297
|
725 |
switch(path.getLeaf().getKind()) {
|
jlahoda@297
|
726 |
case CLASS:
|
jlahoda@297
|
727 |
case METHOD:
|
jlahoda@297
|
728 |
case VARIABLE:
|
jlahoda@297
|
729 |
Set<String> current = suppresWarnings.size() == 0 ? null : suppresWarnings.peek();
|
jlahoda@297
|
730 |
Set<String> nju = current == null ? new HashSet<String>() : new HashSet<String>(current);
|
jlahoda@0
|
731 |
|
jlahoda@297
|
732 |
Element e = getTrees().getElement(path);
|
jlahoda@0
|
733 |
|
jlahoda@297
|
734 |
if ( e != null) {
|
jlahoda@297
|
735 |
for (AnnotationMirror am : e.getAnnotationMirrors()) {
|
jlahoda@297
|
736 |
String name = ((TypeElement)am.getAnnotationType().asElement()).getQualifiedName().toString();
|
jlahoda@297
|
737 |
if ( "java.lang.SuppressWarnings".equals(name) ) { // NOI18N
|
jlahoda@297
|
738 |
Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = am.getElementValues();
|
jlahoda@297
|
739 |
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : elementValues.entrySet()) {
|
jlahoda@297
|
740 |
if( "value".equals(entry.getKey().getSimpleName().toString()) ) { // NOI18N
|
jlahoda@297
|
741 |
Object value = entry.getValue().getValue();
|
jlahoda@297
|
742 |
if ( value instanceof List) {
|
jlahoda@297
|
743 |
for (Object av : (List)value) {
|
jlahoda@297
|
744 |
if( av instanceof AnnotationValue ) {
|
jlahoda@297
|
745 |
Object wname = ((AnnotationValue)av).getValue();
|
jlahoda@297
|
746 |
if ( wname instanceof String ) {
|
jlahoda@297
|
747 |
nju.add((String)wname);
|
jlahoda@297
|
748 |
}
|
jlahoda@297
|
749 |
}
|
jlahoda@0
|
750 |
}
|
jlahoda@0
|
751 |
}
|
jlahoda@0
|
752 |
}
|
jlahoda@0
|
753 |
}
|
jlahoda@0
|
754 |
}
|
jlahoda@0
|
755 |
}
|
jlahoda@297
|
756 |
}
|
jlahoda@0
|
757 |
|
jlahoda@297
|
758 |
suppresWarnings.push(nju);
|
jlahoda@297
|
759 |
return true;
|
jlahoda@0
|
760 |
}
|
jlahoda@297
|
761 |
return false;
|
jlahoda@0
|
762 |
}
|
jlahoda@0
|
763 |
|
jlahoda@0
|
764 |
private Trees getTrees() {
|
jlahoda@0
|
765 |
return info != null ? info.getTrees() : Trees.instance(env);
|
jlahoda@0
|
766 |
}
|
jlahoda@0
|
767 |
}
|
jlahoda@0
|
768 |
|
jlahoda@0
|
769 |
static boolean isInGuarded(CompilationInfo info, TreePath tree) {
|
jlahoda@0
|
770 |
if (info == null) {
|
jlahoda@0
|
771 |
return false;
|
jlahoda@0
|
772 |
}
|
jlahoda@297
|
773 |
|
jlahoda@0
|
774 |
try {
|
jlahoda@0
|
775 |
Document doc = info.getDocument();
|
jlahoda@0
|
776 |
|
jlahoda@0
|
777 |
if (doc instanceof GuardedDocument) {
|
jlahoda@0
|
778 |
int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), tree.getLeaf());
|
jlahoda@0
|
779 |
int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), tree.getLeaf());
|
jlahoda@0
|
780 |
GuardedDocument gdoc = (GuardedDocument) doc;
|
jlahoda@0
|
781 |
MarkBlockChain guardedBlockChain = gdoc.getGuardedBlockChain();
|
jlahoda@0
|
782 |
if (guardedBlockChain.compareBlock(start, end) == MarkBlock.INNER) {
|
jlahoda@0
|
783 |
return true;
|
jlahoda@0
|
784 |
}
|
jlahoda@0
|
785 |
}
|
jlahoda@0
|
786 |
} catch (IOException ex) {
|
jlahoda@0
|
787 |
Exceptions.printStackTrace(ex);
|
jlahoda@0
|
788 |
}
|
jlahoda@0
|
789 |
|
jlahoda@0
|
790 |
return false;
|
jlahoda@0
|
791 |
}
|
jlahoda@0
|
792 |
|
jlahoda@297
|
793 |
private Collection<? extends ErrorDescription> runHint(HintDescription hd, HintContext ctx) {
|
jlahoda@297
|
794 |
long start = System.nanoTime();
|
jlahoda@0
|
795 |
|
jlahoda@297
|
796 |
try {
|
jlahoda@297
|
797 |
return hd.getWorker().createErrors(ctx);
|
jlahoda@297
|
798 |
} finally {
|
jlahoda@297
|
799 |
long end = System.nanoTime();
|
jlahoda@297
|
800 |
reportSpentTime(hd.getMetadata().id, end - start);
|
jlahoda@297
|
801 |
}
|
jlahoda@297
|
802 |
}
|
jlahoda@297
|
803 |
|
jlahoda@330
|
804 |
public static <K, V> Map<K, List<V>> merge(Map<K, List<V>> to, K key, V value) {
|
jlahoda@330
|
805 |
List<V> toColl = to.get(key);
|
jlahoda@330
|
806 |
|
jlahoda@330
|
807 |
if (toColl == null) {
|
jlahoda@330
|
808 |
to.put(key, toColl = new LinkedList<V>());
|
jlahoda@330
|
809 |
}
|
jlahoda@330
|
810 |
|
jlahoda@330
|
811 |
toColl.add(value);
|
jlahoda@330
|
812 |
|
jlahoda@330
|
813 |
return to;
|
jlahoda@330
|
814 |
}
|
jlahoda@330
|
815 |
|
jlahoda@330
|
816 |
public static <K, V> Map<K, List<V>> merge(Map<K, List<V>> to, K key, Collection<? extends V> value) {
|
jlahoda@330
|
817 |
List<V> toColl = to.get(key);
|
jlahoda@330
|
818 |
|
jlahoda@330
|
819 |
if (toColl == null) {
|
jlahoda@330
|
820 |
to.put(key, toColl = new LinkedList<V>());
|
jlahoda@330
|
821 |
}
|
jlahoda@330
|
822 |
|
jlahoda@330
|
823 |
toColl.addAll(value);
|
jlahoda@330
|
824 |
|
jlahoda@330
|
825 |
return to;
|
jlahoda@330
|
826 |
}
|
jlahoda@330
|
827 |
|
jlahoda@330
|
828 |
public static <K, V> Map<K, List<V>> mergeAll(Map<K, List<V>> to, Map<? extends K, ? extends Collection<? extends V>> what) {
|
jlahoda@330
|
829 |
for (Entry<? extends K, ? extends Collection<? extends V>> e : what.entrySet()) {
|
jlahoda@330
|
830 |
List<V> toColl = to.get(e.getKey());
|
jlahoda@330
|
831 |
|
jlahoda@330
|
832 |
if (toColl == null) {
|
jlahoda@330
|
833 |
to.put(e.getKey(), toColl = new LinkedList<V>());
|
jlahoda@330
|
834 |
}
|
jlahoda@330
|
835 |
|
jlahoda@330
|
836 |
toColl.addAll(e.getValue());
|
jlahoda@330
|
837 |
}
|
jlahoda@330
|
838 |
|
jlahoda@330
|
839 |
return to;
|
jlahoda@330
|
840 |
}
|
jlahoda@330
|
841 |
|
jlahoda@330
|
842 |
public static List<ErrorDescription> join(Map<?, ? extends List<? extends ErrorDescription>> errors) {
|
jlahoda@330
|
843 |
List<ErrorDescription> result = new LinkedList<ErrorDescription>();
|
jlahoda@330
|
844 |
|
jlahoda@330
|
845 |
for (Entry<?, ? extends Collection<? extends ErrorDescription>> e : errors.entrySet()) {
|
jlahoda@330
|
846 |
result.addAll(e.getValue());
|
jlahoda@330
|
847 |
}
|
jlahoda@330
|
848 |
|
jlahoda@330
|
849 |
return result;
|
jlahoda@330
|
850 |
}
|
jlahoda@330
|
851 |
|
jlahoda@297
|
852 |
private static final boolean logTimeSpentInHints = Boolean.getBoolean("java.HintsInvoker.time.in.hints");
|
jlahoda@297
|
853 |
private final Map<String, Long> hint2SpentTime = new HashMap<String, Long>();
|
jlahoda@297
|
854 |
|
jlahoda@297
|
855 |
private void reportSpentTime(String id, long nanoTime) {
|
jlahoda@297
|
856 |
if (!logTimeSpentInHints) return;
|
jlahoda@297
|
857 |
|
jlahoda@297
|
858 |
Long prev = hint2SpentTime.get(id);
|
jlahoda@297
|
859 |
|
jlahoda@297
|
860 |
if (prev == null) {
|
jlahoda@297
|
861 |
prev = (long) 0;
|
jlahoda@0
|
862 |
}
|
jlahoda@0
|
863 |
|
jlahoda@297
|
864 |
hint2SpentTime.put(id, prev + nanoTime);
|
jlahoda@297
|
865 |
}
|
jlahoda@297
|
866 |
|
jlahoda@297
|
867 |
private void dumpTimeSpentInHints() {
|
jlahoda@297
|
868 |
if (!logTimeSpentInHints) return;
|
jlahoda@297
|
869 |
|
jlahoda@297
|
870 |
List<Entry<String, Long>> l = new ArrayList<Entry<String, Long>>(hint2SpentTime.entrySet());
|
jlahoda@297
|
871 |
|
jlahoda@297
|
872 |
Collections.sort(l, new Comparator<Entry<String, Long>>() {
|
jlahoda@297
|
873 |
@Override
|
jlahoda@297
|
874 |
public int compare(Entry<String, Long> o1, Entry<String, Long> o2) {
|
jlahoda@297
|
875 |
return (int) Math.signum(o1.getValue() - o2.getValue());
|
jlahoda@297
|
876 |
}
|
jlahoda@297
|
877 |
});
|
jlahoda@297
|
878 |
|
jlahoda@297
|
879 |
for (Entry<String, Long> e : l) {
|
jlahoda@297
|
880 |
System.err.println(e.getKey() + "=" + String.format("%3.2f", e.getValue() / 1000000.0));
|
jlahoda@0
|
881 |
}
|
jlahoda@0
|
882 |
}
|
jlahoda@522
|
883 |
|
jlahoda@522
|
884 |
|
jlahoda@553
|
885 |
private void enterSpeculativeAssignments(HintContext ctx, List<Condition> conditions, Map<Tree, Map<String, Object>> marks) {
|
jlahoda@553
|
886 |
for (Condition c : conditions) {
|
jlahoda@553
|
887 |
if (!(c instanceof MarkCondition)) continue;
|
jlahoda@553
|
888 |
|
jlahoda@553
|
889 |
MarkCondition mc = (MarkCondition) c;
|
jlahoda@553
|
890 |
|
jlahoda@522
|
891 |
if (mc.op != Operator.ASSIGN) {
|
jlahoda@522
|
892 |
continue;
|
jlahoda@522
|
893 |
}
|
jlahoda@522
|
894 |
|
jlahoda@522
|
895 |
assert mc.left instanceof Selector;
|
jlahoda@522
|
896 |
|
jlahoda@522
|
897 |
Selector s = (Selector) mc.left;
|
jlahoda@522
|
898 |
String treeName = s.selected.get(0);
|
jlahoda@522
|
899 |
String markName = s.selected.get(1);
|
jlahoda@522
|
900 |
TreePath tree = ctx.getVariables().get(treeName);
|
jlahoda@522
|
901 |
|
jlahoda@522
|
902 |
assert tree != null;
|
jlahoda@522
|
903 |
|
jlahoda@522
|
904 |
System.err.println("speculative assignment to: " + tree.getLeaf());
|
jlahoda@522
|
905 |
|
jlahoda@522
|
906 |
Map<String, Object> variables = marks.get(tree.getLeaf());
|
jlahoda@522
|
907 |
|
jlahoda@522
|
908 |
if (variables == null) {
|
jlahoda@522
|
909 |
marks.put(tree.getLeaf(), variables = new HashMap<String, Object>());
|
jlahoda@522
|
910 |
}
|
jlahoda@522
|
911 |
|
jlahoda@522
|
912 |
PossibleValue pv = (PossibleValue) variables.get(markName);
|
jlahoda@522
|
913 |
|
jlahoda@522
|
914 |
if (pv == null) {
|
jlahoda@522
|
915 |
variables.put(markName, pv = new PossibleValue());
|
jlahoda@522
|
916 |
}
|
jlahoda@522
|
917 |
|
jlahoda@522
|
918 |
pv.add(mc);
|
jlahoda@522
|
919 |
}
|
jlahoda@522
|
920 |
}
|
jlahoda@522
|
921 |
|
jlahoda@553
|
922 |
private void clearSpeculativeAssignments(HintContext ctx, List<Condition> conditions, Map<Tree, Map<String, Object>> marks) {
|
jlahoda@553
|
923 |
for (Condition c : conditions) {
|
jlahoda@553
|
924 |
if (!(c instanceof MarkCondition)) continue;
|
jlahoda@553
|
925 |
|
jlahoda@553
|
926 |
MarkCondition mc = (MarkCondition) c;
|
jlahoda@553
|
927 |
|
jlahoda@522
|
928 |
if (mc.op != Operator.ASSIGN) {
|
jlahoda@522
|
929 |
continue;
|
jlahoda@522
|
930 |
}
|
jlahoda@522
|
931 |
|
jlahoda@522
|
932 |
assert mc.left instanceof Selector;
|
jlahoda@522
|
933 |
|
jlahoda@522
|
934 |
Selector s = (Selector) mc.left;
|
jlahoda@522
|
935 |
String treeName = s.selected.get(0);
|
jlahoda@522
|
936 |
String markName = s.selected.get(1);
|
jlahoda@522
|
937 |
TreePath tree = ctx.getVariables().get(treeName);
|
jlahoda@522
|
938 |
|
jlahoda@522
|
939 |
assert tree != null;
|
jlahoda@522
|
940 |
|
jlahoda@522
|
941 |
System.err.println("clearing speculative assignment from: " + tree.getLeaf());
|
jlahoda@522
|
942 |
|
jlahoda@522
|
943 |
Map<String, Object> variables = marks.get(tree.getLeaf());
|
jlahoda@522
|
944 |
|
jlahoda@522
|
945 |
assert variables != null;
|
jlahoda@522
|
946 |
|
jlahoda@522
|
947 |
Object value = variables.get(markName);
|
jlahoda@522
|
948 |
|
jlahoda@522
|
949 |
if (!(value instanceof PossibleValue))
|
jlahoda@522
|
950 |
continue;//XXX: correct?
|
jlahoda@522
|
951 |
|
jlahoda@522
|
952 |
PossibleValue pv = (PossibleValue) value;
|
jlahoda@522
|
953 |
|
jlahoda@522
|
954 |
assert pv != null;
|
jlahoda@522
|
955 |
|
jlahoda@522
|
956 |
pv.remove(mc);
|
jlahoda@522
|
957 |
|
jlahoda@522
|
958 |
if (pv.isEmpty()) {
|
jlahoda@522
|
959 |
variables.remove(markName);
|
jlahoda@522
|
960 |
}
|
jlahoda@522
|
961 |
}
|
jlahoda@522
|
962 |
}
|
jlahoda@522
|
963 |
|
jlahoda@522
|
964 |
/**true==accepted
|
jlahoda@522
|
965 |
* false==rejected
|
jlahoda@522
|
966 |
* null==nothing
|
jlahoda@522
|
967 |
*
|
jlahoda@522
|
968 |
* @return
|
jlahoda@522
|
969 |
*/
|
jlahoda@553
|
970 |
private static Boolean processConditions(HintContext ctx, Map<Tree, Map<String, Object>> marks, List<Condition> cond, int candidatesCount, int confirmedCount) {
|
jlahoda@522
|
971 |
if (cond.isEmpty()) {
|
jlahoda@522
|
972 |
return true; //implicitly accept
|
jlahoda@522
|
973 |
}
|
jlahoda@522
|
974 |
|
jlahoda@553
|
975 |
for (Iterator<Condition> it = cond.iterator(); it.hasNext(); ) {
|
jlahoda@553
|
976 |
Condition c = it.next();
|
jlahoda@522
|
977 |
|
jlahoda@553
|
978 |
if (c instanceof CustomCondition) {
|
jlahoda@553
|
979 |
if (!((CustomCondition) c).holds(ctx)) {
|
jlahoda@553
|
980 |
return false;
|
jlahoda@553
|
981 |
}
|
jlahoda@553
|
982 |
it.remove();
|
jlahoda@553
|
983 |
continue;
|
jlahoda@553
|
984 |
}
|
jlahoda@553
|
985 |
|
jlahoda@553
|
986 |
if (c instanceof OtherwiseCondition) {
|
jlahoda@553
|
987 |
if (candidatesCount > 1) return null;
|
jlahoda@553
|
988 |
if (confirmedCount > 0) return false;
|
jlahoda@553
|
989 |
it.remove();
|
jlahoda@553
|
990 |
continue;
|
jlahoda@553
|
991 |
}
|
jlahoda@553
|
992 |
|
jlahoda@553
|
993 |
MarkCondition mc = (MarkCondition) c;
|
jlahoda@553
|
994 |
|
jlahoda@553
|
995 |
switch (mc.op) {
|
jlahoda@522
|
996 |
case ASSIGN:
|
jlahoda@553
|
997 |
assert mc.left instanceof Selector;
|
jlahoda@522
|
998 |
|
jlahoda@553
|
999 |
Object value = readValue(ctx, marks, mc.right);
|
jlahoda@522
|
1000 |
|
jlahoda@522
|
1001 |
assert value != null;
|
jlahoda@522
|
1002 |
|
jlahoda@553
|
1003 |
Selector s = (Selector) mc.left;
|
jlahoda@522
|
1004 |
String treeName = s.selected.get(0);
|
jlahoda@522
|
1005 |
String markName = s.selected.get(1);
|
jlahoda@522
|
1006 |
TreePath tree = ctx.getVariables().get(treeName);
|
jlahoda@522
|
1007 |
|
jlahoda@522
|
1008 |
assert tree != null; //more gracefull handling, in some case may warn during parsing
|
jlahoda@522
|
1009 |
|
jlahoda@522
|
1010 |
Map<String, Object> variables = marks.get(tree.getLeaf());
|
jlahoda@522
|
1011 |
|
jlahoda@522
|
1012 |
if (variables == null) {
|
jlahoda@522
|
1013 |
marks.put(tree.getLeaf(), variables = new HashMap<String, Object>());
|
jlahoda@522
|
1014 |
}
|
jlahoda@522
|
1015 |
|
jlahoda@522
|
1016 |
variables.put(markName, value);
|
jlahoda@522
|
1017 |
break;
|
jlahoda@522
|
1018 |
case EQUALS: {
|
jlahoda@553
|
1019 |
Object left = readValue(ctx, marks, mc.left);
|
jlahoda@553
|
1020 |
Object right = readValue(ctx, marks, mc.right);
|
jlahoda@522
|
1021 |
|
jlahoda@522
|
1022 |
System.err.println("left=" + left);
|
jlahoda@522
|
1023 |
System.err.println("right=" + right);
|
jlahoda@522
|
1024 |
|
jlahoda@522
|
1025 |
if (left == null || right == null) {
|
jlahoda@522
|
1026 |
// System.err.println("marks=" + marks);
|
jlahoda@522
|
1027 |
// System.err.println("left=" + left);
|
jlahoda@522
|
1028 |
// System.err.println("right=" + right);
|
jlahoda@522
|
1029 |
//can never be true:
|
jlahoda@522
|
1030 |
return false;
|
jlahoda@522
|
1031 |
}
|
jlahoda@522
|
1032 |
|
jlahoda@522
|
1033 |
if (left instanceof PossibleValue || right instanceof PossibleValue) {
|
jlahoda@522
|
1034 |
//nothing to set yet.
|
jlahoda@522
|
1035 |
return null;
|
jlahoda@522
|
1036 |
}
|
jlahoda@522
|
1037 |
|
jlahoda@522
|
1038 |
if (!left.equals(right)) {
|
jlahoda@522
|
1039 |
return false;
|
jlahoda@522
|
1040 |
}
|
jlahoda@522
|
1041 |
|
jlahoda@522
|
1042 |
break;
|
jlahoda@522
|
1043 |
}
|
jlahoda@522
|
1044 |
case NOT_EQUALS: {
|
jlahoda@553
|
1045 |
Object left = readValue(ctx, marks, mc.left);
|
jlahoda@553
|
1046 |
Object right = readValue(ctx, marks, mc.right);
|
jlahoda@522
|
1047 |
|
jlahoda@522
|
1048 |
if (left instanceof PossibleValue || right instanceof PossibleValue) {
|
jlahoda@522
|
1049 |
//nothing to set yet.
|
jlahoda@522
|
1050 |
return null;
|
jlahoda@522
|
1051 |
}
|
jlahoda@522
|
1052 |
|
jlahoda@522
|
1053 |
if (left == right || (left != null && left.equals(right))) {
|
jlahoda@522
|
1054 |
return false;
|
jlahoda@522
|
1055 |
}
|
jlahoda@522
|
1056 |
|
jlahoda@522
|
1057 |
break;
|
jlahoda@522
|
1058 |
}
|
jlahoda@522
|
1059 |
default:
|
jlahoda@522
|
1060 |
throw new UnsupportedOperationException();
|
jlahoda@522
|
1061 |
}
|
jlahoda@522
|
1062 |
|
jlahoda@522
|
1063 |
it.remove();
|
jlahoda@522
|
1064 |
}
|
jlahoda@522
|
1065 |
|
jlahoda@522
|
1066 |
assert cond.isEmpty();
|
jlahoda@522
|
1067 |
|
jlahoda@522
|
1068 |
return true;
|
jlahoda@522
|
1069 |
}
|
jlahoda@522
|
1070 |
|
jlahoda@522
|
1071 |
private static Object readValue(HintContext ctx, Map<Tree, Map<String, Object>> marks, Value v) {
|
jlahoda@522
|
1072 |
if (v instanceof Selector) {
|
jlahoda@522
|
1073 |
Selector s = (Selector) v;
|
jlahoda@522
|
1074 |
|
jlahoda@522
|
1075 |
if (s.selected.size() == 1) {
|
jlahoda@522
|
1076 |
String name = s.selected.get(0);
|
jlahoda@522
|
1077 |
TreePath tree = ctx.getVariables().get(name);
|
jlahoda@522
|
1078 |
|
jlahoda@522
|
1079 |
assert tree != null;
|
jlahoda@522
|
1080 |
|
jlahoda@522
|
1081 |
return ctx.getInfo().getTrees().getElement(tree);
|
jlahoda@522
|
1082 |
}
|
jlahoda@522
|
1083 |
|
jlahoda@522
|
1084 |
if (s.selected.size() == 2) {
|
jlahoda@522
|
1085 |
String treeName = s.selected.get(0);
|
jlahoda@522
|
1086 |
String markName = s.selected.get(1);
|
jlahoda@522
|
1087 |
TreePath tree = ctx.getVariables().get(treeName);
|
jlahoda@522
|
1088 |
|
jlahoda@522
|
1089 |
assert tree != null; //more gracefull handling, in some case may warn during parsing
|
jlahoda@522
|
1090 |
|
jlahoda@522
|
1091 |
System.err.println("reading=" + tree.getLeaf() + "." + markName);
|
jlahoda@522
|
1092 |
|
jlahoda@522
|
1093 |
Map<String, Object> variables = marks.get(tree.getLeaf());
|
jlahoda@522
|
1094 |
|
jlahoda@522
|
1095 |
if (variables == null) return null;
|
jlahoda@522
|
1096 |
|
jlahoda@522
|
1097 |
return variables.get(markName);
|
jlahoda@522
|
1098 |
}
|
jlahoda@522
|
1099 |
|
jlahoda@522
|
1100 |
assert false;
|
jlahoda@522
|
1101 |
}
|
jlahoda@522
|
1102 |
|
jlahoda@522
|
1103 |
//XXX: not tested!
|
jlahoda@522
|
1104 |
if (v instanceof Literal) {
|
jlahoda@522
|
1105 |
return ((Literal) v).value;
|
jlahoda@522
|
1106 |
}
|
jlahoda@522
|
1107 |
|
jlahoda@522
|
1108 |
assert false;
|
jlahoda@522
|
1109 |
|
jlahoda@522
|
1110 |
return null;
|
jlahoda@522
|
1111 |
}
|
jlahoda@522
|
1112 |
|
jlahoda@522
|
1113 |
private static final class PossibleValue extends HashSet<MarkCondition> {}
|
jlahoda@522
|
1114 |
|
jlahoda@522
|
1115 |
private static final class HintEvaluationData {
|
jlahoda@522
|
1116 |
public final HintContext ctx;
|
jlahoda@522
|
1117 |
public final HintDescription hd;
|
jlahoda@553
|
1118 |
public final List<Condition> marks;
|
jlahoda@554
|
1119 |
public final ErrorDescriptionAcceptor acceptor;
|
jlahoda@522
|
1120 |
public final List<FixEvaluationData> fixDescriptions;
|
jlahoda@522
|
1121 |
public final List<Fix> createdFixes = new LinkedList<Fix>();
|
jlahoda@554
|
1122 |
public HintEvaluationData(HintContext ctx, HintDescription hd, List<Condition> marks, ErrorDescriptionAcceptor acceptor, List<FixEvaluationData> fixDescriptions) {
|
jlahoda@522
|
1123 |
this.ctx = ctx;
|
jlahoda@522
|
1124 |
this.hd = hd;
|
jlahoda@522
|
1125 |
this.marks = marks;
|
jlahoda@522
|
1126 |
this.acceptor = acceptor;
|
jlahoda@522
|
1127 |
this.fixDescriptions = fixDescriptions;
|
jlahoda@522
|
1128 |
}
|
jlahoda@522
|
1129 |
}
|
jlahoda@522
|
1130 |
|
jlahoda@522
|
1131 |
private static final class FixEvaluationData {
|
jlahoda@527
|
1132 |
public final HintContext ctx;
|
jlahoda@553
|
1133 |
public final List<Condition> marks;
|
jlahoda@554
|
1134 |
public final FixAcceptor acceptor;
|
jlahoda@554
|
1135 |
public FixEvaluationData(HintContext ctx, List<Condition> marks, FixAcceptor acceptor) {
|
jlahoda@527
|
1136 |
this.ctx = ctx;
|
jlahoda@522
|
1137 |
this.marks = marks;
|
jlahoda@522
|
1138 |
this.acceptor = acceptor;
|
jlahoda@522
|
1139 |
}
|
jlahoda@522
|
1140 |
}
|
jlahoda@522
|
1141 |
|
jlahoda@0
|
1142 |
}
|