/****************************************************************************** * Copyright (c) 2002 - 2006 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ package com.ibm.wala.cast.loader; import java.io.Reader; import java.net.URL; import java.util.Collection; import java.util.Collections; import com.ibm.wala.cast.tree.CAstSourcePositionMap; import com.ibm.wala.cast.types.AstMethodReference; import com.ibm.wala.cast.types.AstTypeReference; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.classLoader.IField; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.shrikeCT.ClassConstants; import com.ibm.wala.types.Selector; import com.ibm.wala.types.TypeName; import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.strings.Atom; abstract public class AstFunctionClass implements IClass, ClassConstants { private final IClassLoader loader; protected IMethod functionBody; private final CAstSourcePositionMap.Position sourcePosition; private final TypeReference reference; private final TypeReference superReference; protected AstFunctionClass(TypeReference reference, TypeReference superReference, IClassLoader loader, CAstSourcePositionMap.Position sourcePosition) { this.superReference = superReference; this.sourcePosition = sourcePosition; this.reference = reference; this.loader = loader; } protected AstFunctionClass(TypeReference reference, IClassLoader loader, CAstSourcePositionMap.Position sourcePosition) { this(reference, TypeReference.findOrCreate(reference.getClassLoader(), AstTypeReference.functionTypeName), loader, sourcePosition); } @Override public String toString() { try { return "function " + functionBody.getReference().getDeclaringClass().getName(); } catch (NullPointerException e) { return "<need to set code body>"; } } @Override public IClassLoader getClassLoader() { return loader; } @Override public boolean isInterface() { return false; } @Override public boolean isAbstract() { return functionBody == null; } @Override public boolean isPublic() { return true; } @Override public boolean isPrivate() { return false; } public boolean isStatic() { return false; } @Override public int getModifiers() { return ACC_PUBLIC; } @Override public IClass getSuperclass() { return loader.lookupClass(superReference.getName()); } @Override public Collection<IClass> getDirectInterfaces() { return Collections.emptySet(); } @Override public Collection<IClass> getAllImplementedInterfaces() { return Collections.emptySet(); } public Collection<IClass> getAllAncestorInterfaces() { return Collections.emptySet(); } @Override public IMethod getMethod(Selector selector) { if (selector.equals(AstMethodReference.fnSelector)) { return functionBody; } else { return loader.lookupClass(superReference.getName()).getMethod(selector); } } @Override public IField getField(Atom name) { return loader.lookupClass(superReference.getName()).getField(name); } @Override public IField getField(Atom name, TypeName type) { // assume that for AST classes, you can't have multiple fields with the same name return loader.lookupClass(superReference.getName()).getField(name); } @Override public TypeReference getReference() { return reference; } public CAstSourcePositionMap.Position getSourcePosition() { return sourcePosition; } public URL getSourceURL() { return sourcePosition.getURL(); } @Override public String getSourceFileName() { return sourcePosition.getURL().getFile(); } @Override public Reader getSource() { return null; } @Override public IMethod getClassInitializer() { return null; } @Override public boolean isArrayClass() { return false; } @Override public Collection<IMethod> getDeclaredMethods() { if (functionBody != null) { return Collections.singleton(functionBody); } else { throw new Error("function " + reference + " has no body!"); } } @Override public Collection<IField> getDeclaredInstanceFields() { return Collections.emptySet(); } @Override public Collection<IField> getDeclaredStaticFields() { return Collections.emptySet(); } @Override public Collection<IField> getAllInstanceFields() { return Collections.emptySet(); } @Override public Collection<IField> getAllStaticFields() { return Collections.emptySet(); } @Override public Collection<IField> getAllFields() { return Collections.emptySet(); } @Override public Collection<IMethod> getAllMethods() { return Collections.singleton(functionBody); } @Override public TypeName getName() { return reference.getName(); } @Override public boolean isReferenceType() { return true; } public IMethod getCodeBody() { return functionBody; } }