1 19 20 package org.netbeans.modules.retouche.hints; 21 22 import java.io.IOException ; 23 import java.util.ArrayList ; 24 import java.util.Arrays ; 25 import java.util.Collections ; 26 import java.util.HashMap ; 27 import java.util.List ; 28 import java.util.Map ; 29 import javax.swing.text.Document ; 30 import javax.swing.text.StyledDocument ; 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 ; 44 import java.util.HashSet ; 45 import java.util.Set ; 46 import java.util.logging.Level ; 47 import java.util.logging.Logger ; 48 import javax.swing.text.BadLocationException ; 49 import javax.swing.text.Position ; 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 75 public final class GsfHintsProvider implements CancellableTask<CompilationInfo> { 76 77 public static ErrorManager ERR = ErrorManager.getDefault().getInstance("org.netbeans.modules.retouche.hints"); public static Logger LOG = Logger.getLogger("org.netbeans.modules.retouche.hints"); 80 private FileObject file; 81 82 85 GsfHintsProvider(FileObject file) { 86 this.file = file; 87 } 88 89 private static final Map <org.netbeans.api.gsf.Severity, Severity> errorKind2Severity; 90 91 static { 92 errorKind2Severity = new EnumMap <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 } 99 100 List <ErrorDescription> computeErrors(CompilationInfo info, Document doc) { 101 Source js = Source.forFileObject(file); 102 List <Error > errors = info.getDiagnostics(); 103 List <ErrorDescription> descs = new ArrayList <ErrorDescription>(); 104 105 if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) 106 ERR.log(ErrorManager.INFORMATIONAL, "errors = " + errors ); 107 108 Map <Class , Data> data = new HashMap <Class , Data>(); 109 110 for (Error 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 <String , List <ErrorRule>> code2Rules = RulesManager.getInstance().getErrors(); 118 119 List <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 = 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 desc = d.getDisplayName(); 141 final Position [] 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 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 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 224 private static final Set <String > CANNOT_RESOLVE = Collections.emptySet(); 225 231 private static final Set <String > UNDERLINE_IDENTIFIER = Collections.emptySet(); 232 237 private Position [] getLine(CompilationInfo info, Error d, final Document doc, int startOffset, int endOffset) { 238 StyledDocument sdoc = (StyledDocument ) 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 273 if (!rangePrepared) { 274 String 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 [] result = new Position [2]; 297 298 doc.render(new Runnable () { 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 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 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 <ErrorDescription> errors = computeErrors(info, doc); 356 357 if (errors == null) return ; 359 360 HintsController.setErrors(doc, "java-hints", errors); 361 362 long end = System.currentTimeMillis(); 363 364 } 366 367 private long getPrefferedPosition(CompilationInfo info, Error d) { 369 393 return d.getStartPosition().getOffset(); 394 } 395 } 396 397 | Popular Tags |