| /* |
| * Copyright 2007 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.dev.javac.typemodel; |
| |
| import com.google.gwt.core.ext.TreeLogger; |
| import com.google.gwt.core.ext.UnableToCompleteException; |
| import com.google.gwt.core.ext.typeinfo.JType; |
| import com.google.gwt.core.ext.typeinfo.TypeOracleException; |
| import com.google.gwt.dev.util.log.PrintWriterTreeLogger; |
| |
| import junit.framework.TestCase; |
| |
| /** |
| * Tests related to JClassType. See individual test methods to details. |
| */ |
| public class JClassTypeTest extends TestCase { |
| private final boolean logToConsole = false; |
| private final ModuleContext moduleContext = new ModuleContext(logToConsole |
| ? new PrintWriterTreeLogger() : TreeLogger.NULL, |
| "com.google.gwt.dev.javac.typemodel.TypeOracleTest"); |
| |
| public JClassTypeTest() throws UnableToCompleteException { |
| } |
| |
| public void testGetInheritableOrOverridableMethods() |
| throws TypeOracleException { |
| TypeOracle typeOracle = moduleContext.getOracle(); |
| // TypeOracle typeOracle = buildOracleFromTestPackage(logger); |
| |
| String[] noParams = new String[0]; |
| String[] intObjectParams = new String[]{"int", "java.lang.Object"}; |
| |
| // Verify IA. |
| { |
| JClassType type = typeOracle.getType("com.google.gwt.dev.javac.typemodel.test.IA"); |
| JMethod[] leafMethods = type.getOverridableMethods(); |
| assertEquals(3, leafMethods.length); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IA", "ia", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IA", "ia", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IA", "foo", noParams); |
| } |
| |
| // Verify IB. |
| { |
| JClassType type = typeOracle.getType("com.google.gwt.dev.javac.typemodel.test.IB"); |
| JMethod[] leafMethods = type.getOverridableMethods(); |
| assertEquals(5, leafMethods.length); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IB", "ia", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IB", "ia", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.IB", "ib", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.IB", "ib", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.IB", "foo", noParams); |
| } |
| |
| // Verify IC. |
| { |
| JClassType type = typeOracle.getType("com.google.gwt.dev.javac.typemodel.test.IC"); |
| JMethod[] leafMethods = type.getOverridableMethods(); |
| assertEquals(7, leafMethods.length); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "ia", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "ia", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "ib", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "ib", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "ic", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "ic", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "foo", noParams); |
| } |
| |
| // Both overloads of ia are only declared in IA, so all searches should find |
| // them there. |
| { |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CA", "ia", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CB", "ia", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "ia", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CA", "ia", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CB", "ia", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "ia", intObjectParams); |
| } |
| |
| // Both overloads of ib are declared in both IB and IC, so |
| // - searching for ib in CB will return IB |
| // - searching for ib in CC will return IC |
| { |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.CB", "ib", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "ib", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.CB", "ib", intObjectParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "ib", intObjectParams); |
| } |
| |
| // Both overloads of ic are declared only in IC, but ic() is also declared |
| // in CB, so |
| // - searching for ic() in CB will return CB |
| // - searching for ic() in CC will return CB |
| // - searching for ic(int, Object) in CC will return IC |
| { |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.CB", |
| "com.google.gwt.dev.javac.typemodel.test.CB", "ic", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.CB", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "ic", noParams); |
| |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IC", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "ic", intObjectParams); |
| } |
| |
| // Both IA and IB define foo(), and searching for foo() on IC should return |
| // IB.foo(). This matters because IC also extends IA, so a naive algorithm |
| // for getLeafMethods() might prefer IA.foo() to IB.foo(). |
| { |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IB", |
| "com.google.gwt.dev.javac.typemodel.test.IC", "foo", noParams); |
| } |
| |
| // Both IA and CB define foo(), foo() being final in CB, so searching for |
| // foo() on CA should return IA.foo() as overridable, while searching for |
| // foo() on CB or CC should return CB.foo() as inheritable but not |
| // overridable. |
| { |
| assertMethodOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.IA", |
| "com.google.gwt.dev.javac.typemodel.test.CA", "foo", noParams); |
| |
| assertMethodInheritableNotOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.CB", |
| "com.google.gwt.dev.javac.typemodel.test.CB", "foo", noParams); |
| |
| assertMethodInheritableNotOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.CB", |
| "com.google.gwt.dev.javac.typemodel.test.CC", "foo", noParams); |
| |
| // Check that we aren't including methods that aren't actually overridable |
| // (but are inheritable) because they are final (but non-private). |
| assertMethodInheritableNotOverridable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.CA", |
| "com.google.gwt.dev.javac.typemodel.test.CA", |
| "caNotOverridableFinal", noParams); |
| |
| // Check that we aren't including methods that aren't actually inheritable |
| // because they are private. |
| assertMethodNotInheritable(typeOracle, |
| "com.google.gwt.dev.javac.typemodel.test.CA", |
| "com.google.gwt.dev.javac.typemodel.test.CA", |
| "caNotOverridablePrivate", noParams); |
| } |
| } |
| |
| private void assertMethodInheritableNotOverridable(TypeOracle typeOracle, |
| String expectedTypeName, String searchTypeName, String methodName, |
| String[] paramTypeNames) throws TypeOracleException { |
| assertInheritableOrOverridableMethod(true, false, typeOracle, |
| expectedTypeName, searchTypeName, methodName, paramTypeNames); |
| } |
| |
| private void assertMethodNotInheritable(TypeOracle typeOracle, |
| String expectedTypeName, String searchTypeName, String methodName, |
| String[] paramTypeNames) throws TypeOracleException { |
| assertInheritableOrOverridableMethod(false, false, typeOracle, |
| expectedTypeName, searchTypeName, methodName, paramTypeNames); |
| } |
| |
| private void assertMethodOverridable(TypeOracle typeOracle, |
| String expectedTypeName, String searchTypeName, String methodName, |
| String[] paramTypeNames) throws TypeOracleException { |
| assertInheritableOrOverridableMethod(true, true, typeOracle, |
| expectedTypeName, searchTypeName, methodName, paramTypeNames); |
| } |
| |
| private void assertInheritableOrOverridableMethod( |
| boolean shouldBeInheritable, boolean shouldBeOverridable, |
| TypeOracle oracle, String expectedTypeName, String searchTypeName, |
| String methodName, String[] paramTypeNames) throws TypeOracleException { |
| |
| JType[] paramTypes = new JType[paramTypeNames.length]; |
| for (int i = 0; i < paramTypeNames.length; i++) { |
| String paramTypeName = paramTypeNames[i]; |
| paramTypes[i] = oracle.parse(paramTypeName); |
| } |
| |
| JClassType expectedType = oracle.getType(expectedTypeName); |
| JClassType searchType = oracle.getType(searchTypeName); |
| |
| assertMethodInclusion(shouldBeInheritable, |
| searchType.getInheritableMethods(), methodName, expectedType, |
| paramTypes); |
| assertMethodInclusion(shouldBeOverridable, |
| searchType.getOverridableMethods(), methodName, expectedType, |
| paramTypes); |
| } |
| |
| private void assertMethodInclusion(boolean shouldBeFound, |
| JMethod[] leafMethods, String methodName, JClassType expectedType, |
| JType[] paramTypes) { |
| boolean wasFound = false; |
| |
| for (JMethod method : leafMethods) { |
| if (method.getName().equals(methodName)) { |
| if (method.hasParamTypes(paramTypes)) { |
| assertEquals(expectedType, method.getEnclosingType()); |
| wasFound = true; |
| break; |
| } |
| } |
| } |
| |
| if (shouldBeFound) { |
| if (wasFound) { |
| // Good. We wanted to find it and we did. |
| } else { |
| fail("Did not find expected method '" + methodName + "' on type '" |
| + expectedType.getQualifiedSourceName() + "'"); |
| } |
| } else { |
| // We want to *not* find it. |
| if (wasFound) { |
| fail("Did not expect to find method '" + methodName + "' on type '" |
| + expectedType.getQualifiedSourceName() + "'"); |
| } else { |
| // Good. We didn't want to find it and didn't. |
| } |
| } |
| } |
| } |