1 /*******************************************************************************
2  * Copyright (c) 2014, 2016 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.rewrite.describing;
15 
16 import java.io.IOException;
17 
18 import junit.framework.Test;
19 
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.jdt.core.ICompilationUnit;
22 import org.eclipse.jdt.core.IJavaProject;
23 import org.eclipse.jdt.core.IPackageFragmentRoot;
24 import org.eclipse.jdt.core.JavaCore;
25 import org.eclipse.jdt.core.dom.AST;
26 import org.eclipse.jdt.core.dom.ASTParser;
27 import org.eclipse.jdt.core.dom.Annotation;
28 import org.eclipse.jdt.core.dom.Assignment;
29 import org.eclipse.jdt.core.dom.CompilationUnit;
30 import org.eclipse.jdt.core.dom.ExpressionStatement;
31 import org.eclipse.jdt.core.dom.ITypeBinding;
32 import org.eclipse.jdt.core.dom.IVariableBinding;
33 import org.eclipse.jdt.core.dom.MarkerAnnotation;
34 import org.eclipse.jdt.core.dom.MethodDeclaration;
35 import org.eclipse.jdt.core.dom.MethodInvocation;
36 import org.eclipse.jdt.core.dom.NormalAnnotation;
37 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
38 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
39 import org.eclipse.jdt.core.dom.Type;
40 import org.eclipse.jdt.core.dom.TypeDeclaration;
41 import org.eclipse.jdt.core.dom.VariableDeclaration;
42 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
43 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
44 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
45 import org.eclipse.jdt.core.tests.model.AbstractJavaModelTests;
46 import org.eclipse.jface.text.BadLocationException;
47 import org.eclipse.jface.text.Document;
48 import org.eclipse.text.edits.MalformedTreeException;
49 import org.eclipse.text.edits.TextEdit;
50 import org.osgi.service.prefs.BackingStoreException;
51 
52 
53 @SuppressWarnings("rawtypes")
54 public class ImportRewrite18Test extends AbstractJavaModelTests {
55 
56 
57 	private static final Class THIS= ImportRewrite18Test.class;
58 	private static final String PROJECT = "ImportRewrite18TestProject";
59 
60 	protected IPackageFragmentRoot sourceFolder;
61 
ImportRewrite18Test(String name)62 	public ImportRewrite18Test(String name) {
63 		super(name);
64 	}
65 
allTests()66 	public static Test allTests() {
67 		return new Suite(THIS);
68 	}
69 
suite()70 	public static Test suite() {
71 		return allTests();
72 	}
73 
74 	@Override
setUp()75 	protected void setUp() throws Exception {
76 		super.setUp();
77 
78 		IJavaProject proj= createJavaProject(PROJECT, new String[] {"src"}, new String[] {"JCL_LIB"}, "bin", "1.8");
79 		proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
80 		proj.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "4");
81 		proj.setOption(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
82 		proj.setOption(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR);
83 		proj.setOption(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
84 		proj.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
85 		proj.setOption(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE, String.valueOf(99));
86 
87 		proj.setOption(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS, String.valueOf(1));
88 
89 
90 		this.sourceFolder = getPackageFragmentRoot(PROJECT, "src");
91 
92 		waitUntilIndexesReady();
93 	}
94 	/**
95 	 * @deprecated
96 	 */
getJLS8()97 	protected static int getJLS8() {
98 		return AST.JLS8;
99 	}
100 	@Override
tearDown()101 	protected void tearDown() throws Exception {
102 		deleteProject(PROJECT);
103 		super.tearDown();
104 	}
105 
testBug417937a_since_8()106 	public void testBug417937a_since_8() throws Exception {
107 		String contents = "package pack1;\n" +
108 				"public class X{\n" +
109 				"	public void foo( pack2.pack3.@Marker B arg , A a) {}\n" +
110 				"}\n" +
111 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
112 				"@interface Marker {}\n";
113 		createFolder("/" + PROJECT + "/src/pack1");
114 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
115 		contents = "package pack1;\n" +
116 				"public class A{}\n";
117 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
118 		contents = "package pack2/pack3;\n" +
119 				"public class B {}\n";
120 		createFolder("/" + PROJECT + "/src/pack2");
121 		createFolder("/" + PROJECT + "/src/pack2/pack3");
122 		createFile("/" + PROJECT + "/src/pack2/pack3/B.java", contents);
123 
124 		ASTParser parser = ASTParser.newParser(getJLS8());
125 		parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack1/A.java"));
126 		parser.setResolveBindings(true);
127 		parser.setStatementsRecovery(true);
128 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
129 
130 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
131 		parser.setSource(cu);
132 		parser.setResolveBindings(true);
133 		parser.setStatementsRecovery(true);
134 		astRoot = (CompilationUnit) parser.createAST(null);
135 		TypeDeclaration type= (TypeDeclaration) astRoot.types().get(0);
136 		MethodDeclaration [] methods =  type.getMethods();
137 		MethodDeclaration method = methods[0];
138 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
139 		IVariableBinding binding = variable.resolveBinding();
140 		ITypeBinding typeBinding = binding.getType();
141 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
142 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
143 		rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
144 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
145 		assertEquals("@Marker B", actualType.toString());
146 		assertTrue(actualType.isSimpleType());
147 		apply(rewrite);
148 		String contentsA = "package pack1;\n" +
149 				"\n" +
150 				"import pack2.pack3.B;\n" +
151 				"\n" +
152 				"public class A{}\n";
153 		assertEqualStringIgnoreDelim(cu.getSource(), contentsA);
154 	}
155 
testBug417937b_since_8()156 	public void testBug417937b_since_8() throws Exception {
157 		String contents = "package pack1;\n" +
158 				"public class X{\n" +
159 				"	public void foo( pack2.pack3.@Marker B arg , A a) {}\n" +
160 				"}\n" +
161 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
162 				"@interface Marker {}\n";
163 		createFolder("/" + PROJECT + "/src/pack1");
164 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
165 		contents = "package pack1;\n" +
166 				"import pack3.pack4.B;\n" +
167 				"public class A{\n" +
168 				"	public void foo(B arg) {}\n" +
169 				"}\n";
170 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
171 		contents = "package pack2/pack3;\n" +
172 				"public class B {}\n";
173 		createFolder("/" + PROJECT + "/src/pack2");
174 		createFolder("/" + PROJECT + "/src/pack2/pack3");
175 		createFile("/" + PROJECT + "/src/pack2/pack3/B.java", contents);
176 		contents = "package pack3/pack4;\n" +
177 				"public class B {}\n";
178 		createFolder("/" + PROJECT + "/src/pack3");
179 		createFolder("/" + PROJECT + "/src/pack3/pack4");
180 		createFile("/" + PROJECT + "/src/pack3/pack4/B.java", contents);
181 
182 		ASTParser parser = ASTParser.newParser(getJLS8());
183 		parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack1/A.java"));
184 		parser.setResolveBindings(true);
185 		parser.setStatementsRecovery(true);
186 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
187 
188 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
189 		parser.setSource(cu);
190 		parser.setResolveBindings(true);
191 		parser.setStatementsRecovery(true);
192 		astRoot = (CompilationUnit) parser.createAST(null);
193 		TypeDeclaration type= (TypeDeclaration) astRoot.types().get(0);
194 		MethodDeclaration [] methods =  type.getMethods();
195 		MethodDeclaration method = methods[0];
196 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
197 		IVariableBinding binding = variable.resolveBinding();
198 		ITypeBinding typeBinding = binding.getType();
199 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
200 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
201 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
202 		assertEquals("pack2.pack3.@Marker B", actualType.toString());
203 		assertTrue(actualType.isNameQualifiedType());
204 		apply(rewrite);
205 		String contentsA = "package pack1;\n" +
206 				"import pack3.pack4.B;\n" +
207 				"public class A{\n" +
208 				"	public void foo(B arg) {}\n" +
209 				"}\n";
210 		assertEqualStringIgnoreDelim(cu.getSource(), contentsA);
211 	}
212 
testBug417937b1_since_8()213 	public void testBug417937b1_since_8() throws Exception {
214 		String contents = "package pack1;\n" +
215 				"public class X{\n" +
216 				"	public void foo( pack2.pack3.@Marker B @Marker [] arg , A a) {}\n" +
217 				"}\n" +
218 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
219 				"@interface Marker {}\n";
220 		createFolder("/" + PROJECT + "/src/pack1");
221 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
222 		contents = "package pack1;\n" +
223 				"import pack3.pack4.B;\n" +
224 				"public class A{\n" +
225 				"	public void foo(B arg) {}\n" +
226 				"}\n";
227 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
228 		contents = "package pack2/pack3;\n" +
229 				"public class B {}\n";
230 		createFolder("/" + PROJECT + "/src/pack2");
231 		createFolder("/" + PROJECT + "/src/pack2/pack3");
232 		createFile("/" + PROJECT + "/src/pack2/pack3/B.java", contents);
233 		contents = "package pack3/pack4;\n" +
234 				"public class B {}\n";
235 		createFolder("/" + PROJECT + "/src/pack3");
236 		createFolder("/" + PROJECT + "/src/pack3/pack4");
237 		createFile("/" + PROJECT + "/src/pack3/pack4/B.java", contents);
238 
239 		ASTParser parser = ASTParser.newParser(getJLS8());
240 		parser.setSource(getCompilationUnit("/" + PROJECT + "/src/pack1/A.java"));
241 		parser.setResolveBindings(true);
242 		parser.setStatementsRecovery(true);
243 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
244 
245 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
246 		parser.setSource(cu);
247 		parser.setResolveBindings(true);
248 		parser.setStatementsRecovery(true);
249 		astRoot = (CompilationUnit) parser.createAST(null);
250 		TypeDeclaration type= (TypeDeclaration) astRoot.types().get(0);
251 		MethodDeclaration [] methods =  type.getMethods();
252 		MethodDeclaration method = methods[0];
253 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
254 		IVariableBinding binding = variable.resolveBinding();
255 		ITypeBinding typeBinding = binding.getType();
256 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
257 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
258 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
259 		assertEquals("pack2.pack3.@Marker B @Marker []", actualType.toString());
260 		assertTrue(actualType.isArrayType());
261 		apply(rewrite);
262 		String contentsA = "package pack1;\n" +
263 				"import pack3.pack4.B;\n" +
264 				"public class A{\n" +
265 				"	public void foo(B arg) {}\n" +
266 				"}\n";
267 		assertEqualStringIgnoreDelim(cu.getSource(), contentsA);
268 	}
269 
runTest417937candGetType(int i)270 	private Type runTest417937candGetType(int i) throws Exception {
271 		String contents = "package pack1;\n" +
272 				"public class X{\n" +
273 				this.bug417937cTestInput[i][0] + "\n" +
274 				"}\n" +
275 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
276 				"@interface Marker {}\n" +
277 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
278 				"@interface Marker2 {}\n" +
279 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
280 				"@interface Annot1 {\n" +
281 				"	int value1() default 1;\n" +
282 				"	int value2();\n" +
283 				"}\n";
284 		createFolder("/" + PROJECT + "/src/pack1");
285 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
286 		contents = "package pack1;\n" +
287 				"public class A{}\n";
288 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
289 		contents = "package pack2;\n" +
290 				"public class B1 {\n" +
291 				"	public class B2 {\n" +
292 				"		public class B3 {\n" +
293 				"			\n" +
294 				"		}\n" +
295 				"	}\n" +
296 				"}\n";
297 		createFolder("/" + PROJECT + "/src/pack2");
298 		createFile("/" + PROJECT + "/src/pack2/B1.java", contents);
299 
300 		ASTParser parser = ASTParser.newParser(getJLS8());
301 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
302 		parser.setSource(cu);
303 		parser.setResolveBindings(true);
304 		parser.setStatementsRecovery(true);
305 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
306 		TypeDeclaration typeDeclaration = (TypeDeclaration) astRoot.types().get(0);
307 		MethodDeclaration [] methods =  typeDeclaration.getMethods();
308 		MethodDeclaration method = methods[0];
309 
310 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
311 		IVariableBinding variableBinding = variable.resolveBinding();
312 		ITypeBinding typeBinding = variableBinding.getType();
313 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
314 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
315 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
316 		apply(rewrite);
317 		String contentsA = "package pack1;\n" +
318 				"\n" +
319 				"import " + this.bug417937cTestInput[i][1] + ";\n" +
320 				"\n" +
321 				"public class A{}\n";
322 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
323 		assertEqualStringIgnoreDelim(cu.getSource(), contentsA);
324 
325 		return actualType;
326 	}
327 
328 	String[][] bug417937cTestInput = {
329 			{"public void foo000( pack2.@Marker B1.@Marker B2.@Marker B3 arg, A a) {}", "pack2.B1", "@Marker B1.@Marker B2.@Marker B3"},
330 			{"public void foo001( pack2.@Marker @Marker2 B1.@Marker B2.B3 arg, A a) {}", "pack2.B1", "@Marker @Marker2 B1.@Marker B2.B3"},
331 			{"public void foo002( pack2.B1.@Marker B2.B3 arg, @Marker int i, A a){}", "pack2.B1.B2", "@Marker B2.B3"},
332 			{"public void foo003( pack2.B1.B2.@Marker B3 arg, A a) {}", "pack2.B1.B2.B3", "@Marker B3"},
333 			{"public void foo004( pack2.B1.B2.@Annot1(value2=2) B3 arg, A a) {}", "pack2.B1.B2.B3", "@Annot1(value2=2) B3"},
334 			{"public void foo005( pack2.B1.B2.@Annot1(value2=2,value1=0) B3 arg, A a) {}", "pack2.B1.B2.B3", "@Annot1(value2=2,value1=0) B3"},
335 			{"public void foo006( pack2.B1.B2.B3 arg, A a) {}", "pack2.B1.B2.B3", "B3"},
336 	};
337 
bug417937c_runi_since_8(int i)338 	private Type bug417937c_runi_since_8(int i) throws Exception {
339 		Type actualType = runTest417937candGetType(i);
340 		assertEquals(this.bug417937cTestInput[i][2], actualType.toString());
341 		return actualType;
342 	}
343 
testBug417937c0_since_8()344 	public void testBug417937c0_since_8() throws Exception {
345 		Type type = bug417937c_runi_since_8(0);
346 		assertTrue(type.isQualifiedType());
347 	}
testBug417937c1_since_8()348 	public void testBug417937c1_since_8() throws Exception {
349 		Type type = bug417937c_runi_since_8(1);
350 		assertTrue(type.isQualifiedType());
351 	}
testBug417937c2_since_8()352 	public void testBug417937c2_since_8() throws Exception {
353 		Type type = bug417937c_runi_since_8(2);
354 		assertTrue(type.isQualifiedType());
355 	}
testBug417937c3_since_8()356 	public void testBug417937c3_since_8() throws Exception {
357 		Type type = bug417937c_runi_since_8(3);
358 		assertTrue(type.isSimpleType());
359 	}
testBug417937c4_since_8()360 	public void testBug417937c4_since_8() throws Exception {
361 		Type type = bug417937c_runi_since_8(4);
362 		assertTrue(type.isSimpleType());
363 	}
testBug417937c5_since_8()364 	public void testBug417937c5_since_8() throws Exception {
365 		Type type = bug417937c_runi_since_8(5);
366 		assertTrue(type.isSimpleType());
367 	}
testBug417937c6_since_8()368 	public void testBug417937c6_since_8() throws Exception {
369 		Type type = bug417937c_runi_since_8(6);
370 		assertTrue(type.isSimpleType());
371 	}
372 
testBug417937d001_since_8()373 	public void testBug417937d001_since_8() throws Exception {
374 		String contents = "package pack1;\n" +
375 				"public class X{\n" +
376 				"public void foo000( pack3.C1<pack2.B1>.C2<pack2.B1.B2>.C3<pack2.B1> arg, A a) {}\n" +
377 				"}\n";
378 		createFolder("/" + PROJECT + "/src/pack1");
379 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
380 		contents = "package pack1;\n" +
381 				"public class A{}\n";
382 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
383 		contents = "package pack2;\n" +
384 				"public class B1 {\n" +
385 				"	public class B2 {\n" +
386 				"		public class B3 {\n" +
387 				"			\n" +
388 				"		}\n" +
389 				"	}\n" +
390 				"}\n";
391 		createFolder("/" + PROJECT + "/src/pack2");
392 		createFile("/" + PROJECT + "/src/pack2/B1.java", contents);
393 		contents = "package pack3;\n" +
394 				"public class C1 <T> {\n" +
395 				"	public class C2 <P>{\n" +
396 				"		public class C3 <Q> {\n" +
397 				"			\n" +
398 				"		}\n" +
399 				"	}\n" +
400 				"}\n" +
401 		createFolder("/" + PROJECT + "/src/pack3");
402 		createFile("/" + PROJECT + "/src/pack3/C1.java", contents);
403 		contents = "package pack4;\n" +
404 				"public class D1 {\n" +
405 				"	public class D2 <T>{\n" +
406 				"		public class D3 <S> {\n" +
407 				"			\n" +
408 				"		}\n" +
409 				"	}\n" +
410 				"}\n" +
411 		createFolder("/" + PROJECT + "/src/pack4");
412 		createFile("/" + PROJECT + "/src/pack4/D1.java", contents);
413 
414 		ASTParser parser = ASTParser.newParser(getJLS8());
415 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
416 		parser.setSource(cu);
417 		parser.setResolveBindings(true);
418 		parser.setStatementsRecovery(true);
419 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
420 		TypeDeclaration typeDeclaration = (TypeDeclaration) astRoot.types().get(0);
421 		MethodDeclaration [] methods =  typeDeclaration.getMethods();
422 		MethodDeclaration method = methods[0];
423 
424 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
425 		IVariableBinding variableBinding = variable.resolveBinding();
426 		ITypeBinding typeBinding = variableBinding.getType();
427 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
428 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
429 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
430 		apply(rewrite);
431 		String contentsA = "package pack1;\n" +
432 				"\n" +
433 				"import pack2.B1;\n" +
434 				"import pack2.B1.B2;\n" +
435 				"import pack3.C1;\n" +
436 				"\n" +
437 				"public class A{}\n";
438 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
439 		assertEqualStringIgnoreDelim(cu.getSource(), contentsA);
440 		assertEquals("C1<B1>.C2<B2>.C3<B1>", actualType.toString());
441 		assertTrue(actualType.isParameterizedType());
442 	}
443 
testBug417937d002_since_8()444 	public void testBug417937d002_since_8() throws Exception {
445 		String contents = "package pack1;\n" +
446 				"public class X{\n" +
447 				"public void foo001( pack4.D1.D2<pack2.B1>.D3<pack2.B1> arg, A a) {}\n" +
448 				"}\n";
449 		createFolder("/" + PROJECT + "/src/pack1");
450 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
451 		contents = "package pack1;\n" +
452 				"public class A{}\n";
453 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
454 		contents = "package pack2;\n" +
455 				"public class B1 {\n" +
456 				"	public class B2 {\n" +
457 				"		public class B3 {\n" +
458 				"			\n" +
459 				"		}\n" +
460 				"	}\n" +
461 				"}\n";
462 		createFolder("/" + PROJECT + "/src/pack2");
463 		createFile("/" + PROJECT + "/src/pack2/B1.java", contents);
464 		contents = "package pack3;\n" +
465 				"public class C1 <T> {\n" +
466 				"	public class C2 <P>{\n" +
467 				"		public class C3 <Q> {\n" +
468 				"			\n" +
469 				"		}\n" +
470 				"	}\n" +
471 				"}\n" +
472 		createFolder("/" + PROJECT + "/src/pack3");
473 		createFile("/" + PROJECT + "/src/pack3/C1.java", contents);
474 		contents = "package pack4;\n" +
475 				"public class D1 {\n" +
476 				"	public class D2 <T>{\n" +
477 				"		public class D3 <S> {\n" +
478 				"			\n" +
479 				"		}\n" +
480 				"	}\n" +
481 				"}\n" +
482 		createFolder("/" + PROJECT + "/src/pack4");
483 		createFile("/" + PROJECT + "/src/pack4/D1.java", contents);
484 
485 		ASTParser parser = ASTParser.newParser(getJLS8());
486 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
487 		parser.setSource(cu);
488 		parser.setResolveBindings(true);
489 		parser.setStatementsRecovery(true);
490 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
491 		TypeDeclaration typeDeclaration = (TypeDeclaration) astRoot.types().get(0);
492 		MethodDeclaration [] methods =  typeDeclaration.getMethods();
493 		MethodDeclaration method = methods[0];
494 
495 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
496 		IVariableBinding variableBinding = variable.resolveBinding();
497 		ITypeBinding typeBinding = variableBinding.getType();
498 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
499 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
500 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
501 		apply(rewrite);
502 		String contentsA = "package pack1;\n" +
503 				"\n" +
504 				"import pack2.B1;\n" +
505 				"import pack4.D1.D2;\n" +
506 				"\n" +
507 				"public class A{}\n";
508 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
509 		assertEqualStringIgnoreDelim(cu.getSource(), contentsA);
510 		assertEquals("D2<B1>.D3<B1>", actualType.toString());
511 		assertTrue(actualType.isParameterizedType());
512 	}
513 
testBug417937e_since_8()514 	public void testBug417937e_since_8() throws Exception {
515 		String contents = "package pack1;\n" +
516 				"import pack2.B1;\n" +
517 				"public class X{\n" +
518 				"    public void foo001(B1<C1>.B2<C1>.@Annot(true) B3<C1> arg, A a) {}\n" +
519 				"}\n" +
520 				"class C1{}\n" +
521 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
522 				"@interface Annot {\n	boolean value() default false;\n}\n" +
523 				"}\n";
524 		createFolder("/" + PROJECT + "/src/pack1");
525 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
526 		contents = "package pack1;\n" +
527 				"public class A{}\n";
528 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
529 		contents = "package pack2;\n" +
530 				"public class B1<T> {\n" +
531 				"	public class B2<P> {\n" +
532 				"		public class B3<Q> {\n" +
533 				"		}\n" +
534 				"	}\n" +
535 				"}\n";
536 		createFolder("/" + PROJECT + "/src/pack2");
537 		createFile("/" + PROJECT + "/src/pack2/B1.java", contents);
538 
539 		ASTParser parser = ASTParser.newParser(getJLS8());
540 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
541 		parser.setSource(cu);
542 		parser.setResolveBindings(true);
543 		parser.setStatementsRecovery(true);
544 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
545 		TypeDeclaration typeDeclaration = (TypeDeclaration) astRoot.types().get(0);
546 		MethodDeclaration [] methods =  typeDeclaration.getMethods();
547 		MethodDeclaration method = methods[0];
548 
549 		VariableDeclaration variable= (VariableDeclaration) method.parameters().get(0);
550 		IVariableBinding variableBinding = variable.resolveBinding();
551 		ITypeBinding typeBinding = variableBinding.getType();
552 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
553 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
554 		Type actualType = rewrite.addImport(typeBinding, astRoot.getAST());
555 		assertTrue(actualType.isParameterizedType());
556 	}
557 
runTest426094andGetType(int i, boolean testNullImportRewriteContext)558 	private Type runTest426094andGetType(int i, boolean testNullImportRewriteContext) throws Exception {
559 		String contents = "package pack1;\n" +
560 				"public class X{\n" +
561 				this.bug426094TestInput[i][0] + "\n" +
562 				"}\n" +
563 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
564 				"@interface Marker {}\n" +
565 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
566 				"@interface Marker1 {}\n" +
567 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
568 				"@interface Marker2 {}\n" +
569 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
570 				"@interface Marker3 {}\n" +
571 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
572 				"@interface Annot {\n" +
573 				"	boolean value() default false;\n" +
574 				"	int value2();\n" +
575 				"}\n" +
576 				"@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
577 				"@interface Annot2 {\n" +
578 				"	int[] value() default {1,2};\n" +
579 				"}\n";
580 		createFolder("/" + PROJECT + "/src/pack1");
581 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
582 		contents = "package pack1;\n" +
583 				"public class A{}\n";
584 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
585 		contents = "package pack2;\n" +
586 				"public class B {\n" +
587 				"	public class C {\n" +
588 				"	}\n" +
589 				"}\n";
590 		createFolder("/" + PROJECT + "/src/pack2");
591 		createFile("/" + PROJECT + "/src/pack2/B.java", contents);
592 
593 		ASTParser parser = ASTParser.newParser(getJLS8());
594 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
595 		parser.setSource(cu);
596 		parser.setResolveBindings(true);
597 		parser.setStatementsRecovery(true);
598 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
599 		TypeDeclaration typeDeclaration = (TypeDeclaration) astRoot.types().get(0);
600 		MethodDeclaration [] methods =  typeDeclaration.getMethods();
601 		MethodDeclaration method = methods[0];
602 
603 		VariableDeclaration variable = (VariableDeclaration) method.parameters().get(0);
604 		IVariableBinding variableBinding = variable.resolveBinding();
605 		ITypeBinding typeBinding = variableBinding.getType();
606 		cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
607 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
608 		Type actualType;
609 		if(testNullImportRewriteContext) {
610 			actualType = rewrite.addImport(typeBinding, astRoot.getAST(), null, TypeLocation.UNKNOWN);
611 		} else {
612 			actualType = rewrite.addImport(typeBinding, astRoot.getAST());
613 		}
614 		return actualType;
615 	}
616 
617 	String[][] bug426094TestInput = {
618 			{"public void foo001(pack2.@Marker B @Marker [] arg,  A a) {}", "@Marker B @Marker []"},
619 			{"public void foo002(pack2.@Marker B.C @Marker[] arg,  A a) {}", "@Marker B.C @Marker []"},
620 			{"public void foo003(pack2.@Marker B @Marker @Marker1[] @Marker1 @Marker2 []arg,  A a) {}", "@Marker B @Marker @Marker1 [] @Marker1 @Marker2 []"},
621 			{"public void foo004(pack2.@Marker B @Marker @Marker1 @Annot(value=true, value2=1) [] @Annot(value=true, value2=1) []arg,  A a) {}", "@Marker B @Marker @Marker1 @Annot(value=true,value2=1) [] @Annot(value=true,value2=1) []"},
622 			{"public void foo005(pack2.@Marker B @Marker @Marker1 @Annot2({1,2})[] @Annot2({1,2}) []arg,  A a) {}", "@Marker B @Marker @Marker1 @Annot2({1,2}) [] @Annot2({1,2}) []"},
623 			{"public void foo0011(pack2.B @Marker[] arg,  A a) {}", "B @Marker []"},
624 			{"public void foo0021(pack2.B.C @Marker[] arg,  A a) {}", "C @Marker []"},
625 			{"public void foo0031(pack2.B @Marker @Marker1[] @Marker1 @Marker2 []arg,  A a) {}", "B @Marker @Marker1 [] @Marker1 @Marker2 []"},
626 			{"public void foo0041(pack2.B @Marker @Marker1 @Annot(value=true, value2=1) [] @Annot(value=true,value2=1) []arg,  A a) {}", "B @Marker @Marker1 @Annot(value=true,value2=1) [] @Annot(value=true,value2=1) []"},
627 			{"public void foo0051(pack2.B @Marker @Marker1 @Annot2(value = {1,2})[] @Annot2({1,2}) []arg,  A a) {}", "B @Marker @Marker1 @Annot2({1,2}) [] @Annot2({1,2}) []"},
628 			{"public void foo000(pack2.B[] arg,  A a) {}", "B[]"},
629 	};
630 
bug426094_runi_since_8(int i)631 	private Type bug426094_runi_since_8(int i) throws Exception {
632 		Type actualType = runTest426094andGetType(i, false);
633 		assertEquals(this.bug426094TestInput[i][1], actualType.toString());
634 		return actualType;
635 	}
636 
testBug4260940_since_8()637 	public void testBug4260940_since_8() throws Exception {
638 		bug426094_runi_since_8(0);
639 	}
testBug4260941_since_8()640 	public void testBug4260941_since_8() throws Exception {
641 		bug426094_runi_since_8(1);
642 	}
testBug4260942_since_8()643 	public void testBug4260942_since_8() throws Exception {
644 		bug426094_runi_since_8(2);
645 	}
testBug4260943_since_8()646 	public void testBug4260943_since_8() throws Exception {
647 		bug426094_runi_since_8(3);
648 	}
testBug4260944_since_8()649 	public void testBug4260944_since_8() throws Exception {
650 		bug426094_runi_since_8(4);
651 	}
testBug4260945_since_8()652 	public void testBug4260945_since_8() throws Exception {
653 		bug426094_runi_since_8(5);
654 	}
testBug4260946_since_8()655 	public void testBug4260946_since_8() throws Exception {
656 		bug426094_runi_since_8(6);
657 	}
testBug4260947_since_8()658 	public void testBug4260947_since_8() throws Exception {
659 		bug426094_runi_since_8(7);
660 	}
testBug4260948_since_8()661 	public void testBug4260948_since_8() throws Exception {
662 		bug426094_runi_since_8(8);
663 	}
testBug4260949_since_8()664 	public void testBug4260949_since_8() throws Exception {
665 		bug426094_runi_since_8(9);
666 	}
testBug42609410_since_8()667 	public void testBug42609410_since_8() throws Exception {
668 		bug426094_runi_since_8(10);
669 	}
670 
testBug426510a()671 	public void testBug426510a() throws Exception {
672 		String contents = "package pack1;\n" +
673 				"public class X{\n" +
674 				"	public void foo001(@pack2.Marker Object o2, A arg) {}\n" +
675 				"	public void foo002(@pack2.Annot2({1,2}) Object o2, A arg) {}\n" +
676 				"	public void foo003(@pack2.Annot1(value = true, value2 = 1) Object o2, A arg) {}\n" +
677 				"}\n";
678 		createFolder("/" + PROJECT + "/src/pack1");
679 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
680 		contents = "package pack1;\n" +
681 				"public class A{}\n";
682 		createFile("/" + PROJECT + "/src/pack1/A.java", contents);
683 		contents = "package pack2;\n" +
684 				"import java.lang.annotation.*;\n" +
685 				"@Target(ElementType.TYPE_USE)\n" +
686 				"public @interface Marker {}";
687 		createFolder("/" + PROJECT + "/src/pack2");
688 		createFile("/" + PROJECT + "/src/pack2/Marker.java", contents);
689 		contents = "package pack2;\n" +
690 				"import java.lang.annotation.*;\n" +
691 				"@Target(ElementType.TYPE_USE)\n" +
692 				"public @interface Annot1 {\n" +
693 				"	boolean value() default false;\n" +
694 				"	int value2();\n" +
695 				"}";
696 		createFile("/" + PROJECT + "/src/pack2/Annot1.java", contents);
697 		contents = "package pack2;\n" +
698 				"import java.lang.annotation.*;\n" +
699 				"@Target(ElementType.TYPE_USE)\n" +
700 				"public @interface Annot2 {\n" +
701 				"	int[] value() default {1,2};\n" +
702 				"}";
703 		createFile("/" + PROJECT + "/src/pack2/Annot2.java", contents);
704 
705 		ASTParser parser = ASTParser.newParser(getJLS8());
706 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
707 		parser.setSource(cu);
708 		parser.setResolveBindings(true);
709 		parser.setStatementsRecovery(true);
710 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
711 		TypeDeclaration typeDeclaration = (TypeDeclaration) astRoot.types().get(0);
712 		MethodDeclaration [] methods =  typeDeclaration.getMethods();
713 		int methodCount = 0;
714 
715 		{
716 			MethodDeclaration method = methods[methodCount++];
717 			cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
718 			ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
719 			SingleVariableDeclaration variable = (SingleVariableDeclaration) method.parameters().get(0);
720 			MarkerAnnotation markerAnnotation = (MarkerAnnotation) variable.modifiers().get(0);
721 			Annotation annotation = rewrite.addAnnotation(markerAnnotation.resolveAnnotationBinding(), astRoot.getAST(), null);
722 			assertTrue(annotation.isMarkerAnnotation());
723 			assertEquals("@Marker", annotation.toString());
724 
725 			apply(rewrite);
726 			contents = "package pack1;\n" +
727 					"\n" +
728 					"import pack2.Marker;\n" +
729 					"\n" +
730 					"public class A{}\n";
731 			cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
732 			assertEqualStringIgnoreDelim(cu.getSource(), contents);
733 		}
734 		{
735 			MethodDeclaration method = methods[methodCount++];
736 			cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
737 			ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
738 			SingleVariableDeclaration variable = (SingleVariableDeclaration) method.parameters().get(0);
739 			SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) variable.modifiers().get(0);
740 			Annotation annotation = rewrite.addAnnotation(singleMemberAnnotation.resolveAnnotationBinding(), astRoot.getAST(), null);
741 			assertTrue(annotation.isSingleMemberAnnotation());
742 			assertEquals("@Annot2({1,2})", annotation.toString());
743 
744 			apply(rewrite);
745 			contents = "package pack1;\n" +
746 					"\n" +
747 					"import pack2.Annot2;\n" +
748 					"\n" +
749 					"public class A{}\n";
750 			cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
751 			assertEqualStringIgnoreDelim(cu.getSource(), contents);
752 		}
753 		{
754 			MethodDeclaration method = methods[methodCount++];
755 			cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
756 			ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
757 			SingleVariableDeclaration variable = (SingleVariableDeclaration) method.parameters().get(0);
758 			NormalAnnotation normalAnnotation = (NormalAnnotation) variable.modifiers().get(0);
759 			Annotation annotation = rewrite.addAnnotation(normalAnnotation.resolveAnnotationBinding(), astRoot.getAST(), null);
760 			assertTrue(annotation.isNormalAnnotation());
761 			assertEquals("@Annot1(value=true,value2=1)", annotation.toString());
762 
763 			apply(rewrite);
764 			contents = "package pack1;\n" +
765 					"\n" +
766 					"import pack2.Annot1;\n" +
767 					"\n" +
768 					"public class A{}\n";
769 			cu = getCompilationUnit("/" + PROJECT + "/src/pack1/A.java");
770 			assertEqualStringIgnoreDelim(cu.getSource(), contents);
771 		}
772 	}
773 
testBug474270_since_8()774 	public void testBug474270_since_8() throws Exception {
775 		String contents =
776 				"package pack1;\n" +
777 				"import java.util.Comparator;\n" +
778 				"interface Comparator<T> {\n" +
779 				"    int compare(T o1, T o2);\n" +
780 				"    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {\n" +
781 				"		return null;\n" +
782 				"    }\n" +
783 				"}\n" +
784 				"public class X {\n" +
785 				"    Comparator mComparator1 = null;\n" +
786 				"	 Comparator mComparator2 = (pObj1, pObj2) -> mComparator1.compare(pObj1, pObj2);\n" +
787 				"    X() {mComparator1 = Comparator.naturalOrder();}\n" +
788 				"}\n";
789 		createFolder("/" + PROJECT + "/src/pack1");
790 		createFile("/" + PROJECT + "/src/pack1/X.java", contents);
791 
792 		ICompilationUnit cu = getCompilationUnit("/" + PROJECT + "/src/pack1/X.java");
793 		ASTParser parser = ASTParser.newParser(getJLS8());
794 		parser.setSource(cu);
795 		parser.setResolveBindings(true);
796 		parser.setStatementsRecovery(true);
797 		CompilationUnit astRoot = (CompilationUnit) parser.createAST(null);
798 		TypeDeclaration type= (TypeDeclaration) astRoot.types().get(1);
799 		MethodDeclaration [] methods =  type.getMethods();
800 		MethodDeclaration method = methods[0];
801 		ExpressionStatement stmt =  (ExpressionStatement) method.getBody().statements().get(0);
802 		Assignment assignment = (Assignment) stmt.getExpression();
803 		MethodInvocation invocation = (MethodInvocation) assignment.getRightHandSide();
804 		ITypeBinding typeBinding = invocation.resolveTypeBinding();
805 		typeBinding = typeBinding.getDeclaredMethods()[0].getParameterTypes()[0];
806 		contents = "package pack2;\n" +
807 				"\n" +
808 				"public class A{}\n";
809 		createFolder("/" + PROJECT + "/src/pack2");
810 		createFile("/" + PROJECT + "/src/pack2/A.java", contents);
811 		cu = getCompilationUnit("/" + PROJECT + "/src/pack2/A.java");
812 		ImportRewrite rewrite = newImportsRewrite(cu, new String[0], 99, 99, true);
813 		rewrite.addImport(typeBinding, astRoot.getAST());
814 	}
815 
assertEqualStringIgnoreDelim(String actual, String expected)816 	private void assertEqualStringIgnoreDelim(String actual, String expected) throws IOException {
817 		StringAsserts.assertEqualStringIgnoreDelim(actual, expected);
818 	}
819 
newImportsRewrite(ICompilationUnit cu, String[] order, int normalThreshold, int staticThreshold, boolean restoreExistingImports)820 	private ImportRewrite newImportsRewrite(ICompilationUnit cu, String[] order, int normalThreshold, int staticThreshold, boolean restoreExistingImports) throws CoreException, BackingStoreException {
821 		ImportRewrite rewrite= ImportRewrite.create(cu, restoreExistingImports);
822 		rewrite.setImportOrder(order);
823 		rewrite.setOnDemandImportThreshold(normalThreshold);
824 		rewrite.setStaticOnDemandImportThreshold(staticThreshold);
825 		return rewrite;
826 	}
827 
newImportsRewrite(CompilationUnit cu, String[] order, int normalThreshold, int staticThreshold, boolean restoreExistingImports)828 	protected ImportRewrite newImportsRewrite(CompilationUnit cu, String[] order, int normalThreshold, int staticThreshold, boolean restoreExistingImports) {
829 		ImportRewrite rewrite= ImportRewrite.create(cu, restoreExistingImports);
830 		rewrite.setImportOrder(order);
831 		rewrite.setOnDemandImportThreshold(normalThreshold);
832 		rewrite.setStaticOnDemandImportThreshold(staticThreshold);
833 		return rewrite;
834 	}
835 
apply(ImportRewrite rewrite)836 	private void apply(ImportRewrite rewrite) throws CoreException, MalformedTreeException, BadLocationException {
837 		TextEdit edit= rewrite.rewriteImports(null);
838 
839 		// not the efficient way!
840 		ICompilationUnit compilationUnit= rewrite.getCompilationUnit();
841 		Document document= new Document(compilationUnit.getSource());
842 		edit.apply(document);
843 		compilationUnit.getBuffer().setContents(document.get());
844 	}
845 
testBug513869()846 	public void testBug513869() throws Exception {
847 		Type actualType = runTest426094andGetType(0, true);
848 		assertEquals(this.bug426094TestInput[0][1], actualType.toString());
849 	}
850 }
851