KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > retouche > hints > GsfHintsProvider


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.retouche.hints;
21
22 import java.io.IOException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import javax.swing.text.Document JavaDoc;
30 import javax.swing.text.StyledDocument JavaDoc;
31 import org.netbeans.api.gsf.CancellableTask;
32 import org.netbeans.api.gsf.Error;
33 import org.netbeans.modules.retouche.hints.spi.ErrorRule;
34 import org.netbeans.modules.retouche.hints.spi.ErrorRule.Data;
35 import org.netbeans.spi.editor.hints.Fix;
36 import org.netbeans.spi.editor.hints.LazyFixList;
37 import org.netbeans.spi.editor.hints.Severity;
38 import org.openide.ErrorManager;
39 import org.openide.filesystems.FileObject;
40 import org.openide.filesystems.FileUtil;
41 import org.openide.loaders.DataObject;
42 import org.openide.text.Line;
43 import java.util.EnumMap JavaDoc;
44 import java.util.HashSet JavaDoc;
45 import java.util.Set JavaDoc;
46 import java.util.logging.Level JavaDoc;
47 import java.util.logging.Logger JavaDoc;
48 import javax.swing.text.BadLocationException JavaDoc;
49 import javax.swing.text.Position JavaDoc;
50 import javax.swing.text.Position.Bias;
51 import org.netbeans.api.retouche.source.CompilationInfo;
52 import org.netbeans.api.retouche.source.Source;
53 import org.netbeans.modules.retouche.hints.infrastructure.RulesManager;
54 import org.netbeans.spi.editor.hints.ErrorDescription;
55 import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
56 import org.netbeans.spi.editor.hints.HintsController;
57 import org.openide.cookies.EditorCookie;
58 import org.openide.cookies.LineCookie;
59 import org.openide.text.NbDocument;
60
61
62
63 /**
64  * This class is based on JavaHintsFactory in Retouche's org.netbeans.modules.java.hints
65  * This file is originally from Retouche, the Java Support
66  * infrastructure in NetBeans. I have modified the file as little
67  * as possible to make merging Retouche fixes back as simple as
68  * possible.
69  *
70  *
71  * @author Jan Lahoda
72  * @author leon chiver
73  * @author Tor Norbye
74  */

