1 19 package org.netbeans.modules.java.editor.semantic; 20 21 import com.sun.source.tree.IdentifierTree; 22 import com.sun.source.tree.ClassTree; 23 import com.sun.source.tree.CompilationUnitTree; 24 import com.sun.source.tree.MemberSelectTree; 25 import com.sun.source.tree.MethodTree; 26 import com.sun.source.tree.Tree; 27 import com.sun.source.tree.Tree.Kind; 28 import com.sun.source.tree.VariableTree; 29 import com.sun.source.util.SourcePositions; 30 import com.sun.source.util.TreePath; 31 import java.awt.Color ; 32 import java.util.ArrayList ; 33 import java.util.Collection ; 34 import java.util.Collections ; 35 import java.util.HashMap ; 36 import java.util.logging.Level ; 37 import javax.swing.text.BadLocationException ; 38 import javax.swing.text.Document ; 39 import javax.swing.text.Position ; 40 import javax.swing.text.Position.Bias; 41 import java.util.HashSet ; 42 import java.util.List ; 43 import java.util.Map ; 44 import java.util.Set ; 45 import java.util.logging.Logger ; 46 import javax.lang.model.element.Element; 47 import javax.lang.model.element.ElementKind; 48 import javax.lang.model.element.Modifier; 49 import javax.lang.model.element.Name; 50 import org.netbeans.modules.editor.highlights.spi.Highlight; 51 import org.openide.text.NbDocument; 52 import org.openide.util.Exceptions; 53 54 58 public class Utilities { 59 60 private static final Logger LOG = Logger.getLogger(Utilities.class.getName()); 61 62 @Deprecated 63 private static final boolean DEBUG = false; 64 65 private static final int[] NO_SPAN = {-1, -1}; 66 67 68 public Utilities() { 69 } 70 71 private static int[] findIdentifierSpanImpl(Tree decl, Tree lastLeft, String name, CompilationUnitTree cu, SourcePositions positions, Document doc) { 72 return findIdentifierSpanImpl(decl, lastLeft, Collections.<Tree>emptyList(), name, cu, positions, doc); 73 } 74 75 private static int[] findIdentifierSpanImpl(Tree decl, Tree lastLeft, List <? extends Tree> firstRight, String name, CompilationUnitTree cu, SourcePositions positions, Document doc) { 76 int declStart = (int) positions.getStartPosition(cu, decl); 77 int start = lastLeft != null ? (int)positions.getEndPosition(cu, lastLeft) : declStart; 78 79 if (start == (-1)) { 80 start = declStart; 81 if (start == (-1)) { 82 return NO_SPAN; 83 } 84 } 85 86 try { 87 int end = (int)positions.getEndPosition(cu, decl); 88 89 for (Tree t : firstRight) { 90 if (t == null) 91 continue; 92 93 int proposedEnd = (int)positions.getStartPosition(cu, t); 94 95 if (proposedEnd != (-1) && proposedEnd < end) 96 end = proposedEnd; 97 } 98 99 if (end == (-1)) { 100 return NO_SPAN; 101 } 102 103 if (start > end) { 104 start = (int) positions.getStartPosition(cu, decl); 109 } 110 111 if (start > doc.getLength() || end > doc.getLength()) { 112 if (DEBUG) { 113 System.err.println("Log: position outside document: "); 114 System.err.println("lastLeft = " + lastLeft ); 115 System.err.println("decl = " + decl); 116 System.err.println("startOffset = " + start); 117 System.err.println("endOffset = " + end); 118 Thread.dumpStack(); 119 } 120 121 return NO_SPAN; 122 } 123 124 String text = doc.getText(start, end - start); 125 126 int index = text.lastIndexOf(name.toString()); 127 128 if (index != (-1)) { 129 return new int[] {start + index, start + index + name.length()}; 130 } 131 } catch (BadLocationException e) { 132 LOG.log(Level.INFO, null, e); 133 } 134 135 return NO_SPAN; 136 } 137 138 private static int[] findIdentifierSpanImpl(MemberSelectTree tree, CompilationUnitTree cu, SourcePositions positions, Document doc) { 139 int start = (int)positions.getStartPosition(cu, tree); 140 141 int endPosition = (int)positions.getEndPosition(cu, tree); 142 143 if (start == (-1) || endPosition == (-1)) 144 return NO_SPAN; 145 146 try { 147 String member = tree.getIdentifier().toString(); 148 int end = endPosition - start; 149 150 if (start > doc.getLength() || end > doc.getLength()) { 151 if (DEBUG) { 152 System.err.println("Log: position outside document: "); 153 System.err.println("tree = " + tree ); 154 System.err.println("member = " + member); 155 System.err.println("startOffset = " + start); 156 System.err.println("endOffset = " + end); 157 Thread.dumpStack(); 158 } 159 160 return NO_SPAN; 161 } 162 163 String text = doc.getText(start, end); 164 165 int index = text.lastIndexOf(member); 166 167 if (index != (-1)) { 168 return new int[] {start + index, start + index + member.length()}; 169 } 170 } catch (BadLocationException e) { 171 BadLocationException ex = Exceptions.attachMessage(e, "start=" + start + ", endPosition=" + endPosition); 172 LOG.log(Level.INFO, null, ex); 173 } 174 175 return NO_SPAN; 176 } 177 178 private static final Map <Class , List <Kind>> class2Kind; 179 180 static { 181 class2Kind = new HashMap <Class , List <Kind>>(); 182 183 for (Kind k : Kind.values()) { 184 Class c = k.asInterface(); 185 List <Kind> kinds = class2Kind.get(c); 186 187 if (kinds == null) { 188 class2Kind.put(c, kinds = new ArrayList <Kind>()); 189 } 190 191 kinds.add(k); 192 } 193 } 194 195 private static int[] findIdentifierSpanImpl(TreePath decl, CompilationUnitTree cu, SourcePositions positions, Document doc) { 196 if (doc == null) { 197 throw new NullPointerException (); 198 } 199 200 Tree leaf = decl.getLeaf(); 201 202 if (class2Kind.get(MethodTree.class).contains(leaf.getKind())) { 203 if (positions.getStartPosition(cu, leaf) == (-1) || positions.getEndPosition(cu, leaf) == (-1)) 204 return NO_SPAN; 206 MethodTree method = (MethodTree) leaf; 207 List <Tree> rightTrees = new ArrayList <Tree>(); 208 209 rightTrees.addAll(method.getParameters()); 210 rightTrees.addAll(method.getThrows()); 211 rightTrees.add(method.getBody()); 212 213 Name name = method.getName(); 214 215 if (method.getReturnType() == null) 216 name = ((ClassTree) decl.getParentPath().getLeaf()).getSimpleName(); 217 218 return findIdentifierSpanImpl(leaf, method.getReturnType(), rightTrees, name.toString(), cu, positions, doc); 219 } 220 if (class2Kind.get(VariableTree.class).contains(leaf.getKind())) { 221 VariableTree var = (VariableTree) leaf; 222 223 return findIdentifierSpanImpl(leaf, var.getType(), Collections.singletonList(var.getInitializer()), var.getName().toString(), cu, positions, doc); 224 } 225 if (class2Kind.get(MemberSelectTree.class).contains(leaf.getKind())) { 226 return findIdentifierSpanImpl((MemberSelectTree) leaf, cu, positions, doc); 227 } 228 if (class2Kind.get(ClassTree.class).contains(leaf.getKind())) { 229 int start = (int)positions.getStartPosition(cu, leaf); 231 int end = (int)positions.getEndPosition(cu, leaf); 232 233 if (start == (-1) || end == (-1)) { 234 return NO_SPAN; 235 } 236 237 if (start > doc.getLength() || end > doc.getLength()) { 238 if (DEBUG) { 239 System.err.println("Log: position outside document: "); 240 System.err.println("decl = " + decl); 241 System.err.println("startOffset = " + start); 242 System.err.println("endOffset = " + end); 243 Thread.dumpStack(); 244 } 245 246 return NO_SPAN; 247 } 248 249 String name = ((ClassTree) leaf).getSimpleName().toString(); 250 251 if (name.length() == 0) 252 return NO_SPAN; 253 254 try { 255 String text = doc.getText(start, end - start); 256 257 int index = text.indexOf(name); 258 259 if (index == (-1)) { 260 return NO_SPAN; 261 } 263 264 start += index; 265 } catch (BadLocationException e) { 266 LOG.log(Level.INFO, null, e); 267 } 268 269 int exactEnd = start + name.length(); 270 271 return new int[] {start, exactEnd}; 272 } 273 throw new IllegalArgumentException ("Only MethodDecl, VariableDecl and ClassDecl are accepted by this method."); 274 } 275 276 public static int[] findIdentifierSpan(final TreePath decl, final CompilationUnitTree cu, final SourcePositions positions, final Document doc) { 277 final int[][] result = new int[1][]; 278 doc.render(new Runnable () { 279 public void run() { 280 result[0] = findIdentifierSpanImpl(decl, cu, positions, doc); 281 } 282 }); 283 284 return result[0]; 285 } 286 287 private static int findBodyStartImpl(Tree cltree, CompilationUnitTree cu, SourcePositions positions, Document doc) { 288 int start = (int)positions.getStartPosition(cu, cltree); 289 int end = (int)positions.getEndPosition(cu, cltree); 290 291 if (start == (-1) || end == (-1)) { 292 return -1; 293 } 294 295 if (start > doc.getLength() || end > doc.getLength()) { 296 if (DEBUG) { 297 System.err.println("Log: position outside document: "); 298 System.err.println("decl = " + cltree); 299 System.err.println("startOffset = " + start); 300 System.err.println("endOffset = " + end); 301 Thread.dumpStack(); 302 } 303 304 return (-1); 305 } 306 307 try { 308 String text = doc.getText(start, end - start); 309 310 int index = text.indexOf('{'); 311 312 if (index == (-1)) { 313 return -1; 314 } 316 317 return start + index; 318 } catch (BadLocationException e) { 319 LOG.log(Level.INFO, null, e); 320 } 321 322 return (-1); 323 } 324 325 public static int findBodyStart(final Tree cltree, final CompilationUnitTree cu, final SourcePositions positions, final Document doc) { 326 Kind kind = cltree.getKind(); 327 if (kind != Kind.CLASS && kind != Kind.METHOD) 328 throw new IllegalArgumentException ("Unsupported kind: "+ kind); 329 final int[] result = new int[1]; 330 331 doc.render(new Runnable () { 332 public void run() { 333 result[0] = findBodyStartImpl(cltree, cu, positions, doc); 334 } 335 }); 336 337 return result[0]; 338 } 339 340 private static int findLastBracketImpl(MethodTree tree, CompilationUnitTree cu, SourcePositions positions, Document doc) { 341 int start = (int)positions.getStartPosition(cu, tree); 342 int end = (int)positions.getEndPosition(cu, tree); 343 344 if (start == (-1) || end == (-1)) { 345 return -1; 346 } 347 348 if (start > doc.getLength() || end > doc.getLength()) { 349 if (DEBUG) { 350 System.err.println("Log: position outside document: "); 351 System.err.println("decl = " + tree); 352 System.err.println("startOffset = " + start); 353 System.err.println("endOffset = " + end); 354 Thread.dumpStack(); 355 } 356 357 return (-1); 358 } 359 360 try { 361 String text = doc.getText(end - 1, 1); 362 363 if (text.charAt(0) == '}') 364 return end - 1; 365 } catch (BadLocationException e) { 366 LOG.log(Level.INFO, null, e); 367 } 368 369 return (-1); 370 } 371 372 public static int findLastBracket(final MethodTree tree, final CompilationUnitTree cu, final SourcePositions positions, final Document doc) { 373 final int[] result = new int[1]; 374 375 doc.render(new Runnable () { 376 public void run() { 377 result[0] = findLastBracketImpl(tree, cu, positions, doc); 378 } 379 }); 380 381 return result[0]; 382 } 383 384 private static Highlight createHighlightImpl(CompilationUnitTree cu, SourcePositions positions, Document doc, int startOffset, int endOffset, Collection <ColoringAttributes> c, Color es) { 385 try { 386 if (startOffset > doc.getLength() || endOffset > doc.getLength()) { 387 if (DEBUG) { 388 System.err.println("Log: position outside document: "); 389 System.err.println("startOffset = " + startOffset ); 391 System.err.println("endOffset = " + endOffset ); 392 Thread.dumpStack(); 393 } 394 395 return null; 396 } 397 398 return new HighlightImpl(doc, startOffset, endOffset, c, es); 399 } catch (BadLocationException e) { 400 e.printStackTrace(); 401 return null; 402 } 403 } 404 405 private static Highlight createHighlightImpl(CompilationUnitTree cu, SourcePositions positions, Document doc, TreePath tree, Collection <ColoringAttributes> c, Color es) { 406 Tree leaf = tree.getLeaf(); 407 int startOffset = (int)positions.getStartPosition(cu, leaf); 408 int endOffset = (int)positions.getEndPosition(cu, leaf); 409 410 if (leaf instanceof MethodTree || leaf instanceof VariableTree || leaf instanceof ClassTree || leaf instanceof MemberSelectTree) { 412 int[] span = findIdentifierSpan(tree, cu, positions, doc); 413 414 startOffset = span[0]; 415 endOffset = span[1]; 416 } 417 418 if (startOffset == (-1) || endOffset == (-1)) 419 return null; 420 421 return createHighlightImpl(cu, positions, doc, startOffset, endOffset, c, es); 422 } 423 424 public static Highlight createHighlight(final CompilationUnitTree cu, final SourcePositions positions, final Document doc, final TreePath tree, final Collection <ColoringAttributes> c, final Color es) { 425 final Highlight[] result = new Highlight[1]; 426 427 doc.render(new Runnable () { 428 public void run() { 429 result[0] = createHighlightImpl(cu, positions, doc, tree, c, es); 430 } 431 }); 432 433 return result[0]; 434 } 435 436 public static Highlight createHighlight(final CompilationUnitTree cu, final SourcePositions positions, final Document doc, final int startOffset, final int endOffset, final Collection <ColoringAttributes> c, final Color es) { 437 final Highlight[] result = new Highlight[1]; 438 439 doc.render(new Runnable () { 440 public void run() { 441 result[0] = createHighlightImpl(cu, positions, doc, startOffset, endOffset, c, es); 442 } 443 }); 444 445 return result[0]; 446 } 447 448 private static final Set <String > keywords; 449 450 static { 451 keywords = new HashSet (); 452 453 keywords.add("true"); 454 keywords.add("false"); 455 keywords.add("null"); 456 keywords.add("this"); 457 keywords.add("super"); 458 keywords.add("class"); 459 } 460 461 public static boolean isKeyword(Tree tree) { 462 if (tree.getKind() == Kind.IDENTIFIER) { 463 return keywords.contains(((IdentifierTree) tree).getName().toString()); 464 } 465 if (tree.getKind() == Kind.MEMBER_SELECT) { 466 return keywords.contains(((MemberSelectTree) tree).getIdentifier().toString()); 467 } 468 469 return false; 470 } 471 472 public static boolean isPrivateElement(Element el) { 473 if (el.getKind() == ElementKind.PARAMETER) 474 return true; 475 476 if (el.getKind() == ElementKind.LOCAL_VARIABLE) 477 return true; 478 479 if (el.getKind() == ElementKind.EXCEPTION_PARAMETER) 480 return true; 481 482 return el.getModifiers().contains(Modifier.PRIVATE); 483 } 484 485 486 } 487 | Popular Tags |