001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.core.ext.typeinfo;
017:
018: import com.google.gwt.core.ext.TreeLogger;
019: import com.google.gwt.core.ext.UnableToCompleteException;
020: import com.google.gwt.core.ext.typeinfo.test.Base;
021: import com.google.gwt.core.ext.typeinfo.test.Derived;
022: import com.google.gwt.core.ext.typeinfo.test.GenericClass;
023: import com.google.gwt.core.ext.typeinfo.test.MyCustomList;
024: import com.google.gwt.core.ext.typeinfo.test.MyIntegerList;
025: import com.google.gwt.core.ext.typeinfo.test.MyList;
026: import com.google.gwt.core.ext.typeinfo.test.GenericClass.GenericInnerClass;
027: import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
028:
029: import java.io.Serializable;
030: import java.util.ArrayList;
031: import java.util.Arrays;
032: import java.util.HashSet;
033: import java.util.List;
034: import java.util.Set;
035:
036: /**
037: * Test for {@link JParameterizedType}.
038: */
039: public class JParameterizedTypeTest extends
040: JDelegatingClassTypeTestBase {
041: /**
042: * Helper for verifying parameterized substitutions.
043: */
044: static class ParameterizedSubstitution implements Substitution {
045: private final JParameterizedType parameterizedType;
046:
047: public ParameterizedSubstitution(
048: JParameterizedType parameterizedType) {
049: this .parameterizedType = parameterizedType;
050: }
051:
052: public JType getSubstitution(JType type) {
053: return type.getSubstitutedType(parameterizedType);
054: }
055: }
056:
057: private final JClassType integerType;
058: private final boolean logToConsole = false;
059: private final ModuleContext moduleContext = new ModuleContext(
060: logToConsole ? new PrintWriterTreeLogger()
061: : TreeLogger.NULL,
062: "com.google.gwt.core.ext.typeinfo.TypeOracleTest");
063:
064: public JParameterizedTypeTest() throws UnableToCompleteException,
065: NotFoundException {
066: integerType = moduleContext.getOracle().getType(
067: Integer.class.getName());
068: }
069:
070: @Override
071: public void testFindNestedType() {
072: // TODO: complete this test method
073: }
074:
075: /**
076: * Checks that GenericClass<Integer> ends up with the correct substitutions.
077: *
078: * @throws NotFoundException
079: */
080: public void testGenericClass_Integer() throws NotFoundException {
081: TypeOracle oracle = moduleContext.getOracle();
082: JGenericType genericType = getGenericTestType();
083: JClassType type = oracle.getParameterizedType(genericType,
084: new JClassType[] { integerType });
085: JParameterizedType parameterizedType = type.isParameterized();
086:
087: validateTypeSubstitution(genericType, parameterizedType,
088: new ParameterizedSubstitution(parameterizedType));
089: }
090:
091: public void testGenericClass_LowerBoundWildcard()
092: throws NotFoundException {
093: TypeOracle oracle = moduleContext.getOracle();
094: JGenericType genericType = getGenericTestType();
095: JWildcardType lowerBoundWildcard = oracle
096: .getWildcardType(new JLowerBound(
097: new JClassType[] { integerType }));
098:
099: JClassType type = oracle.getParameterizedType(genericType,
100: new JClassType[] { lowerBoundWildcard });
101: JParameterizedType parameterizedType = type.isParameterized();
102:
103: validateTypeSubstitution(genericType, parameterizedType,
104: new ParameterizedSubstitution(parameterizedType));
105: }
106:
107: public void testGenericClass_UnboundWildcard()
108: throws NotFoundException {
109: TypeOracle oracle = moduleContext.getOracle();
110: JGenericType genericType = getGenericTestType();
111: JWildcardType upperBoundWildcard = oracle
112: .getWildcardType(new JUpperBound(
113: new JClassType[] { oracle.getJavaLangObject() }));
114:
115: JClassType type = oracle.getParameterizedType(genericType,
116: new JClassType[] { upperBoundWildcard });
117: JParameterizedType parameterizedType = type.isParameterized();
118:
119: validateTypeSubstitution(genericType, parameterizedType,
120: new ParameterizedSubstitution(parameterizedType));
121: }
122:
123: public void testGenericClass_UpperBoundWildcard()
124: throws NotFoundException {
125: TypeOracle oracle = moduleContext.getOracle();
126: JGenericType genericType = getGenericTestType();
127: JWildcardType upperBoundWildcard = oracle
128: .getWildcardType(new JUpperBound(
129: new JClassType[] { integerType }));
130:
131: JClassType type = oracle.getParameterizedType(genericType,
132: new JClassType[] { upperBoundWildcard });
133: JParameterizedType parameterizedType = type.isParameterized();
134:
135: validateTypeSubstitution(genericType, parameterizedType,
136: new ParameterizedSubstitution(parameterizedType));
137: }
138:
139: /**
140: * Test method for
141: * {@link com.google.gwt.core.ext.typeinfo.JParameterizedType#getEnclosingType()}.
142: *
143: * @throws NotFoundException
144: */
145: @Override
146: public void testGetEnclosingType() throws NotFoundException {
147: JParameterizedType testType = getTestType();
148:
149: // Check that GenericClass<Integer> is not nested
150: assertNull(testType.getEnclosingType());
151:
152: /*
153: * Check that GenericClass<Integer>.GenericInnerClass<Boolean> has //
154: * GenericClass<Integer> as its // enclosing type
155: */
156: JParameterizedType parameterizedInnerClass = getInnerParameterizedType();
157:
158: assertEquals(testType, parameterizedInnerClass
159: .getEnclosingType());
160: }
161:
162: @Override
163: public void testGetNestedType() {
164: // TODO: complete this test method
165: }
166:
167: /**
168: * Test method for {@link
169: * com.google.gwt.core.ext.typeinfo.JParameterizedType#getNestedTypes()}.
170: *
171: * @throws NotFoundException
172: */
173: @Override
174: public void testGetNestedTypes() throws NotFoundException {
175: JParameterizedType cut = getTestType();
176: JParameterizedType innerCut = getInnerParameterizedType();
177:
178: // Check that inner parameterized types don't appear in the parent's nested
179: // type set
180: assertEquals(0, cut.getNestedTypes().length);
181:
182: try {
183: cut.getNestedType(innerCut.getSimpleSourceName());
184: fail("Type " + cut.getQualifiedSourceName()
185: + " should report that it has no nested types");
186: } catch (NotFoundException ex) {
187: // Expected to get here
188: }
189: }
190:
191: @Override
192: public void testGetOverridableMethods() throws NotFoundException {
193: // Tested via testOverridableMethods_Base, testOverridableMethods_Derived,
194: // testOverridableMethods_Derived_Integer
195: }
196:
197: /**
198: * Tests the subtypes of MyList<Integer>. These should be:
199: * <ul>
200: * <li><code>MyIntegerList</code></li>
201: * <li><code>MyCustomList<? extends Serializable, Integer></code></li>
202: * </ul>
203: *
204: * @throws NotFoundException
205: */
206: @Override
207: public void testGetSubtypes() throws NotFoundException {
208: TypeOracle oracle = moduleContext.getOracle();
209: JGenericType genericType = oracle.getType(
210: MyList.class.getName()).isGenericType();
211:
212: JParameterizedType parameterizedType = oracle
213: .getParameterizedType(genericType,
214: new JClassType[] { integerType });
215: JClassType[] actualSubtypes = parameterizedType.getSubtypes();
216:
217: JGenericType myCustomListType = oracle.getType(
218: MyCustomList.class.getName()).isGenericType();
219: JParameterizedType parameterizedMyCustomList = oracle
220: .getParameterizedType(
221: myCustomListType,
222: new JClassType[] {
223: oracle
224: .getWildcardType(new JUpperBound(
225: oracle
226: .getType(Serializable.class
227: .getName()))),
228: integerType });
229: JClassType[] expected = {
230: oracle.getType(MyIntegerList.class.getName()),
231: parameterizedMyCustomList };
232:
233: validateEquals(oracle, expected, actualSubtypes);
234: }
235:
236: /**
237: * Test method for
238: * {@link com.google.gwt.core.ext.typeinfo.JParameterizedType#isAssignableFrom(JClassType)}.
239: */
240: @Override
241: public void testIsAssignableFrom() throws NotFoundException {
242: // Check that raw types can be assigned to a parameterized type
243: JParameterizedType testType = getTestType();
244: JClassType rawType = testType.getRawType();
245:
246: assertTrue(testType.isAssignableFrom(rawType));
247:
248: TypeOracle oracle = moduleContext.getOracle();
249: JGenericType genericList = (JGenericType) oracle
250: .getType(List.class.getName());
251:
252: JWildcardType unboundWildcard = oracle
253: .getWildcardType(new JUpperBound(oracle
254: .getJavaLangObject()));
255: JWildcardType numUpperBoundWildcard = oracle
256: .getWildcardType(new JUpperBound(oracle
257: .getType(Number.class.getName())));
258:
259: // List<?> should be assignable from List<? extends Number>
260: JParameterizedType unboundList = oracle.getParameterizedType(
261: genericList, new JClassType[] { unboundWildcard });
262: JParameterizedType numUpperBoundList = oracle
263: .getParameterizedType(genericList,
264: new JClassType[] { numUpperBoundWildcard });
265: assertTrue(unboundList.isAssignableFrom(numUpperBoundList));
266: assertFalse(unboundList.isAssignableTo(numUpperBoundList));
267:
268: assertFalse(numUpperBoundList.isAssignableFrom(unboundList));
269: assertTrue(numUpperBoundList.isAssignableTo(unboundList));
270:
271: // List<? extends Number> should be assignable from List<? extends Integer>
272: JWildcardType intUpperBoundWildcard = oracle
273: .getWildcardType(new JUpperBound(integerType));
274:
275: JParameterizedType intUpperBoundList = oracle
276: .getParameterizedType(genericList,
277: new JClassType[] { intUpperBoundWildcard });
278: assertTrue(numUpperBoundList
279: .isAssignableFrom(intUpperBoundList));
280: assertFalse(numUpperBoundList.isAssignableTo(intUpperBoundList));
281:
282: assertFalse(intUpperBoundList
283: .isAssignableFrom(numUpperBoundList));
284: assertTrue(intUpperBoundList.isAssignableTo(numUpperBoundList));
285:
286: // List<? super Integer> should be assignable from List<? super Number>
287: JWildcardType numLowerBoundWildcard = oracle
288: .getWildcardType(new JLowerBound(oracle
289: .getType(Number.class.getName())));
290: JWildcardType intLowerBoundWildcard = oracle
291: .getWildcardType(new JLowerBound(integerType));
292:
293: JParameterizedType numLowerBoundList = oracle
294: .getParameterizedType(genericList,
295: new JClassType[] { numLowerBoundWildcard });
296: JParameterizedType intLowerBoundList = oracle
297: .getParameterizedType(genericList,
298: new JClassType[] { intLowerBoundWildcard });
299:
300: assertTrue(intLowerBoundList
301: .isAssignableFrom(numLowerBoundList));
302: assertFalse(intLowerBoundList.isAssignableTo(numLowerBoundList));
303: assertFalse(numLowerBoundList
304: .isAssignableFrom(intLowerBoundList));
305: assertTrue(numLowerBoundList.isAssignableTo(intLowerBoundList));
306: }
307:
308: public void testOverridableMethods_Base() throws NotFoundException {
309: TypeOracle oracle = moduleContext.getOracle();
310: JClassType type = oracle.getType(Base.class.getName());
311: JGenericType genericType = type.isGenericType();
312: assertNotNull(genericType);
313:
314: List<JMethod> expected = new ArrayList<JMethod>(Arrays
315: .asList(type.getOverloads("m")));
316: List<JMethod> actual = new ArrayList<JMethod>(Arrays
317: .asList(type.getOverridableMethods()));
318:
319: validateOverridableMethods(expected, actual, true);
320: }
321:
322: public void testOverridableMethods_Derived()
323: throws NotFoundException {
324: TypeOracle oracle = moduleContext.getOracle();
325: JClassType type = oracle.getType(Derived.class.getName());
326: JGenericType genericType = type.isGenericType();
327: assertNotNull(genericType);
328:
329: JClassType super type = type.getSuperclass();
330: JParameterizedType paramType = super type.isParameterized();
331: // JGenericType genericSuperType = paramType.getBaseType().isGenericType();
332: assertNotNull(paramType);
333:
334: List<JMethod> expected = new ArrayList<JMethod>();
335: expected.addAll(Arrays.asList(genericType.getOverloads("m")));
336: expected.add(paramType.getMethod("m", new JType[] { paramType
337: .getTypeArgs()[0] }));
338:
339: List<JMethod> actual = new ArrayList<JMethod>(Arrays
340: .asList(type.getOverridableMethods()));
341:
342: validateOverridableMethods(expected, actual, true);
343: }
344:
345: public void testOverridableMethods_Derived_Integer()
346: throws NotFoundException {
347: TypeOracle oracle = moduleContext.getOracle();
348: JClassType type = oracle.getType(Derived.class.getName());
349: JGenericType genericType = type.isGenericType();
350: assertNotNull(genericType);
351:
352: JParameterizedType paramType = oracle.getParameterizedType(
353: genericType, new JClassType[] { integerType });
354:
355: List<JMethod> expected = new ArrayList<JMethod>();
356: expected.addAll(Arrays.asList(paramType.getOverloads("m")));
357:
358: List<JMethod> actual = new ArrayList<JMethod>(Arrays
359: .asList(paramType.getOverridableMethods()));
360:
361: validateOverridableMethods(expected, actual, true);
362: }
363:
364: /**
365: * Returns the <code>TypeOracle</code> type for {@link GenericClass}.
366: *
367: * @return <code>TypeOracle</code> type for {@link GenericClass}
368: * @throws NotFoundException
369: */
370: protected JGenericType getGenericTestType()
371: throws NotFoundException {
372: TypeOracle oracle = moduleContext.getOracle();
373: JClassType type = oracle.getType(GenericClass.class.getName());
374: assertNotNull(type.isGenericType());
375: return type.isGenericType();
376: }
377:
378: @Override
379: protected Substitution getSubstitution() throws NotFoundException {
380: return new ParameterizedSubstitution(getTestType());
381: }
382:
383: @Override
384: protected JParameterizedType getTestType() throws NotFoundException {
385: JGenericType type = getGenericTestType();
386:
387: return moduleContext.getOracle().getParameterizedType(type,
388: null, new JClassType[] { integerType });
389: }
390:
391: /**
392: * Returns the type for GenericClass<Integer>.GenericInnerClass<Boolean>.
393: *
394: * @throws NotFoundException
395: * @return type for GenericClass<Integer>.GenericInnerClass<Boolean>
396: */
397: private JParameterizedType getInnerParameterizedType()
398: throws NotFoundException {
399: JParameterizedType cut = getTestType();
400: TypeOracle oracle = moduleContext.getOracle();
401: JGenericType innerGenericClass = cut.getBaseType()
402: .getNestedType(GenericInnerClass.class.getSimpleName())
403: .isGenericType();
404:
405: JClassType booleanType = oracle
406: .getType(Boolean.class.getName());
407:
408: /*
409: * Check that GenericClass<Integer>.GenericInnerClass<Boolean> has
410: * GenericClass<Integer> as its enclosing type
411: */
412: //
413: JParameterizedType parameterizedInnerClass = oracle
414: .getParameterizedType(innerGenericClass, cut,
415: new JClassType[] { booleanType });
416:
417: return parameterizedInnerClass;
418: }
419:
420: private void validateOverridableMethods(List<JMethod> expected,
421: List<JMethod> actual, boolean addObjectMethods) {
422: Set<JMethod> expectedMethods = new HashSet<JMethod>();
423: expectedMethods.addAll(expected);
424: if (addObjectMethods) {
425: TypeOracle oracle = moduleContext.getOracle();
426: expectedMethods.addAll(Arrays.asList(oracle
427: .getJavaLangObject().getMethods()));
428: }
429:
430: for (JMethod method : actual) {
431: assertEquals("Method "
432: + method.getReadableDeclaration()
433: + " from type "
434: + method.getEnclosingType()
435: .getQualifiedSourceName()
436: + " was not expected", true, expectedMethods
437: .remove(method));
438: }
439:
440: assertTrue(expectedMethods.isEmpty());
441: }
442:
443: @Override
444: public void testIsAssignableTo() throws NotFoundException {
445: // This is covered as part of testIsAssignableFrom
446: }
447: }
|