1 19 20 package org.netbeans.modules.junit; 21 22 import com.sun.source.tree.ClassTree; 23 import com.sun.source.tree.CompilationUnitTree; 24 import com.sun.source.tree.MethodTree; 25 import com.sun.source.tree.Tree; 26 import com.sun.source.util.SourcePositions; 27 import com.sun.source.util.TreePathScanner; 28 import com.sun.source.util.Trees; 29 import java.io.IOException ; 30 import java.net.URL ; 31 import java.util.ArrayList ; 32 import java.util.List ; 33 import java.util.logging.Level ; 34 import java.util.logging.Level ; 35 import java.util.logging.Logger ; 36 import javax.lang.model.element.Element; 37 import javax.swing.Action ; 38 import javax.swing.JEditorPane ; 39 import javax.swing.text.StyledDocument ; 40 import org.netbeans.api.java.classpath.ClassPath; 41 import org.netbeans.api.java.queries.UnitTestForSourceQuery; 42 import org.netbeans.api.java.source.CancellableTask; 43 import org.netbeans.api.java.source.CompilationController; 44 import org.netbeans.api.java.source.ElementHandle; 45 import org.netbeans.api.java.source.JavaSource; 46 import org.netbeans.api.java.source.JavaSource.Phase; 47 import org.netbeans.spi.java.classpath.PathResourceImplementation; 48 import org.netbeans.spi.java.classpath.support.ClassPathSupport; 49 import org.openide.ErrorManager; 50 import org.openide.cookies.EditorCookie; 51 import org.openide.cookies.LineCookie; 52 import org.openide.cookies.OpenCookie; 53 import org.openide.filesystems.FileObject; 54 import org.openide.loaders.DataObject; 55 import org.openide.loaders.DataObjectNotFoundException; 56 import org.openide.nodes.Node; 57 import org.openide.text.Line; 58 import org.openide.text.NbDocument; 59 import org.openide.util.HelpCtx; 60 import org.openide.util.NbBundle; 61 62 69 @SuppressWarnings ("serial") 70 public class OpenTestAction extends TestAction { 71 72 public OpenTestAction() { 73 putValue("noIconInMenu", Boolean.TRUE); 74 } 75 76 77 protected void performAction (Node[] nodes) { 78 FileObject selectedFO; 79 80 for (int i = 0; i < nodes.length; i++) { 81 selectedFO = TestUtil.getFileObjectFromNode(nodes[i]); 83 if (selectedFO == null) { 84 TestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class, "MSG_file_from_node_failed")); 85 continue; 86 } 87 ClassPath cp = ClassPath.getClassPath(selectedFO, ClassPath.SOURCE); 88 if (cp == null) { 89 TestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class, 90 "MSG_no_project", selectedFO)); 91 continue; 92 } 93 94 FileObject packageRoot = cp.findOwnerRoot(selectedFO); 95 URL [] testRoots = UnitTestForSourceQuery.findUnitTests(packageRoot); 96 FileObject fileToOpen = null; 97 for (int j = 0 ; j < testRoots.length; j++) { 98 fileToOpen = findUnitTestInTestRoot(cp, selectedFO, testRoots[j]); 99 if (fileToOpen != null) break; 100 } 101 102 if (fileToOpen != null) { 103 openFile(fileToOpen); 104 } else { 105 String testClsName = getTestName(cp, selectedFO).replace('/','.'); 106 String pkgName = cp.getResourceName(selectedFO, '.', false); 107 boolean isPackage = selectedFO.isFolder(); 108 boolean isDefPkg = isPackage && (pkgName.length() == 0); 109 String msgPattern = !isPackage 110 ? "MSG_test_class_not_found" : isDefPkg 112 ? "MSG_testsuite_class_not_found_def_pkg" : "MSG_testsuite_class_not_found"; 115 String [] params = isDefPkg ? new String [] { testClsName } 116 : new String [] { testClsName, 117 pkgName }; 118 119 TestUtil.notifyUser(NbBundle.getMessage(OpenTestAction.class, 120 msgPattern, params), 121 ErrorManager.INFORMATIONAL); 122 continue; 123 } 124 } 125 } 126 127 private static FileObject findUnitTestInTestRoot(ClassPath cp, FileObject selectedFO, URL testRoot) { 128 ClassPath testClassPath = null; 129 if (testRoot == null) { testClassPath = cp; 131 } else { 132 try { 133 List <PathResourceImplementation> cpItems 134 = new ArrayList <PathResourceImplementation>(); 135 cpItems.add(ClassPathSupport.createResource(testRoot)); 136 testClassPath = ClassPathSupport.createClassPath(cpItems); 137 } catch (IllegalArgumentException ex) { 138 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 139 testClassPath = cp; 140 } 141 } 142 String testName = getTestName(cp, selectedFO); 143 return testClassPath.findResource(testName+".java"); 144 } 145 146 private static String getTestName(ClassPath cp, FileObject selectedFO) { 147 String resource = cp.getResourceName(selectedFO, '/', false); 148 String testName = null; 149 if (selectedFO.isFolder()) { 150 testName = TestUtil.convertPackage2SuiteName(resource); 152 } else { 153 testName = TestUtil.convertClass2TestName(resource); 155 } 156 157 return testName; 158 } 159 160 164 public static boolean openFile(FileObject fo) { 165 DataObject dobj; 166 try { 167 dobj = DataObject.find(fo); 168 } catch (DataObjectNotFoundException e) { 169 getLogger().log(Level.WARNING, null, e); 170 return false; 171 } 172 assert dobj != null; 173 174 EditorCookie editorCookie = dobj.getCookie(EditorCookie.class); 175 if (editorCookie != null) { 176 editorCookie.open(); 177 return true; 178 } 179 180 OpenCookie openCookie = dobj.getCookie(OpenCookie.class); 181 if (openCookie != null) { 182 openCookie.open(); 183 return true; 184 } 185 186 return false; 187 } 188 189 191 static boolean openFileAtElement(FileObject fileObject, 192 ElementHandle<Element> element) { 193 final DataObject dataObject; 194 try { 195 dataObject = DataObject.find(fileObject); 196 } catch (DataObjectNotFoundException e) { 197 getLogger().log(Level.INFO, null, e); 198 return false; 199 } 200 assert dataObject != null; 201 202 final EditorCookie editorCookie = dataObject.getCookie(EditorCookie.class); 203 if (editorCookie != null) { 204 205 StyledDocument doc; 206 try { 207 doc = editorCookie.openDocument(); 208 } catch (IOException ex) { 209 String msg = ex.getLocalizedMessage(); 210 if (msg == null) { 211 msg = ex.getMessage(); 212 } 213 getLogger().log(Level.SEVERE, msg, ex); 214 return false; 215 } 216 217 editorCookie.open(); 218 219 LineCookie lineCookie = dataObject.getCookie(LineCookie.class); 220 if ((lineCookie != null) && (element != null) && (doc != null)) { 221 int currentPos = -1; 222 JEditorPane [] editorPanes = editorCookie.getOpenedPanes(); 223 if ((editorPanes != null) && (editorPanes.length != 0)) { 224 currentPos = editorPanes[0].getCaretPosition(); 225 } 226 int[] elementPositionBounds = null; 227 try { 228 elementPositionBounds = getPositionRange(fileObject, element); 229 } catch (IOException ex) { 230 getLogger().log(Level.WARNING, null, ex); 231 } 232 if ((currentPos == -1) 233 || (elementPositionBounds != null) 234 && ((currentPos < elementPositionBounds[0]) 235 ||(currentPos >= elementPositionBounds[1]))) { 236 int startPos = elementPositionBounds[0]; 237 int lineNum = NbDocument.findLineNumber(doc, startPos); 238 if (lineNum != -1) { 239 Line line = lineCookie.getLineSet().getCurrent(lineNum); 240 try { 241 int lineOffset = NbDocument.findLineOffset(doc, 242 lineNum); 243 int column = startPos - lineOffset; 244 line.show(Line.SHOW_GOTO, column); 245 } catch (IndexOutOfBoundsException ex) { 246 Logger.getLogger(OpenTestAction.class.getName()) 247 .log(Level.INFO, null, ex); 248 line.show(Line.SHOW_GOTO); 249 } 250 } 251 } 252 } 253 return true; 254 } 255 256 OpenCookie openCookie = dataObject.getCookie(OpenCookie.class); 257 if (openCookie != null) { 258 openCookie.open(); 259 return true; 260 } 261 262 return false; 263 } 264 265 267 private static Logger getLogger() { 268 return Logger.getLogger(OpenTestAction.class.getName()); 269 } 270 271 273 private static int[] getPositionRange( 274 FileObject fileObj, 275 ElementHandle<Element> elemHandle) throws IOException { 276 PositionRangeFinder posFinder = new PositionRangeFinder(fileObj, elemHandle); 277 JavaSource.forFileObject(fileObj).runUserActionTask(posFinder, true); 278 return posFinder.getPositionRange(); 279 } 280 281 284 private static class PositionRangeFinder 285 implements CancellableTask<CompilationController> { 286 287 private final FileObject fileObj; 288 private final ElementHandle<Element> elemHandle; 289 private int[] positionRange = null; 290 private volatile boolean cancelled; 291 292 294 private PositionRangeFinder(FileObject fileObj, 295 ElementHandle<Element> elemHandle) { 296 this.fileObj = fileObj; 297 this.elemHandle = elemHandle; 298 } 299 300 302 public void run(CompilationController controller) throws IOException { 303 try { 304 controller.toPhase(Phase.RESOLVED); } catch (IOException ex) { 306 Logger.getLogger("global").log(Level.SEVERE, null, ex); } 308 if (cancelled) { 309 return; 310 } 311 312 Element element = elemHandle.resolve(controller); 313 if (cancelled || (element == null)) { 314 return; 315 } 316 317 Trees trees = controller.getTrees(); 318 CompilationUnitTree compUnit = controller.getCompilationUnit(); 319 DeclarationTreeFinder treeFinder = new DeclarationTreeFinder( 320 element, trees); 321 treeFinder.scan(compUnit, null); 322 Tree tree = treeFinder.getDeclarationTree(); 323 324 if (tree != null) { 325 SourcePositions srcPositions = trees.getSourcePositions(); 326 long startPos = srcPositions.getStartPosition(compUnit, tree); 327 long endPos = srcPositions.getEndPosition(compUnit, tree); 328 329 if ((startPos >= 0) && (startPos <= (long) Integer.MAX_VALUE) 330 && (endPos >= 0) && (endPos <= (long) Integer.MAX_VALUE)) { 331 positionRange = new int[2]; 332 positionRange[0] = (int) startPos; 333 positionRange[1] = (int) endPos; 334 } 335 } 336 } 337 338 340 public void cancel() { 341 cancelled = true; 342 } 343 344 346 int[] getPositionRange() { 347 return positionRange; 348 } 349 350 } 351 352 355 private static class DeclarationTreeFinder extends TreePathScanner<Void , Void > { 356 357 private final Element element; 358 private final Trees trees; 359 private Tree declTree; 360 361 363 private DeclarationTreeFinder(Element element, Trees trees) { 364 this.element = element; 365 this.trees = trees; 366 } 367 368 @Override 369 public Void visitClass(ClassTree tree, Void d) { 370 if (declTree == null) { 371 handleDeclaration(); 372 super.visitClass(tree, d); 373 } 374 return null; 375 } 376 377 @Override 378 public Void visitMethod(MethodTree tree, Void d) { 379 if (declTree == null) { 380 handleDeclaration(); 381 super.visitMethod(tree, d); 382 } 383 return null; 384 } 385 386 388 public void handleDeclaration() { 389 Element found = trees.getElement(getCurrentPath()); 390 391 if (element.equals(found)) { 392 declTree = getCurrentPath().getLeaf(); 393 } 394 } 395 396 398 Tree getDeclarationTree() { 399 return declTree; 400 } 401 402 } 403 404 public String getName () { 405 return NbBundle.getMessage (OpenTestAction.class, "LBL_Action_OpenTest"); 406 } 407 408 protected String iconResource () { 409 return "org/netbeans/modules/junit/resources/OpenTestActionIcon.gif"; 410 } 411 412 public HelpCtx getHelpCtx () { 413 return new HelpCtx(OpenTestAction.class); 414 } 415 416 422 423 protected void initialize () { 424 super.initialize (); 425 putProperty(Action.SHORT_DESCRIPTION, NbBundle.getMessage(OpenTestAction.class, "HINT_Action_OpenTest")); 426 } 427 428 } 429 | Popular Tags |