430 lines
10 KiB
Java
430 lines
10 KiB
Java
/*******************************************************************************
|
|
* 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.classLoader;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
|
|
import com.ibm.wala.cfg.InducedCFG;
|
|
import com.ibm.wala.ipa.callgraph.Context;
|
|
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
|
import com.ibm.wala.ssa.IR;
|
|
import com.ibm.wala.ssa.SSAInstruction;
|
|
import com.ibm.wala.ssa.SSAOptions;
|
|
import com.ibm.wala.types.Descriptor;
|
|
import com.ibm.wala.types.MethodReference;
|
|
import com.ibm.wala.types.Selector;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.types.annotations.Annotation;
|
|
import com.ibm.wala.util.bytecode.BytecodeStream;
|
|
import com.ibm.wala.util.debug.UnimplementedError;
|
|
import com.ibm.wala.util.strings.Atom;
|
|
|
|
/**
|
|
* An implementation of {@link IMethod}, usually for a synthesized method that is not read directly from any source {@link Module}.
|
|
*/
|
|
public class SyntheticMethod implements IMethod {
|
|
|
|
public final static SSAInstruction[] NO_STATEMENTS = new SSAInstruction[0];
|
|
|
|
private final MethodReference method;
|
|
|
|
protected final IMethod resolvedMethod;
|
|
|
|
public final IClass declaringClass;
|
|
|
|
private final boolean isStatic;
|
|
|
|
private final boolean isFactory;
|
|
|
|
public SyntheticMethod(MethodReference method, IClass declaringClass, boolean isStatic, boolean isFactory) {
|
|
super();
|
|
if (method == null) {
|
|
throw new IllegalArgumentException("null method");
|
|
}
|
|
this.method = method;
|
|
this.resolvedMethod = null;
|
|
this.declaringClass = declaringClass;
|
|
this.isStatic = isStatic;
|
|
this.isFactory = isFactory;
|
|
}
|
|
|
|
public SyntheticMethod(IMethod method, IClass declaringClass, boolean isStatic, boolean isFactory) {
|
|
super();
|
|
if (method == null) {
|
|
throw new IllegalArgumentException("null method");
|
|
}
|
|
this.resolvedMethod = method;
|
|
this.method = resolvedMethod.getReference();
|
|
this.declaringClass = declaringClass;
|
|
this.isStatic = isStatic;
|
|
this.isFactory = isFactory;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isClinit()
|
|
*/
|
|
@Override
|
|
public boolean isClinit() {
|
|
return method.getSelector().equals(MethodReference.clinitSelector);
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isInit()
|
|
*/
|
|
@Override
|
|
public boolean isInit() {
|
|
return method.getSelector().equals(MethodReference.initSelector);
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isStatic()
|
|
*/
|
|
@Override
|
|
public boolean isStatic() {
|
|
return isStatic;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isNative()
|
|
*/
|
|
@Override
|
|
public boolean isNative() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isAbstract()
|
|
*/
|
|
@Override
|
|
public boolean isAbstract() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isPrivate()
|
|
*/
|
|
@Override
|
|
public boolean isPrivate() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isProtected() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isPublic() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isFinal()
|
|
*/
|
|
@Override
|
|
public boolean isFinal() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isBridge()
|
|
*/
|
|
@Override
|
|
public boolean isBridge() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isAbstract()
|
|
*/
|
|
@Override
|
|
public boolean isSynchronized() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isWalaSynthetic()
|
|
*/
|
|
@Override
|
|
public boolean isWalaSynthetic() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#isSynthetic()
|
|
*/
|
|
@Override
|
|
public boolean isSynthetic() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @see com.ibm.wala.classLoader.IMethod#getReference()
|
|
*/
|
|
@Override
|
|
public MethodReference getReference() {
|
|
return method;
|
|
}
|
|
|
|
/**
|
|
* Create an {@link InducedCFG} from an instruction array.
|
|
*
|
|
* NOTE: SIDE EFFECT!!! ... nulls out phi instructions in the instruction array!
|
|
*/
|
|
public InducedCFG makeControlFlowGraph(SSAInstruction[] instructions) {
|
|
return this.getDeclaringClass().getClassLoader().getLanguage().makeInducedCFG(instructions, this, Everywhere.EVERYWHERE);
|
|
}
|
|
|
|
public BytecodeStream getBytecodeStream() throws UnsupportedOperationException {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
/*
|
|
* TODO: why isn't this abstract?
|
|
*
|
|
* @see com.ibm.wala.classLoader.IMethod#getMaxLocals()
|
|
*
|
|
* @throws UnsupportedOperationException unconditionally
|
|
*/
|
|
public int getMaxLocals() throws UnsupportedOperationException {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
/*
|
|
* TODO: why isn't this abstract?
|
|
*
|
|
* @see com.ibm.wala.classLoader.IMethod#getMaxStackHeight()
|
|
*/
|
|
public int getMaxStackHeight() throws UnsupportedOperationException {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
public IClass getDeclaringClass() {
|
|
return declaringClass;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
StringBuffer s = new StringBuffer("synthetic ");
|
|
if (isFactoryMethod()) {
|
|
s.append(" factory ");
|
|
}
|
|
s.append(method.toString());
|
|
return s.toString();
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
final int prime = 31;
|
|
int result = 1;
|
|
result = prime * result + ((declaringClass == null) ? 0 : declaringClass.hashCode());
|
|
result = prime * result + ((method == null) ? 0 : method.hashCode());
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (this == obj)
|
|
return true;
|
|
if (obj == null)
|
|
return false;
|
|
if (getClass() != obj.getClass())
|
|
return false;
|
|
final SyntheticMethod other = (SyntheticMethod) obj;
|
|
if (declaringClass == null) {
|
|
if (other.declaringClass != null)
|
|
return false;
|
|
} else if (!declaringClass.equals(other.declaringClass))
|
|
return false;
|
|
if (method == null) {
|
|
if (other.method != null)
|
|
return false;
|
|
} else if (!method.equals(other.method))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasExceptionHandler() {
|
|
return false;
|
|
}
|
|
|
|
public boolean hasPoison() {
|
|
return false;
|
|
}
|
|
|
|
public String getPoison() {
|
|
return null;
|
|
}
|
|
|
|
public byte getPoisonLevel() {
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* TODO: why isn't this abstract?
|
|
*
|
|
* @param options options governing SSA construction
|
|
*/
|
|
@Deprecated
|
|
public SSAInstruction[] getStatements(@SuppressWarnings("unused") SSAOptions options) {
|
|
return NO_STATEMENTS;
|
|
}
|
|
|
|
/**
|
|
* Most subclasses should override this.
|
|
*
|
|
* @param context TODO
|
|
* @param options options governing IR conversion
|
|
*/
|
|
public IR makeIR(Context context, SSAOptions options) throws UnimplementedError {
|
|
throw new UnimplementedError("haven't implemented IR yet for class " + getClass());
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getParameterType(int)
|
|
*/
|
|
@Override
|
|
public TypeReference getParameterType(int i) {
|
|
if (isStatic()) {
|
|
return method.getParameterType(i);
|
|
} else {
|
|
if (i == 0) {
|
|
return method.getDeclaringClass();
|
|
} else {
|
|
return method.getParameterType(i - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @see com.ibm.wala.classLoader.IMethod#getNumberOfParameters()
|
|
*/
|
|
@Override
|
|
public int getNumberOfParameters() {
|
|
int n = method.getNumberOfParameters();
|
|
return isStatic() ? n : n + 1;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getDeclaredExceptions()
|
|
*/
|
|
@Override
|
|
public TypeReference[] getDeclaredExceptions() throws InvalidClassFileException {
|
|
if (resolvedMethod == null) {
|
|
return null;
|
|
} else {
|
|
return resolvedMethod.getDeclaredExceptions();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Atom getName() {
|
|
return method.getSelector().getName();
|
|
}
|
|
|
|
@Override
|
|
public Descriptor getDescriptor() {
|
|
return method.getSelector().getDescriptor();
|
|
}
|
|
/** BEGIN Custom change: : precise bytecode positions */
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getSourcePosition(int)
|
|
*/
|
|
@Override
|
|
public SourcePosition getSourcePosition(int bcIndex) throws InvalidClassFileException {
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getParameterSourcePosition(int)
|
|
*/
|
|
@Override
|
|
public SourcePosition getParameterSourcePosition(int paramNum) throws InvalidClassFileException {
|
|
return null;
|
|
}
|
|
/** END Custom change: precise bytecode positions */
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getLineNumber(int)
|
|
*/
|
|
@Override
|
|
public int getLineNumber(int bcIndex) {
|
|
return -1;
|
|
}
|
|
|
|
public boolean isFactoryMethod() {
|
|
return isFactory;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getSignature()
|
|
*/
|
|
@Override
|
|
public String getSignature() {
|
|
return getReference().getSignature();
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getSelector()
|
|
*/
|
|
@Override
|
|
public Selector getSelector() {
|
|
return getReference().getSelector();
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getLocalVariableName(int, int)
|
|
*/
|
|
@Override
|
|
public String getLocalVariableName(int bcIndex, int localNumber) {
|
|
// no information is available
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#hasLocalVariableTable()
|
|
*/
|
|
@Override
|
|
public boolean hasLocalVariableTable() {
|
|
return false;
|
|
}
|
|
|
|
public SSAInstruction[] getStatements() {
|
|
return getStatements(SSAOptions.defaultOptions());
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getReturnType()
|
|
*/
|
|
@Override
|
|
public TypeReference getReturnType() {
|
|
return getReference().getReturnType();
|
|
}
|
|
|
|
@Override
|
|
public IClassHierarchy getClassHierarchy() {
|
|
return getDeclaringClass().getClassHierarchy();
|
|
}
|
|
|
|
@Override
|
|
public Collection<Annotation> getAnnotations() {
|
|
return Collections.emptySet();
|
|
}
|
|
|
|
}
|