1 /*******************************************************************************
2  * Copyright (c) 2016, 2019 Sven Strohschein 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  * Contributors:
11  *     Sven Strohschein - initial API and implementation
12  *******************************************************************************/
13 package org.eclipse.jdt.core.tests.compiler.regression;
14 
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
17 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
18 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
19 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
20 import org.eclipse.jdt.internal.compiler.lookup.Binding;
21 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
22 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
23 import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
24 import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
25 
26 public class PackageBindingTest extends AbstractCompilerTest
27 {
PackageBindingTest(String name)28 	public PackageBindingTest(String name) {
29 		super(name);
30 	}
31 
32 	/**
33 	 * This test checks if it is searched for packages before searching for types.
34 	 * The search for packages is much faster than searching for types, therefore it should get executed before searching for types.
35 	 * Commented since reverted to original behaviour as per bug 495598
36 	 */
_test01()37 	public void _test01() {
38 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(true);
39 
40 		PlainPackageBinding packageBinding = new PlainPackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
41 		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray(), null, false);
42 		assertNotNull(resultBinding);
43 
44 		assertTrue(nameEnv.isPackageSearchExecuted);
45 		assertFalse(nameEnv.isTypeSearchExecuted);
46 	}
47 
48 	/**
49 	 * This test checks if it is searched for types when no package was found.
50 	 * The test {@link #_test01()} checks if the package search is executed before the type search.
51 	 * The search for packages is much faster than searching for types, therefore it should get executed before searching for types.
52 	 */
test02()53 	public void test02() {
54 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(false);
55 
56 		LookupEnvironment environment = new LookupEnvironment(null, new CompilerOptions(), null, nameEnv);
57 		PlainPackageBinding packageBinding = new PlainPackageBinding(environment);
58 		Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray(), environment.module, false);
59 		assertNull(resultBinding); // (not implemented)
60 
61 		assertTrue(nameEnv.isPackageSearchExecuted);
62 		assertTrue(nameEnv.isTypeSearchExecuted);
63 	}
64 
65 	/**
66 	 * This test checks if {@link INameEnvironment#findType(char[], char[][])} is executed.
67 	 * INameEnvironment has no option to avoid the search for secondary types, therefore the search for secondary types is executed (when available).
68 	 */
test03()69 	public void test03() {
70 		NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(false);
71 
72 		LookupEnvironment lookupEnv = new LookupEnvironment(null, new CompilerOptions(), null, nameEnv);
73 		PackageBinding packageBinding = lookupEnv.createPackage(new char[][]{"org/eclipse/jdt".toCharArray(), "org/eclipse/jdt/internal".toCharArray()});
74 		assertNotNull(packageBinding);
75 
76 		assertTrue(nameEnv.isTypeSearchExecuted); //the method findType(char[], char[][]) should got executed (without an option to avoid the search for secondary types)
77 	}
78 
79 	/**
80 	 * This test checks if types are searched on creating a package, but without the search for secondary types.
81 	 * It isn't necessary to search for secondary types when creating a package, because a package name can not collide with a secondary type.
82 	 * The search for secondary types should not get executed, because the search for secondary types is very expensive regarding performance
83 	 * (all classes of a package have to get loaded, parsed and analyzed).
84 	 */
test04()85 	public void test04() {
86 		NameEnvironmentWithProgressDummy nameEnvWithProgress = new NameEnvironmentWithProgressDummy();
87 
88 		LookupEnvironment lookupEnv = new LookupEnvironment(null, new CompilerOptions(), null, nameEnvWithProgress);
89 		PackageBinding packageBinding = lookupEnv.createPackage(new char[][]{"org/eclipse/jdt".toCharArray(), "org/eclipse/jdt/internal".toCharArray()});
90 		assertNotNull(packageBinding);
91 
92 		assertTrue(nameEnvWithProgress.isTypeSearchExecutedWithSearchWithSecondaryTypes); //the method findType(char[], char[][], boolean) should got executed ...
93 		assertFalse(nameEnvWithProgress.isTypeSearchWithSearchWithSecondaryTypes); //... but without the search for secondary types
94 	}
95 
96 	private class NameEnvironmentDummy implements INameEnvironment
97 	{
98 		private final boolean isPackage;
99 		boolean isPackageSearchExecuted;
100 		boolean isTypeSearchExecuted;
101 
NameEnvironmentDummy(boolean isPackage)102 		NameEnvironmentDummy(boolean isPackage) {
103 			this.isPackage = isPackage;
104 		}
105 
106 		@Override
findType(char[][] compoundTypeName)107 		public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
108 			this.isTypeSearchExecuted = true;
109 			return null;
110 		}
111 
112 		@Override
findType(char[] typeName, char[][] packageName)113 		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
114 			this.isTypeSearchExecuted = true;
115 			return null;
116 		}
117 
118 		@Override
isPackage(char[][] parentPackageName, char[] packageName)119 		public boolean isPackage(char[][] parentPackageName, char[] packageName) {
120 			this.isPackageSearchExecuted = true;
121 			return this.isPackage;
122 		}
123 
124 		@Override
cleanup()125 		public void cleanup() {
126 		}
127 	}
128 
129 	private class NameEnvironmentWithProgressDummy implements INameEnvironmentWithProgress
130 	{
131 		boolean isTypeSearchWithSearchWithSecondaryTypes;
132 		boolean isTypeSearchExecutedWithSearchWithSecondaryTypes;
133 
NameEnvironmentWithProgressDummy()134 		NameEnvironmentWithProgressDummy() {}
135 
136 		@Override
findType(char[][] compoundTypeName)137 		public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
138 			return null;
139 		}
140 
141 		@Override
isPackage(char[][] parentPackageName, char[] packageName)142 		public boolean isPackage(char[][] parentPackageName, char[] packageName) {
143 			return false;
144 		}
145 
146 		@Override
cleanup()147 		public void cleanup() {
148 		}
149 
150 		@Override
setMonitor(IProgressMonitor monitor)151 		public void setMonitor(IProgressMonitor monitor) {
152 		}
153 
154 		@Override
findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, char[] moduleName)155 		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, boolean searchWithSecondaryTypes, char[] moduleName) {
156 			this.isTypeSearchExecutedWithSearchWithSecondaryTypes = true;
157 			this.isTypeSearchWithSearchWithSecondaryTypes = searchWithSecondaryTypes;
158 			return null;
159 		}
160 
161 		@Override
findType(char[] typeName, char[][] packageName)162 		public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
163 			// TODO Auto-generated method stub
164 			return null;
165 		}
166 	}
167 }