75 public final class GsfHintsProvider implements CancellableTask<CompilationInfo> {
76     
77     public static ErrorManager ERR = ErrorManager.getDefault().getInstance("org.netbeans.modules.retouche.hints"); // NOI18N
78
public static Logger JavaDoc LOG = Logger.getLogger("org.netbeans.modules.retouche.hints"); // NOI18N
79

80     private FileObject file;
81     
82     /**
83      * Creates a new instance of GsfHintsProvider
84      */

85     GsfHintsProvider(FileObject file) {
86         this.file = file;
87     }
88     
89     private static final Map JavaDoc<org.netbeans.api.gsf.Severity, Severity> errorKind2Severity;
90     
91     static {
92         errorKind2Severity = new EnumMap JavaDoc<org.netbeans.api.gsf.Severity, Severity>(org.netbeans.api.gsf.Severity.class);
93         errorKind2Severity.put(org.netbeans.api.gsf.Severity.ERROR, Severity.ERROR);
94         errorKind2Severity.put(org.netbeans.api.gsf.Severity.WARNING, Severity.WARNING);
95 // errorKind2Severity.put(Error/*Diagnostic*/.Kind.WARNING, Severity.WARNING);
96
// errorKind2Severity.put(Error/*Diagnostic*/.Kind.NOTE, Severity.WARNING);
97
// errorKind2Severity.put(Error/*Diagnostic*/.Kind.OTHER, Severity.WARNING);
98
}
99     
100     List JavaDoc<ErrorDescription> computeErrors(CompilationInfo info, Document JavaDoc doc) {
101         Source js = Source.forFileObject(file);
102         List JavaDoc<Error JavaDoc/*Diagnostic*/> errors = info.getDiagnostics();
103         List JavaDoc<ErrorDescription> descs = new ArrayList JavaDoc<ErrorDescription>();
104         
105         if (ERR.isLoggable(ErrorManager.INFORMATIONAL))
106             ERR.log(ErrorManager.INFORMATIONAL, "errors = " + errors );
107         
108         Map JavaDoc<Class JavaDoc, Data> data = new HashMap JavaDoc<Class JavaDoc, Data>();
109         
110         for (Error JavaDoc/*Diagnostic*/ d : errors) {
111             if (isCanceled())
112                 return null;
113             
114             if (ERR.isLoggable(ErrorManager.INFORMATIONAL))
115                 ERR.log(ErrorManager.INFORMATIONAL, "d = " + d );
116             
117             Map JavaDoc<String JavaDoc, List JavaDoc<ErrorRule>> code2Rules = RulesManager.getInstance().getErrors();
118             
119             List JavaDoc<ErrorRule> rules = code2Rules.get(d.getKey());
120             
121             if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
122                 ERR.log(ErrorManager.INFORMATIONAL, "code= " + d.getKey());
123                 ERR.log(ErrorManager.INFORMATIONAL, "rules = " + rules);
124             }
125             
126             //int position = (int)d.getPosition();
127
int position = d.getStartPosition().getOffset();
128             int endPosition = d.getEndPosition().getOffset();
129             LazyFixList ehm;
130             
131             if (rules != null) {
132                 ehm = new CreatorBasedLazyFixList(info.getFileObject(), d.getKey(), (int)getPrefferedPosition(info, d), rules, data);
133             } else {
134                 ehm = ErrorDescriptionFactory.lazyListForFixes(Collections.<Fix>emptyList());
135             }
136             
137             if (ERR.isLoggable(ErrorManager.INFORMATIONAL))
138                 ERR.log(ErrorManager.INFORMATIONAL, "ehm=" + ehm);
139             
140             final String JavaDoc desc = d.getDisplayName();
141             final Position JavaDoc[] range = getLine(info, d, doc, position, endPosition);
142             
143             if (isCanceled())
144                 return null;
145             
146             if (range[0] == null || range[1] == null)
147                 continue;
148             
149             descs.add(ErrorDescriptionFactory.createErrorDescription(errorKind2Severity.get(d.getSeverity()), desc, ehm, doc, range[0], range[1]));
150         }
151         
152         if (isCanceled())
153             return null;
154         
155         LazyHintComputationFactory.getAndClearToCompute(file);
156         
157         return descs;
158     }
159     
160     public Document JavaDoc getDocument() {
161         try {
162             DataObject d = DataObject.find(file);
163             EditorCookie ec = (EditorCookie) d.getCookie(EditorCookie.class);
164             
165             if (ec == null)
166                 return null;
167             
168             return ec.getDocument();
169         } catch (IOException JavaDoc e) {
170             Logger.getLogger(GsfHintsProvider.class.getName()).log(Level.INFO, "GsfHintsProvider: Cannot find DataObject for file: " + FileUtil.getFileDisplayName(file), e);
171             return null;
172         }
173     }
174     
175 // static Token findUnresolvedElementToken(CompilationInfo info, int offset) {
176
// TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence();
177
//
178
// ts.move(offset);
179
// if (ts.moveNext()) {
180
// Token t = ts.token();
181
//
182
// if (t.id() == JavaTokenId.DOT) {
183
// ts.moveNext();
184
// t = ts.token();
185
// } else {
186
// if (t.id() == JavaTokenId.LT) {
187
// ts.moveNext();
188
// t = ts.token();
189
// }
190
// }
191
//
192
// if (t.id() == JavaTokenId.IDENTIFIER) {
193
// return ts.offsetToken();
194
// }
195
// }
196
// return null;
197
// }
198
//
199
// private static int[] findUnresolvedElementSpan(CompilationInfo info, int offset) {
200
// TokenHierarchy th = info.getTokenHierarchy();
201
//
202
// Token t = findUnresolvedElementToken(info, offset);
203
//
204
// if (t != null) {
205
// return new int[] {
206
// t.offset(th),
207
// t.offset(th) + t.length()
208
// };
209
// }
210
//
211
// return null;
212
// }
213
//
214
// static TreePath findUnresolvedElement(CompilationInfo info, int offset) {
215
// int[] span = findUnresolvedElementSpan(info, offset);
216
//
217
// if (span != null) {
218
// return info.getTreeUtilities().pathFor(span[0] + 1);
219
// } else {
220
// return null;
221
// }
222
// }
223

224     private static final Set JavaDoc<String JavaDoc> CANNOT_RESOLVE = Collections.emptySet();
225 // new HashSet<String>(Arrays.asList(
226
// "compiler.err.cant.resolve",
227
// "compiler.err.cant.resolve.location",
228
// "compiler.err.doesnt.exist"
229
// ));
230

231     private static final Set JavaDoc<String JavaDoc> UNDERLINE_IDENTIFIER = Collections.emptySet();
232 // new HashSet<String>(Arrays.asList(
233
// "compiler.err.local.var.accessed.from.icls.needs.final",
234
// "compiler.err.var.might.not.have.been.initialized"
235
// ));
236

