/* * Copyright 2003-2010 the original author or authors. * * 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 org.codehaus.groovy.transform.stc; import static org.codehaus.groovy.ast.ClassHelper.GROOVY_OBJECT_TYPE; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.tools.WideningCategories; /** * Static support methods for {@link StaticTypeCheckingVisitor}. */ public abstract class StaticTypeCheckingSupport { /** * This is for internal use only. When an argument method is null, we cannot determine its type, so * we use this one as a wildcard. */ final static ClassNode UNKNOWN_PARAMETER_TYPE = ClassHelper.make("<unknown parameter type>"); public static boolean isBeingCompiled(ClassNode node) { return node.getCompileUnit() != null; } public static boolean implementsInterfaceOrIsSubclassOf(ClassNode type, ClassNode superOrInterface) { boolean result = type.equals(superOrInterface) || type.isDerivedFrom(superOrInterface) || type.implementsInterface(superOrInterface) || type == UNKNOWN_PARAMETER_TYPE; if (result) { return true; } if (superOrInterface instanceof WideningCategories.LowestUpperBoundClassNode) { WideningCategories.LowestUpperBoundClassNode cn = (WideningCategories.LowestUpperBoundClassNode) superOrInterface; result = implementsInterfaceOrIsSubclassOf(type, cn.getSuperClass()); if (result) { for (ClassNode interfaceNode : cn.getInterfaces()) { result = type.implementsInterface(interfaceNode); if (!result) break; } } if (result) return true; } else if (superOrInterface instanceof UnionTypeClassNode) { UnionTypeClassNode union = (UnionTypeClassNode) superOrInterface; for (ClassNode delegate : union.getDelegates()) { if (implementsInterfaceOrIsSubclassOf(type, delegate)) return true; } } if (type.isArray() && superOrInterface.isArray()) { return implementsInterfaceOrIsSubclassOf(type.getComponentType(), superOrInterface.getComponentType()); } if (GROOVY_OBJECT_TYPE.equals(superOrInterface) && !type.isInterface() && isBeingCompiled(type)) { return true; } return false; } }