1 19 20 package edu.umd.cs.findbugs.gui2; 21 22 import java.awt.Color ; 23 import java.io.FileReader ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import java.util.LinkedList ; 29 import java.util.Map ; 30 31 import javax.swing.JTextPane ; 32 import javax.swing.text.DefaultStyledDocument ; 33 import javax.swing.text.Document ; 34 import javax.swing.text.Element ; 35 import javax.swing.text.StyledDocument ; 36 import javax.swing.text.BadLocationException ; 37 38 import edu.umd.cs.findbugs.BugAnnotation; 39 import edu.umd.cs.findbugs.BugInstance; 40 import edu.umd.cs.findbugs.SourceLineAnnotation; 41 import edu.umd.cs.findbugs.annotations.CheckForNull; 42 import edu.umd.cs.findbugs.annotations.NonNull; 43 import edu.umd.cs.findbugs.ba.SourceFile; 44 import edu.umd.cs.findbugs.sourceViewer.JavaSourceDocument; 45 46 public final class SourceCodeDisplay implements Runnable { 47 final MainFrame frame; 48 49 private static final Color MAIN_HIGHLIGHT = new Color (1f, 1f, 0.5f); 50 private static final Color MAIN_HIGHLIGHT_MORE = MAIN_HIGHLIGHT.brighter(); 51 private static final Color ALTERNATIVE_HIGHLIGHT = new Color (0.86f, 0.90f, 1.0f); 52 private static final Color FOUND_HIGHLIGHT = new Color (0.75f, 0.75f, 1f); 53 54 static final Document SOURCE_NOT_RELEVANT = new DefaultStyledDocument ();; 55 56 public JavaSourceDocument myDocument; 57 private int currentChar = -1; 59 private final Map <String , JavaSourceDocument> map = new HashMap <String , JavaSourceDocument>(); 60 61 SourceCodeDisplay(MainFrame frame) { 62 this.frame = frame; 63 Thread t = new Thread (this, "Source code display thread"); 64 t.setDaemon(true); 65 t.start(); 66 } 67 68 private boolean pendingUpdate; 69 70 @CheckForNull private BugInstance bugToDisplay; 71 72 private SourceLineAnnotation sourceToHighlight; 73 74 public synchronized void displaySource(BugInstance bug, 75 SourceLineAnnotation source) { 76 bugToDisplay = bug; 77 sourceToHighlight = source; 78 pendingUpdate = true; 79 notifyAll(); 80 } 81 82 public void clearCache() { 83 map.clear(); 84 } 85 86 @NonNull 87 private JavaSourceDocument getDocument(SourceLineAnnotation source) { 88 try { 89 SourceFile sourceFile = frame.sourceFinder.findSourceFile(source); 90 String fullFileName = sourceFile.getFullFileName(); 91 JavaSourceDocument result = map.get(fullFileName); 92 if (result != null) 93 return result; 94 try { 95 InputStream in = sourceFile.getInputStream(); 96 result = new JavaSourceDocument(source.getClassName(), 97 new InputStreamReader (in), sourceFile); 98 } catch (Exception e) { 99 result = JavaSourceDocument.UNKNOWNSOURCE; 100 Debug.println(e); } 102 map.put(fullFileName, result); 103 return result; 104 } catch (Exception e) { 105 Debug.println(e); return JavaSourceDocument.UNKNOWNSOURCE; 107 108 } 109 } 110 111 public void run() { 112 while (true) { 113 BugInstance myBug; 114 SourceLineAnnotation mySourceLine; 115 synchronized (this) { 116 while (!pendingUpdate) { 117 try { 118 wait(); 119 } catch (InterruptedException e) { 120 } 122 } 123 myBug = bugToDisplay; 124 mySourceLine = sourceToHighlight; 125 bugToDisplay = null; 126 sourceToHighlight = null; 127 pendingUpdate = false; 128 } 129 if (myBug == null) { 130 frame.clearSourcePane(); 131 continue; 132 } 133 134 try { 135 final JavaSourceDocument src = getDocument(mySourceLine); 136 this.myDocument = src; 137 src.getHighlightInformation().clear(); 138 String primaryKind = mySourceLine.getDescription(); 139 for(Iterator <BugAnnotation> i = myBug.annotationIterator(); i.hasNext(); ) { 141 BugAnnotation annotation = i.next(); 142 if (annotation instanceof SourceLineAnnotation) { 143 SourceLineAnnotation sourceAnnotation = (SourceLineAnnotation) annotation; 144 if (sourceAnnotation == mySourceLine) continue; 145 if (sourceAnnotation.getDescription().equals(primaryKind)) 146 highlight(src, sourceAnnotation, MAIN_HIGHLIGHT_MORE); 147 else 148 highlight(src, sourceAnnotation, ALTERNATIVE_HIGHLIGHT); 149 } 150 } 151 highlight(src, mySourceLine, MAIN_HIGHLIGHT); 152 final BugInstance thisBug = myBug; 153 final SourceLineAnnotation thisSource = mySourceLine; 154 javax.swing.SwingUtilities.invokeLater(new Runnable () { 155 public void run() { 156 frame.sourceCodeTextPane.setEditorKit(src.getEditorKit()); 157 StyledDocument document = src.getDocument(); 158 frame.sourceCodeTextPane.setDocument(document); 159 frame.setSourceTabTitle(thisSource.getSourceFile() + " in " + thisSource.getPackageName()); 160 int startLine = thisSource.getStartLine(); 161 int endLine = thisSource.getEndLine(); 162 int originLine = (startLine + endLine) / 2; 163 LinkedList <Integer > otherLines = new LinkedList <Integer >(); 164 for(Iterator <BugAnnotation> i = thisBug.annotationIterator(); i.hasNext(); ) { 166 BugAnnotation annotation = i.next(); 167 if (annotation instanceof SourceLineAnnotation) { 168 SourceLineAnnotation sourceAnnotation = (SourceLineAnnotation) annotation; 169 if (sourceAnnotation != thisSource) { 170 int otherLine = sourceAnnotation.getStartLine(); 172 if (otherLine > originLine) otherLine = sourceAnnotation.getEndLine(); 173 otherLines.add(otherLine); 174 } 175 } 176 } 177 if (startLine >= 0 && endLine >= 0) 179 frame.sourceCodeTextPane.scrollLinesToVisible(startLine, endLine, otherLines); 180 } 181 }); 182 } catch (Exception e) { 183 Debug.println(e); } 185 } 186 } 187 188 192 private void highlight(JavaSourceDocument src, SourceLineAnnotation sourceAnnotation, Color color) { 193 194 int startLine = sourceAnnotation.getStartLine(); 195 if (startLine == -1) return; 196 if (!sourceAnnotation.getClassName().equals(src.getTitle())) return; 197 src.getHighlightInformation().setHighlight(startLine, sourceAnnotation.getEndLine(), color); 198 } 199 200 public void foundItem(int lineNum) { 201 myDocument.getHighlightInformation().updateFoundLineNum(lineNum); 202 myDocument.getHighlightInformation().setHighlight(lineNum, FOUND_HIGHLIGHT); 203 frame.sourceCodeTextPane.scrollLineToVisible(lineNum); 204 frame.sourceCodeTextPane.updateUI(); 205 } 206 207 private int search(JavaSourceDocument document, String target, int start, Boolean backwards) 208 { 209 String docContent = null; 210 try{ 211 docContent = document.getDocument().getText(0, document.getDocument().getLength()); 212 } 213 catch(BadLocationException ble){System.out.println("Bad location exception");} 214 catch(NullPointerException npe){return -1;} 215 if(docContent == null) return -1; 216 int targetLen = target.length(); 217 int sourceLen = docContent.length(); 218 if(targetLen > sourceLen) 219 return -1; 220 else if(backwards) 221 { 222 for(int i=start; i>=0; i--) 223 if(docContent.substring(i, i+targetLen).equals(target)) 224 return i; 225 for(int i=(sourceLen-targetLen); i>start; i--) 226 if(docContent.substring(i, i+targetLen).equals(target)) 227 return i; 228 return -1; 229 } 230 else 231 { 232 for(int i=start; i<=(sourceLen-targetLen); i++) 233 if(docContent.substring(i, i+targetLen).equals(target)) 234 return i; 235 for(int i=0; i<start; i++) 236 if(docContent.substring(i, i+targetLen).equals(target)) 237 return i; 238 return -1; 239 } 240 } 241 242 private int charToLineNum(int charNum) 243 { 244 if(charNum==-1) return -1; 245 try 246 { 247 for(int i=1; true; i++){ 248 if(frame.sourceCodeTextPane.getLineOffset(i) > charNum) 249 return i-1; 250 else if(frame.sourceCodeTextPane.getLineOffset(i) == -1) 251 return -1; 252 } 253 } 254 catch(BadLocationException ble){return -1;} 255 } 256 257 public int find(String target) 258 { 259 int charFoundAt = search(myDocument, target, 0, false); 260 currentChar = charFoundAt; 261 return charToLineNum(currentChar); 264 } 265 266 public int findNext(String target) 267 { 268 int charFoundAt = search(myDocument, target, currentChar+1, false); 269 currentChar = charFoundAt; 270 return charToLineNum(currentChar); 273 } 274 275 public int findPrevious(String target) 276 { 277 int charFoundAt = search(myDocument, target, currentChar-1, true); 278 currentChar = charFoundAt; 279 return charToLineNum(currentChar); 282 } 283 284 private void show(JTextPane pane, Document src, SourceLineAnnotation sourceAnnotation) { 285 286 int startLine = sourceAnnotation.getStartLine(); 287 if (startLine == -1) return; 288 frame.sourceCodeTextPane.scrollLineToVisible(startLine); 289 300 } 301 302 public void showLine(int line) { 303 frame.sourceCodeTextPane.scrollLineToVisible(line); 304 310 } 311 } 312 | Popular Tags |