237     private Position JavaDoc[] getLine(CompilationInfo info, Error JavaDoc d, final Document JavaDoc doc, int startOffset, int endOffset) {
238         StyledDocument JavaDoc sdoc = (StyledDocument JavaDoc) doc;
239         DataObject dObj = (DataObject)doc.getProperty(doc.StreamDescriptionProperty );
240         LineCookie lc = (LineCookie) dObj.getCookie(LineCookie.class);
241         int lineNumber = NbDocument.findLineNumber(sdoc, startOffset);
242         int lineOffset = NbDocument.findLineOffset(sdoc, lineNumber);
243         Line line = lc.getLineSet().getCurrent(lineNumber);
244         
245         boolean rangePrepared = false;
246         
247 // if (CANNOT_RESOLVE.contains(d.getCode())) {
248
// int[] span = findUnresolvedElementSpan(info, (int) getPrefferedPosition(info, d));
249
//
250
// if (span != null && span[0] != (-1) && span[1] != (-1)) {
251
// startOffset = span[0];
252
// endOffset = span[1];
253
// rangePrepared = true;
254
// }
255
// }
256
//
257
// if (UNDERLINE_IDENTIFIER.contains(d.getCode())) {
258
// TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence(JavaTokenId.language());
259
//
260
// int diff = ts.move((int) getPrefferedPosition(info, d));
261
//
262
// if (ts.moveNext() && diff >= 0 && diff < ts.token().length()) {
263
// Token<JavaTokenId> t = ts.token();
264
//
265
// if (t.id() == JavaTokenId.IDENTIFIER) {
266
// startOffset = ts.offset();
267
// endOffset = startOffset + t.length();
268
// rangePrepared = true;
269
// }
270
// }
271
// }
272

273         if (!rangePrepared) {
274             String JavaDoc text = line.getText();
275             
276             int column = 0;
277             int length = text.length();
278             
279             while (column < text.length() && Character.isWhitespace(text.charAt(column)))
280                 column++;
281             
282             while (length > 0 && Character.isWhitespace(text.charAt(length - 1)))
283                 length--;
284             
285             startOffset = lineOffset + column;
286             endOffset = lineOffset + length;
287         }
288         
289         if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
290             ERR.log(ErrorManager.INFORMATIONAL, "startOffset = " + startOffset );
291             ERR.log(ErrorManager.INFORMATIONAL, "endOffset = " + endOffset );
292         }
293         
294         final int startOffsetFinal = startOffset;
295         final int endOffsetFinal = endOffset;
296         final Position JavaDoc[] result = new Position JavaDoc[2];
297         
298         doc.render(new Runnable JavaDoc() {
299             public void run() {
300                 if (isCanceled())
301                     return;
302                 
303                 int len = doc.getLength();
304                 
305                 if (startOffsetFinal > len || endOffsetFinal > len) {
306                     if (!isCanceled() && ERR.isLoggable(ErrorManager.WARNING)) {
307                         ERR.log(ErrorManager.WARNING, "document changed, but not canceled?" );
308                         ERR.log(ErrorManager.WARNING, "len = " + len );
309                         ERR.log(ErrorManager.WARNING, "startOffset = " + startOffsetFinal );
310                         ERR.log(ErrorManager.WARNING, "endOffset = " + endOffsetFinal );
311                     }
312                     cancel();
313                     
314                     return;
315                 }
316                 
317                 try {
318                     result[0] = NbDocument.createPosition(doc, startOffsetFinal, Bias.Forward);
319                     result[1] = NbDocument.createPosition(doc, endOffsetFinal, Bias.Backward);
320                 } catch (BadLocationException JavaDoc e) {
321                     ERR.notify(ErrorManager.ERROR, e);
322                 }
323             }
324         });
325         
326         return result;
327     }
328     
329     private boolean cancel;
330     
331     synchronized boolean isCanceled() {
332         return cancel;
333     }
334     
335     public synchronized void cancel() {
336         cancel = true;
337     }
338     
339     synchronized void resume() {
340         cancel = false;
341     }
342     
343     public void run(CompilationInfo info) {
344         resume();
345         
346         Document JavaDoc doc = getDocument();
347         
348         if (doc == null) {
349             Logger.getLogger(GsfHintsProvider.class.getName()).log(Level.INFO, "SemanticHighlighter: Cannot get document!");
350             return ;
351         }
352         
353         long start = System.currentTimeMillis();
354         
355         List JavaDoc<ErrorDescription> errors = computeErrors(info, doc);
356         
357         if (errors == null) //meaning: cancelled
358
return ;
359         
360         HintsController.setErrors(doc, "java-hints", errors);
361         
362         long end = System.currentTimeMillis();
363         
364         //TimesCollector.getDefault().reportTime(info.getFileObject(), "com-hints", "Hints", end - start);
365
}
366     
367     // TODO this is a typo!! Fix original in java/hints/
368
private long getPrefferedPosition(CompilationInfo info, Error JavaDoc d) {
369 // if ("compiler.err.doesnt.exist".equals(d.getCode())) {
370
// return d.getStartPosition();
371
// }
372
// if ("compiler.err.not.stmt".equals(d.getCode())) {
373
// //check for "Collections.":
374
// TreePath path = findUnresolvedElement(info, (int) d.getStartPosition() - 1);
375
// Element el = path != null ? info.getTrees().getElement(path) : null;
376
//
377
// if (el == null || el.asType().getKind() == TypeKind.ERROR) {
378
// return d.getStartPosition() - 1;
379
// }
380
//
381
// if (el.asType().getKind() == TypeKind.PACKAGE) {
382
// //check if the package does actually exist:
383
// String s = ((PackageElement) el).getQualifiedName().toString();
384
// if (info.getElements().getPackageElement(s) == null) {
385
// //it does not:
386
// return d.getStartPosition() - 1;
387
// }
388
// }
389
//
390
// return d.getStartPosition();
391
// }
392

393         return d.getStartPosition().getOffset();
394     }
395 }
396
397
Popular Tags