1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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.core.tests.model;
15 
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.jdt.core.ICompilationUnit;
18 import org.eclipse.jdt.core.IJavaElement;
19 import org.eclipse.jdt.core.IType;
20 
21 import junit.framework.Test;
22 
23 public class LocalElementTests extends ModifyingResourceTests {
24 
LocalElementTests(String name)25 	public LocalElementTests(String name) {
26 		super(name);
27 	}
28 
29 	// Use this static initializer to specify subset for tests
30 	// All specified tests which do not belong to the class are skipped...
31 	static {
32 		// Names of tests to run: can be "testBugXXXX" or "BugXXXX")
33 //		TESTS_NAMES = new String[] { "testLocalType8" };
34 		// Numbers of tests to run: "test<number>" will be run for each number of this array
35 //		TESTS_NUMBERS = new int[] { 13 };
36 		// Range numbers of tests to run: all tests between "test<first>" and "test<last>" will be run for { first, last }
37 //		TESTS_RANGE = new int[] { 16, -1 };
38 	}
suite()39 	public static Test suite() {
40 		return buildModelTestSuite(LocalElementTests.class);
41 	}
42 
43 	@Override
setUpSuite()44 	public void setUpSuite() throws Exception {
45 		createJavaProject("P");
46 	}
47 
48 	@Override
tearDownSuite()49 	public void tearDownSuite() throws Exception {
50 		deleteProject("P");
51 	}
52 
53 	/*
54 	 * Anonymous type test.
55 	 */
testAnonymousType1()56 	public void testAnonymousType1() throws CoreException {
57 		try {
58 			createFile(
59 				"/P/X.java",
60 				"public class X {\n" +
61 				"  void foo() {\n" +
62 				"    run(new X() {\n" +
63 				"    });\n" +
64 				"  }\n" +
65 				"  void run(X x) {\n" +
66 				"  }\n" +
67 				"}"
68 			);
69 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
70 			assertElementDescendants(
71 				"Unexpected compilation unit contents",
72 				"X.java\n" +
73 				"  class X\n" +
74 				"    void foo()\n" +
75 				"      class <anonymous #1>\n" +
76 				"    void run(X)",
77 				cu);
78 		} finally {
79 			deleteFile("/P/X.java");
80 		}
81 	}
82 
83 	/*
84 	 * Anonymous type test.
85 	 */
testAnonymousType2()86 	public void testAnonymousType2() throws CoreException {
87 		try {
88 			createFile(
89 				"/P/X.java",
90 				"public class X {\n" +
91 				"  public class Y {\n" +
92 				"  }\n" +
93 				"  void foo() {\n" +
94 				"    run(new X() {\n" +
95 				"    });\n" +
96 				"    run(new Y() {\n" +
97 				"    });\n" +
98 				"  }\n" +
99 				"  void run(X x) {\n" +
100 				"  }\n" +
101 				"}"
102 			);
103 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
104 			assertElementDescendants(
105 				"Unexpected compilation unit contents",
106 				"X.java\n" +
107 				"  class X\n" +
108 				"    class Y\n" +
109 				"    void foo()\n" +
110 				"      class <anonymous #1>\n" +
111 				"      class <anonymous #2>\n" +
112 				"    void run(X)",
113 				cu);
114 		} finally {
115 			deleteFile("/P/X.java");
116 		}
117 	}
118 
119 	/*
120 	 * Anonymous type test.
121 	 */
testAnonymousType3()122 	public void testAnonymousType3() throws CoreException {
123 		try {
124 			createFile(
125 				"/P/X.java",
126 				"public class X {\n" +
127 				"  void foo() {\n" +
128 				"    run(new X() {\n" +
129 				"      void bar() {\n" +
130 				"        run(new X() {\n" +
131 				"        });\n" +
132 				"      }\n" +
133 				"    });\n" +
134 				"  }\n" +
135 				"  void run(X x) {\n" +
136 				"  }\n" +
137 				"}"
138 			);
139 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
140 			assertElementDescendants(
141 				"Unexpected compilation unit contents",
142 				"X.java\n" +
143 				"  class X\n" +
144 				"    void foo()\n" +
145 				"      class <anonymous #1>\n" +
146 				"        void bar()\n" +
147 				"          class <anonymous #1>\n" +
148 				"    void run(X)",
149 				cu);
150 		} finally {
151 			deleteFile("/P/X.java");
152 		}
153 	}
154 
155 	/*
156 	 * Anonymous type test.
157 	 */
testAnonymousType4()158 	public void testAnonymousType4() throws CoreException {
159 		try {
160 			createFile(
161 				"/P/X.java",
162 				"public class X {\n" +
163 				"  {\n" +
164 				"      field = new Vector() {\n" +
165 				"      };\n" +
166 				"  }\n" +
167 				"  Object field = new Object() {\n" +
168 				"  };\n" +
169 				"  void foo() {\n" +
170 				"    run(new X() {\n" +
171 				"    });\n" +
172 				"  }\n" +
173 				"  void run(X x) {\n" +
174 				"  }\n" +
175 				"}"
176 			);
177 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
178 			assertElementDescendants(
179 				"Unexpected compilation unit contents",
180 				"X.java\n" +
181 				"  class X\n" +
182 				"    <initializer #1>\n" +
183 				"      class <anonymous #1>\n" +
184 				"    Object field\n" +
185 				"      class <anonymous #1>\n" +
186 				"    void foo()\n" +
187 				"      class <anonymous #1>\n" +
188 				"    void run(X)",
189 				cu);
190 		} finally {
191 			deleteFile("/P/X.java");
192 		}
193 	}
194 
195 	/*
196 	 * Anonymous type test.
197 	 * (regression test for bug 69028 Anonymous type in argument of super() is not in type hierarchy)
198 	 */
testAnonymousType5()199 	public void testAnonymousType5() throws CoreException {
200 		try {
201 			createFile(
202 				"/P/X.java",
203 				"public class X {\n" +
204 				"  X(Object o) {\n" +
205 				"  }\n" +
206 				"}\n" +
207 				"class Y extends X {\n" +
208 				"  Y() {\n" +
209 				"    super(new Object() {});\n" +
210 				"  }\n" +
211 				"}"
212 			);
213 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
214 			assertElementDescendants(
215 				"Unexpected compilation unit contents",
216 				"X.java\n" +
217 				"  class X\n" +
218 				"    X(Object)\n" +
219 				"  class Y\n" +
220 				"    Y()\n" +
221 				"      class <anonymous #1>",
222 				cu);
223 		} finally {
224 			deleteFile("/P/X.java");
225 		}
226 	}
227 
228 	/*
229 	 * Ensures that an anonymous in an enum constant is said to be local.
230 	 * (regression test for bug 85298 [1.5][enum] IType of anonymous enum declaration says isLocal() == false)
231 	 */
testAnonymousType6()232 	public void testAnonymousType6() throws CoreException {
233 		try {
234 			createJavaProject("P15", new String[] {""}, new String[] {"JCL15_LIB"}, "", "1.5");
235 			createFile(
236 				"/P15/En.java",
237 				"public enum En {\n" +
238 				"  CONST() {};\n" +
239 				"}"
240 			);
241 			IType type = getCompilationUnit("/P15/En.java").getType("En").getField("CONST").getType("", 1);
242 			assertTrue("Should be a local type", type.isLocal());
243 		} finally {
244 			deleteProject("P15");
245 		}
246 	}
247 
248 	/*
249 	 * Anonymous type test.
250 	 * (regression test for bug 147485 Anonymous type missing from java model)
251 	 */
testAnonymousType7()252 	public void testAnonymousType7() throws CoreException {
253 		try {
254 			createFile(
255 				"/P/X.java",
256 				"public class X {\n" +
257 				"	class Y {\n" +
258 				"	}\n" +
259 				"	{\n" +
260 				"		new Y() {\n" +
261 				"			class Z {\n" +
262 				"			}\n" +
263 				"			{\n" +
264 				"				new Y() {\n" +
265 				"				};\n" +
266 				"			}\n" +
267 				"		};\n" +
268 				"	}\n" +
269 				"}"
270 			);
271 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
272 			assertElementDescendants(
273 				"Unexpected compilation unit contents",
274 				"X.java\n" +
275 				"  class X\n" +
276 				"    class Y\n" +
277 				"    <initializer #1>\n" +
278 				"      class <anonymous #1>\n" +
279 				"        class Z\n" +
280 				"        <initializer #1>\n" +
281 				"          class <anonymous #1>",
282 				cu);
283 		} finally {
284 			deleteFile("/P/X.java");
285 		}
286 	}
287 
288 	/*
289 	 * IType.getSuperclassName() test
290 	 */
testGetSuperclassName()291 	public void testGetSuperclassName() throws CoreException {
292 		try {
293 			createFile(
294 				"/P/X.java",
295 				"public class X {\n" +
296 				"  void foo() {\n" +
297 				"    run(new X() {\n" +
298 				"    });\n" +
299 				"  }\n" +
300 				"  void run(X x) {\n" +
301 				"  }\n" +
302 				"}"
303 			);
304 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
305 			IType type = cu.getType("X").getMethod("foo", new String[0]).getType("", 1);
306 			assertEquals(
307 				"Unexpected superclass name",
308 				"X",
309 				type.getSuperclassName());
310 		} finally {
311 			deleteFile("/P/X.java");
312 		}
313 	}
314 
315 	/*
316 	 * IMember.getType(...) test
317 	 */
testGetType()318 	public void testGetType() {
319 		ICompilationUnit cu = getCompilationUnit("P/X.java");
320 		IType topLevelType = cu.getType("X");
321 		IJavaElement[] types = new IJavaElement[5];
322 		types[0] = topLevelType.getInitializer(1).getType("", 1);
323 		types[1] = topLevelType.getInitializer(1).getType("Y", 1);
324 		types[2] = topLevelType.getField("f").getType("", 1);
325 		types[3] = topLevelType.getMethod("foo", new String[] {"I", "QString;"}).getType("", 1);
326 		types[4] = topLevelType.getMethod("foo", new String[] {"I", "QString;"}).getType("Z", 1);
327 		assertElementsEqual(
328 			"Unexpected types",
329 			"<anonymous #1> [in <initializer #1> [in X [in X.java [in <default> [in <project root> [in P]]]]]]\n" +
330 			"Y [in <initializer #1> [in X [in X.java [in <default> [in <project root> [in P]]]]]]\n" +
331 			"<anonymous #1> [in f [in X [in X.java [in <default> [in <project root> [in P]]]]]]\n" +
332 			"<anonymous #1> [in foo(int, String) [in X [in X.java [in <default> [in <project root> [in P]]]]]]\n" +
333 			"Z [in foo(int, String) [in X [in X.java [in <default> [in <project root> [in P]]]]]]",
334 			types);
335 	}
336 
337 	/*
338 	 * Local type test.
339 	 */
testLocalType1()340 	public void testLocalType1() throws CoreException {
341 		try {
342 			createFile(
343 				"/P/X.java",
344 				"public class X {\n" +
345 				"  void foo() {\n" +
346 				"    class Y {\n" +
347 				"    }\n" +
348 				"  }\n" +
349 				"}"
350 			);
351 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
352 			assertElementDescendants(
353 				"Unexpected compilation unit contents",
354 				"X.java\n" +
355 				"  class X\n" +
356 				"    void foo()\n" +
357 				"      class Y",
358 				cu);
359 		} finally {
360 			deleteFile("/P/X.java");
361 		}
362 	}
363 
364 	/*
365 	 * Local type test.
366 	 */
testLocalType2()367 	public void testLocalType2() throws CoreException {
368 		try {
369 			createFile(
370 				"/P/X.java",
371 				"public class X {\n" +
372 				"  void foo() {\n" +
373 				"    class Y {\n" +
374 				"    }\n" +
375 				"    class Z {\n" +
376 				"    }\n" +
377 				"  }\n" +
378 				"}"
379 			);
380 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
381 			assertElementDescendants(
382 				"Unexpected compilation unit contents",
383 				"X.java\n" +
384 				"  class X\n" +
385 				"    void foo()\n" +
386 				"      class Y\n" +
387 				"      class Z",
388 				cu);
389 		} finally {
390 			deleteFile("/P/X.java");
391 		}
392 	}
393 
394 	/*
395 	 * Local type test.
396 	 */
testLocalType3()397 	public void testLocalType3() throws CoreException {
398 		try {
399 			createFile(
400 				"/P/X.java",
401 				"public class X {\n" +
402 				"  void foo() {\n" +
403 				"    class Y {\n" +
404 				"      void bar() {\n" +
405 				"        class Z {\n" +
406 				"        }\n" +
407 				"      }\n" +
408 				"    }\n" +
409 				"  }\n" +
410 				"}"
411 			);
412 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
413 			assertElementDescendants(
414 				"Unexpected compilation unit contents",
415 				"X.java\n" +
416 				"  class X\n" +
417 				"    void foo()\n" +
418 				"      class Y\n" +
419 				"        void bar()\n" +
420 				"          class Z",
421 				cu);
422 		} finally {
423 			deleteFile("/P/X.java");
424 		}
425 	}
426 
427 	/*
428 	 * Local type test.
429 	 */
testLocalType4()430 	public void testLocalType4() throws CoreException {
431 		try {
432 			createFile(
433 				"/P/X.java",
434 				"public class X {\n" +
435 				"  {\n" +
436 				"      class Y {\n" +
437 				"      }\n" +
438 				"  }\n" +
439 				"  void foo() {\n" +
440 				"    class Z {\n" +
441 				"    }\n" +
442 				"  }\n" +
443 				"}"
444 			);
445 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
446 			assertElementDescendants(
447 				"Unexpected compilation unit contents",
448 				"X.java\n" +
449 				"  class X\n" +
450 				"    <initializer #1>\n" +
451 				"      class Y\n" +
452 				"    void foo()\n" +
453 				"      class Z",
454 				cu);
455 		} finally {
456 			deleteFile("/P/X.java");
457 		}
458 	}
459 
460 	/*
461 	 * Local type test.
462 	 */
testLocalType5()463 	public void testLocalType5() throws CoreException {
464 		try {
465 			createFile(
466 				"/P/X.java",
467 				"public class X {\n" +
468 				"  void foo() {\n" +
469 				"    class Z {\n" +
470 				"    }\n" +
471 				"    Z\n" +
472 				"  }\n" +
473 				"}"
474 			);
475 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
476 			assertElementDescendants(
477 				"Unexpected compilation unit contents",
478 				"X.java\n" +
479 				"  class X\n" +
480 				"    void foo()\n" +
481 				"      class Z",
482 				cu);
483 		} finally {
484 			deleteFile("/P/X.java");
485 		}
486 	}
487 
488 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=167357
testLocalType6()489 	public void testLocalType6() throws CoreException {
490 		try {
491 			createFile(
492 					"/P/X.java",
493 					"public class X {\n" +
494 					"  void foo() {\n" +
495 					"    class Y {\n" +
496 					"      {\n" +
497 					"        class Z {\n" +
498 					"        }\n" +
499 					"      }\n" +
500 					"    }\n" +
501 					"  }\n" +
502 					"}"
503 			);
504 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
505 			assertElementDescendants(
506 					"Unexpected compilation unit contents",
507 					"X.java\n" +
508 					"  class X\n" +
509 					"    void foo()\n" +
510 					"      class Y\n" +
511 					"        <initializer #1>\n" +
512 					"          class Z",
513 					cu);
514 		} finally {
515 			deleteFile("/P/X.java");
516 		}
517 	}
518 
519 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=167357
testLocalType7()520 	public void testLocalType7() throws CoreException {
521 		try {
522 			createFile(
523 					"/P/X.java",
524 					"public class X {\n" +
525 					"  void foo() {\n" +
526 					"    class Y {\n" +
527 					"      {\n" +
528 					"        class Z {\n" +
529 					"        }\n" +
530 					"      }\n" +
531 					"      String s = null;\n" +
532 					"    }\n" +
533 					"  }\n" +
534 					"}"
535 			);
536 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
537 			assertElementDescendants(
538 					"Unexpected compilation unit contents",
539 					"X.java\n" +
540 					"  class X\n" +
541 					"    void foo()\n" +
542 					"      class Y\n" +
543 					"        <initializer #1>\n" +
544 					"          class Z\n" +
545 					"        String s",
546 					cu);
547 		} finally {
548 			deleteFile("/P/X.java");
549 		}
550 	}
551 
552 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=167357
testLocalType8()553 	public void testLocalType8() throws CoreException {
554 		try {
555 			createFile(
556 					"/P/X.java",
557 					"public class X {\n" +
558 					"  void foo() {\n" +
559 					"    class Y {\n" +
560 					"      String s = null;\n" +
561 					"      {\n" +
562 					"        class Z {\n" +
563 					"        }\n" +
564 					"      }\n" +
565 					"    }\n" +
566 					"  }\n" +
567 					"}"
568 			);
569 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
570 			assertElementDescendants(
571 					"Unexpected compilation unit contents",
572 					"X.java\n" +
573 					"  class X\n" +
574 					"    void foo()\n" +
575 					"      class Y\n" +
576 					"        String s\n"+
577 					"        <initializer #1>\n" +
578 					"          class Z",
579 					cu);
580 		} finally {
581 			deleteFile("/P/X.java");
582 		}
583 	}
584 
585 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=167357
testLocalType9()586 	public void testLocalType9() throws CoreException {
587 		try {
588 			createFile(
589 					"/P/X.java",
590 					"public class X {\n" +
591 					"  {\n" +
592 					"    class Y {\n" +
593 					"      String s = null;\n" +
594 					"      {\n" +
595 					"        class Z {\n" +
596 					"        }\n" +
597 					"      }\n" +
598 					"    }\n" +
599 					"  }\n" +
600 					"}"
601 			);
602 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
603 			assertElementDescendants(
604 					"Unexpected compilation unit contents",
605 					"X.java\n" +
606 					"  class X\n" +
607 					"    <initializer #1>\n" +
608 					"      class Y\n" +
609 					"        String s\n"+
610 					"        <initializer #1>\n" +
611 					"          class Z",
612 					cu);
613 		} finally {
614 			deleteFile("/P/X.java");
615 		}
616 	}
617 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=167357
testLocalType10()618 	public void testLocalType10() throws CoreException {
619 		try {
620 			createFile(
621 					"/P/X.java",
622 					"public class X {\n" +
623 					"  void foo() {\n" +
624 					"    class Y {\n" +
625 					"      String s = null;\n" +
626 					"      {\n" +
627 					"        {" +
628 					"          class Z {\n" +
629 					"          }" +
630 					"        }\n" +
631 					"      }\n" +
632 					"    }\n" +
633 					"  }\n" +
634 					"}"
635 			);
636 			ICompilationUnit cu = getCompilationUnit("/P/X.java");
637 			assertElementDescendants(
638 					"Unexpected compilation unit contents",
639 					"X.java\n" +
640 					"  class X\n" +
641 					"    void foo()\n" +
642 					"      class Y\n" +
643 					"        String s\n"+
644 					"        <initializer #1>\n" +
645 					"          class Z",
646 					cu);
647 		} finally {
648 			deleteFile("/P/X.java");
649 		}
650 	}
651 }
652