1 /******************************************************************************* 2 * Copyright (c) 2005, 2020 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.text.tests; 15 16 import static org.junit.Assert.assertEquals; 17 import static org.junit.Assert.assertNull; 18 19 import java.util.Arrays; 20 import java.util.Comparator; 21 22 import org.junit.After; 23 import org.junit.Before; 24 import org.junit.Rule; 25 import org.junit.Test; 26 27 import org.eclipse.jdt.testplugin.JavaProjectHelper; 28 29 import org.eclipse.jdt.core.ICompilationUnit; 30 import org.eclipse.jdt.core.IJavaProject; 31 import org.eclipse.jdt.core.IPackageFragment; 32 import org.eclipse.jdt.core.IPackageFragmentRoot; 33 import org.eclipse.jdt.core.JavaModelException; 34 import org.eclipse.jdt.core.dom.ASTParser; 35 import org.eclipse.jdt.core.dom.CompilationUnit; 36 37 import org.eclipse.jdt.internal.core.manipulation.search.IOccurrencesFinder.OccurrenceLocation; 38 import org.eclipse.jdt.internal.corext.dom.IASTSharedValues; 39 40 import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup; 41 42 import org.eclipse.jdt.internal.ui.search.BreakContinueTargetFinder; 43 44 /** 45 * Tests for the BreakContinueTargerFinder class. 46 * 47 * @since 3.2 48 */ 49 public class BreakContinueTargetFinderTest { 50 @Rule 51 public ProjectTestSetup pts= new ProjectTestSetup(); 52 53 private ASTParser fParser; 54 private BreakContinueTargetFinder fFinder; 55 private IJavaProject fJProject1; 56 private IPackageFragmentRoot fSourceFolder; 57 58 /* 59 * @see junit.framework.TestCase#setUp() 60 */ 61 @Before setUp()62 public void setUp() throws Exception { 63 fParser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); 64 fFinder= new BreakContinueTargetFinder(); 65 66 fJProject1= ProjectTestSetup.getProject(); 67 fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); 68 } 69 70 @After tearDown()71 public void tearDown() throws Exception { 72 JavaProjectHelper.clear(fJProject1, ProjectTestSetup.getDefaultClasspath()); 73 } 74 getHighlights(StringBuffer source, int offset, int length)75 private OccurrenceLocation[] getHighlights(StringBuffer source, int offset, int length) throws Exception { 76 CompilationUnit root = createCompilationUnit(source); 77 String errorString = fFinder.initialize(root, offset, length); 78 assertNull(errorString, errorString); 79 return fFinder.getOccurrences(); 80 } 81 createCompilationUnit(StringBuffer source)82 private CompilationUnit createCompilationUnit(StringBuffer source) throws JavaModelException { 83 IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); 84 ICompilationUnit cu= pack1.createCompilationUnit("E.java", source.toString(), false, null); 85 fParser.setSource(cu); 86 return (CompilationUnit) fParser.createAST(null); 87 } 88 checkSelection(StringBuffer s, int offset, int length, OccurrenceLocation[] expected)89 private void checkSelection(StringBuffer s, int offset, int length, OccurrenceLocation[] expected) throws Exception { 90 OccurrenceLocation[] selectedNodes= getHighlights(s, offset, length); 91 assertEquals("number of selections", expected.length, selectedNodes.length); 92 sortByStartIndex(selectedNodes); 93 sortByStartIndex(expected); 94 for (int i= 0; i < selectedNodes.length; i++) { 95 assertEquals(expected[i].getOffset(), selectedNodes[i].getOffset()); 96 assertEquals(expected[i].getLength(), selectedNodes[i].getLength()); 97 } 98 } 99 sortByStartIndex(OccurrenceLocation[] OccurrenceLocations)100 private void sortByStartIndex(OccurrenceLocation[] OccurrenceLocations) { 101 Arrays.sort(OccurrenceLocations, new Comparator<OccurrenceLocation>() { 102 @Override 103 public int compare(OccurrenceLocation node0, OccurrenceLocation node1) { 104 return node0.getOffset() - node1.getOffset(); 105 } 106 }); 107 } 108 109 //pattern must be found - otherwise it's assumed to be an error find(StringBuffer s, String pattern, int ithOccurrence)110 private OccurrenceLocation find(StringBuffer s, String pattern, int ithOccurrence) { 111 if (ithOccurrence < 1) 112 throw new IllegalStateException("ithOccurrence = " + ithOccurrence); 113 return find(s, pattern, ithOccurrence, 0); 114 } 115 find(StringBuffer s, String pattern, int ithOccurrence, int startIdx)116 private OccurrenceLocation find(StringBuffer s, String pattern, int ithOccurrence, int startIdx) { 117 if (startIdx < 0 || startIdx > s.length()) 118 throw new IllegalStateException("startIdx = " + startIdx); 119 int idx = s.indexOf(pattern, startIdx); 120 if (idx == -1) 121 throw new IllegalStateException("not found \"" + pattern + "\" in \"" + s.substring(startIdx)); 122 if (ithOccurrence == 1) 123 return new OccurrenceLocation(idx, pattern.length(), 0, ""); 124 return find(s, pattern, ithOccurrence-1, idx+1); 125 } 126 127 @Test testBreakFor()128 public void testBreakFor() throws Exception { 129 StringBuffer s= new StringBuffer(); 130 s.append("class A{\n"); 131 s.append(" void foo(int[] xs){\n"); 132 s.append(" for (int i = 0; i < xs.length; i++) {\n"); 133 s.append(" break;"); 134 s.append(" }\n"); 135 s.append(" }\n"); 136 s.append("}\n"); 137 int offset= 1 + s.indexOf("break");//middle of word 138 int length= 0; 139 OccurrenceLocation[] ranges= { find(s, "for", 1), find(s, "}", 1) }; 140 checkSelection(s, offset, length, ranges); 141 } 142 143 @Test testBreakForeach()144 public void testBreakForeach() throws Exception { 145 StringBuffer s= new StringBuffer(); 146 s.append("class A{\n"); 147 s.append(" void foo(int[] xs){\n"); 148 s.append(" for (int i : xs){\n"); 149 s.append(" break;"); 150 s.append(" }\n"); 151 s.append(" }\n"); 152 s.append("}\n"); 153 int offset= 1 + s.indexOf("break");//middle of word 154 int length= 0; 155 OccurrenceLocation[] ranges= { find(s, "for", 1), find(s, "}", 1) }; 156 checkSelection(s, offset, length, ranges); 157 } 158 159 @Test testBreakWhile()160 public void testBreakWhile() throws Exception { 161 StringBuffer s= new StringBuffer(); 162 s.append("class A{\n"); 163 s.append(" void foo(boolean b){\n"); 164 s.append(" while (b) {\n"); 165 s.append(" System.err.println(b);\n"); 166 s.append(" break;\n"); 167 s.append(" }\n"); 168 s.append(" }\n"); 169 s.append("}"); 170 int offset= 1 + s.indexOf("break");//middle of word 171 int length= 0; 172 OccurrenceLocation[] ranges= { find(s, "while", 1), find(s, "}", 1) }; 173 checkSelection(s, offset, length, ranges); 174 } 175 176 @Test testBreakDo()177 public void testBreakDo() throws Exception { 178 StringBuffer s= new StringBuffer(); 179 s.append("class A{\n"); 180 s.append(" void foo(boolean b){\n"); 181 s.append(" do {\n"); 182 s.append(" System.err.println(b);\n"); 183 s.append(" break;\n"); 184 s.append(" } while(b);\n"); 185 s.append(" }\n"); 186 s.append("}"); 187 int offset= 1 + s.indexOf("break");//middle of word 188 int length= 0; 189 OccurrenceLocation[] ranges= { find(s, "do", 1), find(s, ";", 3) }; 190 checkSelection(s, offset, length, ranges); 191 } 192 193 @Test testBreakSwitch()194 public void testBreakSwitch() throws Exception { 195 StringBuffer s= new StringBuffer(); 196 s.append("class A{\n"); 197 s.append(" void foo(int i){\n"); 198 s.append(" switch (i){\n"); 199 s.append(" case 1: System.err.println(i); break;\n"); 200 s.append(" default:System.out.println(i);\n"); 201 s.append(" }\n"); 202 s.append(" }\n"); 203 s.append("}\n"); 204 int offset= 1 + s.indexOf("break");//middle of word 205 int length= 2; 206 OccurrenceLocation[] ranges= { find(s, "switch", 1), find(s, "}", 1) }; 207 checkSelection(s, offset, length, ranges); 208 } 209 210 @Test testLabeledBreakFor()211 public void testLabeledBreakFor() throws Exception { 212 StringBuffer s= new StringBuffer(); 213 s.append("class A{\n"); 214 s.append(" void foo(int[] xs){\n"); 215 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 216 s.append(" do{\n"); 217 s.append(" break bar;"); 218 s.append(" }while (xs != null);\n"); 219 s.append(" }\n"); 220 s.append(" }\n"); 221 s.append("}\n"); 222 int offset= 1 + s.indexOf("break");//middle of word 223 int length= 0; 224 OccurrenceLocation[] ranges= { find(s, "bar", 1), find(s, "}", 2) }; 225 checkSelection(s, offset, length, ranges); 226 } 227 228 @Test testLabeledBreakFor1()229 public void testLabeledBreakFor1() throws Exception { 230 StringBuffer s= new StringBuffer(); 231 s.append("class A{\n"); 232 s.append(" void foo(int[] xs){\n"); 233 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 234 s.append(" baz: do{\n"); 235 s.append(" break bar;"); 236 s.append(" }while (xs != null);\n"); 237 s.append(" }\n"); 238 s.append(" }\n"); 239 s.append("}\n"); 240 int offset= 5 + s.indexOf("break");//after word 241 int length= 0; 242 OccurrenceLocation[] ranges= { find(s, "bar", 1), find(s, "}", 2) }; 243 checkSelection(s, offset, length, ranges); 244 } 245 246 @Test testBreakFor2()247 public void testBreakFor2() throws Exception { 248 StringBuffer s= new StringBuffer(); 249 s.append("class A{\n"); 250 s.append(" void foo(int[] xs){\n"); 251 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 252 s.append(" baz: do{\n"); 253 s.append(" break;"); 254 s.append(" }while (xs != null);\n"); 255 s.append(" }\n"); 256 s.append(" }\n"); 257 s.append("}\n"); 258 int offset= s.indexOf("break") + 2; // inside 'break' 259 int length= 0; 260 OccurrenceLocation[] ranges= { find(s, "baz", 1), find(s, ";", 4) }; 261 checkSelection(s, offset, length, ranges); 262 } 263 264 @Test testLabeledBreakIf()265 public void testLabeledBreakIf() throws Exception { 266 StringBuffer s= new StringBuffer(); 267 s.append("class A{\n"); 268 s.append(" public static void main(String[] args) {\n"); 269 s.append(" stay: if (true) {\n"); 270 s.append(" for (int i= 0; i < 5; i++) {\n"); 271 s.append(" System.out.println(i);\n"); 272 s.append(" if (i == 3)\n"); 273 s.append(" break stay;\n"); 274 s.append(" }\n"); 275 s.append(" System.out.println(\"after loop\");\n"); 276 s.append(" return;\n"); 277 s.append(" }\n"); 278 s.append(" System.out.println(\"Stayed!\");\n"); 279 s.append(" }\n"); 280 s.append("}\n"); 281 int offset= s.indexOf("break");//before word 282 int length= 0; 283 OccurrenceLocation[] ranges= { find(s, "stay", 1), find(s, "}", 2) }; 284 checkSelection(s, offset, length, ranges); 285 } 286 287 @Test testContinueFor()288 public void testContinueFor() throws Exception { 289 StringBuffer s= new StringBuffer(); 290 s.append("class A{\n"); 291 s.append(" void foo(int[] xs){\n"); 292 s.append(" for (int i = 0; i < xs.length; i++) {\n"); 293 s.append(" continue;"); 294 s.append(" }\n"); 295 s.append(" }\n"); 296 s.append("}\n"); 297 int offset= 1 + s.indexOf("continue");//middle of word 298 int length= 0; 299 OccurrenceLocation[] ranges= { find(s, "for", 1) }; 300 checkSelection(s, offset, length, ranges); 301 } 302 303 @Test testContinueForeach()304 public void testContinueForeach() throws Exception { 305 StringBuffer s= new StringBuffer(); 306 s.append("class A{\n"); 307 s.append(" void foo(int[] xs){\n"); 308 s.append(" for (int i : xs){\n"); 309 s.append(" continue;"); 310 s.append(" }\n"); 311 s.append(" }\n"); 312 s.append("}\n"); 313 int offset= 1 + s.indexOf("continue");//middle of word 314 int length= 0; 315 OccurrenceLocation[] ranges= { find(s, "for", 1) }; 316 checkSelection(s, offset, length, ranges); 317 } 318 319 @Test testContinueWhile()320 public void testContinueWhile() throws Exception { 321 StringBuffer s= new StringBuffer(); 322 s.append("class A{\n"); 323 s.append(" void foo(boolean b){\n"); 324 s.append(" while (b) {\n"); 325 s.append(" System.err.println(b);\n"); 326 s.append(" continue;\n"); 327 s.append(" }\n"); 328 s.append(" }\n"); 329 s.append("}"); 330 int offset= 1 + s.indexOf("continue");//middle of word 331 int length= 0; 332 OccurrenceLocation[] ranges= { find(s, "while", 1) }; 333 checkSelection(s, offset, length, ranges); 334 } 335 336 @Test testContinueDo()337 public void testContinueDo() throws Exception { 338 StringBuffer s= new StringBuffer(); 339 s.append("class A{\n"); 340 s.append(" void foo(boolean b){\n"); 341 s.append(" do {\n"); 342 s.append(" System.err.println(b);\n"); 343 s.append(" continue;\n"); 344 s.append(" } while(b);\n"); 345 s.append(" }\n"); 346 s.append("}"); 347 int offset= 1 + s.indexOf("continue");//middle of word 348 int length= 0; 349 OccurrenceLocation[] ranges= { find(s, "do", 1) }; 350 checkSelection(s, offset, length, ranges); 351 } 352 353 //continue skips over switches 354 @Test testContinueSwitch()355 public void testContinueSwitch() throws Exception { 356 StringBuffer s= new StringBuffer(); 357 s.append("class A{\n"); 358 s.append(" void foo(int i){\n"); 359 s.append(" do{\n"); 360 s.append(" switch (i){\n"); 361 s.append(" case 1: System.err.println(i); continue;\n"); 362 s.append(" default:System.out.println(i);\n"); 363 s.append(" }\n"); 364 s.append(" }while(i != 9);\n"); 365 s.append(" }\n"); 366 s.append("}\n"); 367 int offset= 1 + s.indexOf("continue");//middle of word 368 int length= 2; 369 OccurrenceLocation[] ranges= { find(s, "do", 1) }; 370 checkSelection(s, offset, length, ranges); 371 } 372 373 @Test testLabeledContinueFor()374 public void testLabeledContinueFor() throws Exception { 375 StringBuffer s= new StringBuffer(); 376 s.append("class A{\n"); 377 s.append(" void foo(int[] xs){\n"); 378 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 379 s.append(" do{\n"); 380 s.append(" continue bar;"); 381 s.append(" }while (xs != null);\n"); 382 s.append(" }\n"); 383 s.append(" }\n"); 384 s.append("}\n"); 385 int offset= 1 + s.indexOf("continue");//middle of word 386 int length= 0; 387 OccurrenceLocation[] ranges= { find(s, "bar", 1) }; 388 checkSelection(s, offset, length, ranges); 389 } 390 391 @Test testLabeledContinueFor1()392 public void testLabeledContinueFor1() throws Exception { 393 StringBuffer s= new StringBuffer(); 394 s.append("class A{\n"); 395 s.append(" void foo(int[] xs){\n"); 396 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 397 s.append(" baz: do{\n"); 398 s.append(" continue bar;"); 399 s.append(" }while (xs != null);\n"); 400 s.append(" }\n"); 401 s.append(" }\n"); 402 s.append("}\n"); 403 int offset= 1 + s.indexOf("continue");//middle of word 404 int length= 0; 405 OccurrenceLocation[] ranges= { find(s, "bar", 1) }; 406 checkSelection(s, offset, length, ranges); 407 } 408 409 @Test testLabeledContinueFor2()410 public void testLabeledContinueFor2() throws Exception { 411 StringBuffer s= new StringBuffer(); 412 s.append("class A{\n"); 413 s.append(" void foo(int[] xs){\n"); 414 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 415 s.append(" baz: do{\n"); 416 s.append(" continue bar;"); 417 s.append(" }while (xs != null);\n"); 418 s.append(" }\n"); 419 s.append(" }\n"); 420 s.append("}\n"); 421 int offset= s.indexOf("continue bar;") + 1+ "continue ".length();//middle of label reference 422 int length= 0; 423 OccurrenceLocation[] ranges= { find(s, "bar", 1) }; 424 checkSelection(s, offset, length, ranges); 425 } 426 427 @Test testContinueFor2()428 public void testContinueFor2() throws Exception { 429 StringBuffer s= new StringBuffer(); 430 s.append("class A{\n"); 431 s.append(" void foo(int[] xs){\n"); 432 s.append(" bar: for (int i = 0; i < xs.length; i++) {\n"); 433 s.append(" baz: do{\n"); 434 s.append(" continue;"); 435 s.append(" }while (xs != null);\n"); 436 s.append(" }\n"); 437 s.append(" }\n"); 438 s.append("}\n"); 439 int offset= s.indexOf("continue;") + 2; // inside 'continue' 440 int length= 0; 441 OccurrenceLocation[] ranges= { find(s, "baz", 1) }; 442 checkSelection(s, offset, length, ranges); 443 } 444 } 445