1 /*******************************************************************************
2  * Copyright (c) 2000, 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.ui.tests.refactoring.typeconstraints;
15 
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.assertTrue;
18 
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22 
23 import org.junit.Rule;
24 import org.junit.Test;
25 
26 import org.eclipse.jdt.core.ICompilationUnit;
27 import org.eclipse.jdt.core.IPackageFragment;
28 import org.eclipse.jdt.core.dom.CompilationUnit;
29 
30 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ASTCreator;
31 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintCollector;
32 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintOperator;
33 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariable;
34 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ConstraintVariableFactory;
35 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.FullConstraintCreator;
36 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.ITypeConstraint;
37 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.TypeConstraintFactory;
38 
39 import org.eclipse.jdt.ui.tests.refactoring.GenericRefactoringTest;
40 import org.eclipse.jdt.ui.tests.refactoring.rules.RefactoringTestSetup;
41 
42 public class TypeConstraintTests extends GenericRefactoringTest {
43 	private static final String PATH= "TypeConstraints/";
44 
45 	@Override
getRefactoringPath()46 	protected String getRefactoringPath() {
47 		return PATH;
48 	}
49 
50 	@Rule
51 	public RefactoringTestSetup rts= new RefactoringTestSetup();
52 
getSimpleTestFileName()53 	private String getSimpleTestFileName(){
54 		return "A_" + tn.getMethodName() + ".java";
55 	}
56 
getTestFileName()57 	private String getTestFileName(){
58 		return TEST_PATH_PREFIX + getRefactoringPath() + getSimpleTestFileName();
59 	}
60 
createCUfromTestFile(IPackageFragment pack)61 	private ICompilationUnit createCUfromTestFile(IPackageFragment pack) throws Exception {
62 		return createCU(pack, getSimpleTestFileName(), getFileContents(getTestFileName()));
63 	}
64 
getCuNode()65 	private CompilationUnit getCuNode() throws Exception {
66 		ICompilationUnit cu= createCUfromTestFile(getPackageP());
67 		return ASTCreator.createAST(cu, null);
68 	}
69 
numberHelper(int number)70 	private void numberHelper(int number) throws Exception {
71 		CompilationUnit cuNode= getCuNode();
72 		ConstraintCollector collector= getCollector();
73 		cuNode.accept(collector);
74 		ITypeConstraint[] constraints= collector.getConstraints();
75 		assertEquals(Arrays.asList(constraints).toString(), number, constraints.length);
76 	}
77 
78 	@Test
testNumber0()79 	public void testNumber0() throws Exception{
80 		numberHelper(2);
81 	}
82 
83 	@Test
testNumber1()84 	public void testNumber1() throws Exception{
85 		numberHelper(3);
86 	}
87 
88 	@Test
testNumber2()89 	public void testNumber2() throws Exception{
90 		numberHelper(10);
91 	}
92 
getCollector()93 	private ConstraintCollector getCollector() {
94 		TypeConstraintFactory factory = new TypeConstraintFactory(){
95 			@Override
96 			public boolean filter(ConstraintVariable v1, ConstraintVariable v2, ConstraintOperator o){
97 				return false;
98 			}
99 		};
100 		ConstraintCollector collector= new ConstraintCollector(new FullConstraintCreator(new ConstraintVariableFactory(), factory));
101 		return collector;
102 	}
103 
allToStrings(Object[] elements)104 	private static List<String> allToStrings(Object[] elements) {
105 		String[] strings= new String[elements.length];
106 		for (int i= 0; i < elements.length; i++) {
107 			strings[i]= elements[i].toString();
108 		}
109 		return new ArrayList<>(Arrays.asList(strings));//want to be able to remove stuff from it
110 	}
111 
testConstraints(String[] constraintStrings)112 	private void testConstraints(String[] constraintStrings) throws Exception{
113 		CompilationUnit cuNode= getCuNode();
114 		ConstraintCollector collector= getCollector();
115 		cuNode.accept(collector);
116 		ITypeConstraint[] constraints= collector.getConstraints();
117 
118 		List<String> externals= allToStrings(constraints);
119 		assertEquals("length", constraintStrings.length, constraints.length);
120 		for (String constraintString : constraintStrings) {
121 			assertTrue("missing constraint:" + constraintString, externals.remove(constraintString));
122 		}
123 	}
124 
125 	@Test
testConstraints0()126 	public void testConstraints0() throws Exception{
127 		String[] strings= {"[null] <= [a0]", "[a0] <= [a1]", "[a0] =^= A", "[a1] =^= A", "Decl(A:f()) =^= p.A"};
128 		testConstraints(strings);
129 	}
130 
131 	@Test
testConstraints1()132 	public void testConstraints1() throws Exception{
133 		String[] strings= {"[null] <= [a0]", "[a0] == [a1]", "[a0] =^= A", "[a1] =^= A", "Decl(A:a0) =^= p.A", "Decl(A:a1) =^= p.A"};
134 		testConstraints(strings);
135 	}
136 
137 	@Test
testConstraints2()138 	public void testConstraints2() throws Exception{
139 		String[] strings= {"[null] <= [a0]", "[(A)a0] =^= A", "[(A)a0] <= [a1]", "[a0] <= [(A)a0] or [(A)a0] <= [a0]", "[a0] =^= A", "[a1] =^= A", "Decl(A:f()) =^= p.A"};
140 		testConstraints(strings);
141 	}
142 
143 	@Test
testConstraints3()144 	public void testConstraints3() throws Exception{
145 		String[] strings= {"[null] <= [a]", "[null] <= [b]", "[a] == [b]", "[a] =^= A", "[b] =^= A", "Decl(A:f()) =^= p.A"};
146 		testConstraints(strings);
147 	}
148 
149 	@Test
testConstraints4()150 	public void testConstraints4() throws Exception{
151 		String[] strings= {"[as0] =^= A[]", "[a0] <= A", "[{a0}] <= [as0]", "Decl(A:f()) =^= p.A", "[null] <= [a0]", "[a0] =^= A"};
152 		testConstraints(strings);
153 	}
154 
155 	@Test
testConstraints5()156 	public void testConstraints5() throws Exception{
157 		String[] strings= {"[as0] =^= A[]", "Decl(A:f()) =^= p.A", "[a0] <= A", "[a0] =^= A", "[null] <= [a0]", "[new A[]{a0}] <= [as0]"};
158 		testConstraints(strings);
159 	}
160 
161 	@Test
testConstraints6()162 	public void testConstraints6() throws Exception{
163 		String[] strings= {"Decl(A:f()) =^= p.A", "Decl(A:A(A)) =^= p.A", "[new A(a0)] =^= p.A", "[a0] <= [Parameter(0,A:A(A))]", "[a1] =^= A", "[a] =^= A", "[a0] =^= A", "[null] <= [a0]", "[new A(a0)] <= [a1]", "[Parameter(0,A:A(A))] =^= [a]"};
164 		testConstraints(strings);
165 	}
166 
167 	@Test
testConstraints7()168 	public void testConstraints7() throws Exception{
169 		String[] strings= {"Decl(A:A()) =^= p.A", "Decl(A:A(A)) =^= p.A", "[null] <= [Parameter(0,A:A(A))]", "[Parameter(0,A:A(A))] =^= [a]", "[a] =^= A"};
170 		testConstraints(strings);
171 	}
172 
173 	@Test
testConstraints8()174 	public void testConstraints8() throws Exception{
175 		String[] strings= {"Decl(A:x) =^= p.A", "Decl(A:f()) =^= p.A", "[x] =^= java.lang.Object", "Decl(A:aField) =^= p.A", "[this] <= [x]", "[aField] =^= A", "[x] =^= Object", "[this] =^= p.A", "[aField] <= Decl(A:x)"};
176 		testConstraints(strings);
177 	}
178 
179 	@Test
testConstraints9()180 	public void testConstraints9() throws Exception{
181 		String[] strings= {"Decl(A:f()) =^= p.A", "[a] =^= A", "[x] =^= boolean", "[a instanceof A] <= [x]", "[null] <= [a]", "[a] <= A or A <= [a]"};
182 		testConstraints(strings);
183 	}
184 
185 	@Test
testConstraints10()186 	public void testConstraints10() throws Exception{
187 		String[] strings= {"[null] <= [A:f1()]_returnType", "Decl(A:f1()) =^= p.A", "[A:f1()]_returnType =^= A[]"};
188 		testConstraints(strings);
189 	}
190 
191 	@Test
testConstraints11()192 	public void testConstraints11() throws Exception{
193 		String[] strings= {"[null] <= [A:f(A, Object)]_returnType", "[Parameter(1,B:f(A, Object))] =^= [a4]",
194 							"[B:f(A, Object)]_returnType =^= A", "Decl(B:f(A, Object)) < Decl(A:f(A, Object))",
195 							"[Parameter(1,A:f(A, Object))] == [Parameter(1,B:f(A, Object))]",
196 							"[Parameter(0,A:f(A, Object))] == [Parameter(0,B:f(A, Object))]",
197 							"[A:f(A, Object)]_returnType == [B:f(A, Object)]_returnType",
198 							"[Parameter(0,B:f(A, Object))] =^= [a3]",
199 							"[Parameter(0,A:f(A, Object))] =^= [a0]", "Decl(A:f(A, Object)) =^= p.A",
200 							"[null] <= [B:f(A, Object)]_returnType", "[Parameter(1,A:f(A, Object))] =^= [a1]",
201 							"[A:f(A, Object)]_returnType =^= A", "Decl(B:f(A, Object)) =^= p.B",
202 							"[a3] =^= A", "[a0] =^= A", "[a1] =^= Object", "[a4] =^= Object"};
203 		testConstraints(strings);
204 	}
205 
206 	@Test
testConstraints12()207 	public void testConstraints12() throws Exception{
208 		String[] strings= { "Decl(B:f(A, Object)) =^= p.B", "[Parameter(1,B:f(A, Object))] =^= [a4]", "[B:f(A, Object)]_returnType =^= A", "[null] <= [B:f(A, Object)]_returnType", "[A:f(A, Object)]_returnType =^= A", "[Parameter(1,A:f(A, Object))] =^= [a1]", "Decl(A:f(A, Object)) =^= p.A", "[Parameter(0,B:f(A, Object))] =^= [a3]", "[null] <= [A:f(A, Object)]_returnType", "[Parameter(0,A:f(A, Object))] =^= [a0]", "[a3] =^= A", "[a0] =^= A", "[a1] =^= Object", "[a4] =^= Object" };
209 		testConstraints(strings);
210 	}
211 
212 	@Test
testConstraints13()213 	public void testConstraints13() throws Exception{
214 		String[] strings= {"Decl(B:f(A, Object)) =^= p.B", "[Parameter(1,B:f(A, Object))] =^= [a4]", "[B:f(A, Object)]_returnType =^= A", "[null] <= [B:f(A, Object)]_returnType", "[A:f(A, Object)]_returnType =^= A", "[Parameter(1,A:f(A, Object))] =^= [a1]", "Decl(A:f(A, Object)) =^= p.A", "[Parameter(0,B:f(A, Object))] =^= [a3]", "[null] <= [A:f(A, Object)]_returnType", "[Parameter(0,A:f(A, Object))] =^= [a0]", "[a3] =^= A", "[a0] =^= A", "[a1] =^= Object", "[a4] =^= Object"};
215 		testConstraints(strings);
216 	}
217 
218 	@Test
testConstraints14()219 	public void testConstraints14() throws Exception{
220 		String[] strings= {"[A:f(A)]_returnType == [B:f(A)]_returnType", "[Parameter(0,A:f(A))] == [Parameter(0,B:f(A))]", "[B:f(A)]_returnType =^= A", "Decl(B:f(A)) < Decl(A:f(A))", "[A:f(A)]_returnType =^= A", "Decl(B:f(A)) < Decl(I:f(A))", "[null] <= [A:f(A)]_returnType", "[Parameter(0,A:f(A))] =^= [a0]", "[I:f(A)]_returnType =^= A", "Decl(A:f(A)) =^= p.A", "[ax] =^= B", "[Parameter(0,B:f(A))] =^= [a3]", "[null] <= [B:f(A)]_returnType", "[a3] <= [Parameter(0,B:f(A))]", "[ax.f(a3)] =^= [B:f(A)]_returnType", "[ax] <= Decl(I:f(A)) or [ax] <= Decl(A:f(A))", "Decl(B:f(A)) =^= p.B", "[I:f(A)]_returnType == [B:f(A)]_returnType", "[Parameter(0,I:f(A))] == [Parameter(0,B:f(A))]", "[null] <= [ax]", "[Parameter(0,I:f(A))] =^= [ai]", "Decl(I:f(A)) =^= p.I", "[a3] =^= A", "[a0] =^= A", "[ai] =^= A"};
221 		testConstraints(strings);
222 	}
223 
224 	@Test
testConstraints15()225 	public void testConstraints15() throws Exception{
226 		String[] strings= {"[Parameter(0,A:f(A))] =^= [a0]", "[I:f(A)]_returnType == [B:f(A)]_returnType", "[Parameter(0,I:f(A))] == [Parameter(0,B:f(A))]", "[null] <= [A:f(A)]_returnType", "[A:f(A)]_returnType == [B:f(A)]_returnType", "[Parameter(0,A:f(A))] == [Parameter(0,B:f(A))]", "Decl(B:f(A)) < Decl(A:f(A))", "[super.f(a3)] =^= [A:f(A)]_returnType", "Decl(A:f(A)) =^= p.A", "[null] <= [B:f(A)]_returnType", "[Parameter(0,I:f(A))] =^= [ai]", "[Parameter(0,B:f(A))] =^= [a3]", "[A:f(A)]_returnType =^= A", "Decl(B:f(A)) =^= p.B", "Decl(I:f(A)) =^= p.I", "Decl(B:f(A)) < Decl(I:f(A))", "[a3] <= [Parameter(0,A:f(A))]", "[I:f(A)]_returnType =^= A", "[B:f(A)]_returnType =^= A", "[a3] =^= A", "[a0] =^= A", "[ai] =^= A"};
227 		testConstraints(strings);
228 	}
229 
230 	@Test
testConstraints16()231 	public void testConstraints16() throws Exception{
232 		String[] strings= {"Decl(A:aField) =^= p.A", "Decl(A:f()) =^= p.A", "[this] =^= p.A", "[this] =^= p.A", "[this] <= [aTemp]", "[this] <= [aField]", "[this] <= [a]", "[a] =^= A", "[aField] =^= A", "[aTemp] =^= A", "[this] =^= p.A"};
233 		testConstraints(strings);
234 	}
235 
236 	@Test
testConstraints17()237 	public void testConstraints17() throws Exception{
238 		String[] strings= {"Decl(A:f()) =^= p.A", "[null] <= [a]", "[A:f()]_returnType =^= A", "[a] =^= A", "[a] <= [A:f()]_returnType"};
239 		testConstraints(strings);
240 	}
241 
242 	@Test
testConstraints18()243 	public void testConstraints18() throws Exception{
244 		String[] strings= {"[Parameter(0,B:B(A))] =^= [a1]", "Decl(B:B(A)) =^= p.B", "[Parameter(0,A:A(A))] =^= [a0]", "Decl(A:A(A)) =^= p.A", "[a1] <= [Parameter(0,A:A(A))]", "[a1] =^= A", "[a0] =^= A"};
245 		testConstraints(strings);
246 	}
247 
248 	@Test
testConstraints19()249 	public void testConstraints19() throws Exception{
250 		String[] strings= {"[aField] =^= p.A", "[a] =^= A", "Decl(B:f()) =^= p.B", "[a] <= [aField]", "[null] <= [a]", "Decl(A:aField) =^= p.A", "[aField] =^= A"};
251 		testConstraints(strings);
252 	}
253 
254 	@Test
testConstraints20()255 	public void testConstraints20() throws Exception{
256 		String[] strings= {"Decl(B:aField) =^= p.B", "Decl(A:aField) =^= p.A", "Decl(B:aField) < Decl(A:aField)", "[aField] =^= A", "[aField] =^= A"};
257 		testConstraints(strings);
258 	}
259 
260 	@Test
testConstraints21()261 	public void testConstraints21() throws Exception{
262 		String[] strings= {"Decl(A:f2(A[])) =^= p.A", "[Parameter(0,A:f2(A[]))] =^= [as]", "[as] =^= A[]"};
263 		testConstraints(strings);
264 	}
265 
266 	@Test
testConstraints22()267 	public void testConstraints22() throws Exception{
268 		String[] strings= {"[null] <= [A:f(A, Object)]_returnType", "[Parameter(0,A:f(A, Object))] =^= [a0]", "[Parameter(1,A:f(A, Object))] =^= [a1]", "[A:f(A, Object)]_returnType =^= A", "Decl(A:f(A, Object)) =^= p.A", "[a1] =^= Object", "[a0] =^= A"};
269 		testConstraints(strings);
270 	}
271 
272 	@Test
testConstraints23()273 	public void testConstraints23() throws Exception{
274 		//test for bug 41271 NullPointerException dumping set of ITypeConstraints to System.out
275 		String[] strings= {"[args.length] =^= int", "[0] <= [i]", "[i] =^= int", "[args] <= Decl((array type):length)", "[args] =^= String[]", "[Parameter(0,Test1:main(String[]))] =^= [args]", "Decl(Test1:main(String[])) =^= p.Test1"};
276 		testConstraints(strings);
277 	}
278 }
279