blob: 196d8d21675052ce88406c6c00927705c327a2bc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* 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 org.eclipse.jdi.internal;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.StackFrame;
import com.sun.jdi.Type;
import com.sun.jdi.VMMismatchException;
/**
* this class implements the corresponding interfaces declared by the JDI
* specification. See the com.sun.jdi package for more information.
*
*/
public class LocalVariableImpl extends MirrorImpl implements LocalVariable, Comparable<LocalVariable> {
/** Method that holds local variable. */
private MethodImpl fMethod;
/** First code index at which the variable is visible (unsigned). */
private long fCodeIndex;
/** The variable's name. */
private String fName;
/** The variable type's JNI signature. */
private String fSignature;
/** The variable type generic signature. */
private String fGenericSignature;
/** The variable's type */
private Type fType;
/** The variables type name */
private String fTypeName;
/**
* Unsigned value used in conjunction with codeIndex. The variable can be
* get or set only when the current codeIndex <= current frame code index <
* code index + length.
* <p>
* The length is set to -1 when this variable represents an inferred
* argument (when local variable info is unavailable). We assume that such
* arguments are visible for the entire method.
* </p>
* */
private int fLength;
/** The local variable's index in its frame. */
private int fSlot;
/** Is the local variable an argument of its method? */
private boolean fIsArgument;
public LocalVariableImpl(VirtualMachineImpl vmImpl, MethodImpl method,
long codeIndex, String name, String signature,
String genericSignature, int length, int slot, boolean isArgument) {
super("LocalVariable", vmImpl); //$NON-NLS-1$
fMethod = method;
fCodeIndex = codeIndex;
fName = name;
fSignature = signature;
fGenericSignature = genericSignature;
fLength = length;
fSlot = slot;
fIsArgument = isArgument;
}
/**
* @return Returns local variable's index in its frame.
*/
public int slot() {
return fSlot;
}
/**
* @return Returns the hash code value.
*/
@Override
public int hashCode() {
return fMethod.hashCode() + (int) fCodeIndex + fSlot;
}
/**
* @return Returns true if two mirrors refer to the same entity in the
* target VM.
* @see java.lang.Object#equals(Object).
*/
@Override
public boolean equals(Object object) {
if (object != null && object.getClass().equals(this.getClass())) {
LocalVariableImpl loc = (LocalVariableImpl) object;
return fMethod.equals(loc.fMethod) && fCodeIndex == loc.fCodeIndex
&& fSlot == loc.fSlot;
}
return false;
}
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(LocalVariable variable) {
if (variable == null || !variable.getClass().equals(this.getClass()))
throw new ClassCastException(
JDIMessages.LocalVariableImpl_Can__t_compare_local_variable_to_given_object_1);
// See if methods are the same, if not return comparison between
// methods.
LocalVariableImpl var2 = (LocalVariableImpl) variable;
if (!method().equals(var2.method()))
return method().compareTo(var2.method());
// Return comparison between the index of each local variable in its
// stack frame.
// Code indexes must be treated as unsigned. This matters if you have to
// compare them.
if (fCodeIndex < 0 || var2.fCodeIndex < 0)
throw new InternalError(
JDIMessages.LocalVariableImpl_Code_indexes_are_assumed_to_be_always_positive_2);
long index2 = var2.fCodeIndex;
if (fCodeIndex < index2)
return -1;
else if (fCodeIndex > index2)
return 1;
else
return 0;
}
/**
* @return Returns true if this variable is an argument to its method.
*/
@Override
public boolean isArgument() {
return fIsArgument;
}
@Override
public boolean isVisible(StackFrame frame) throws IllegalArgumentException,
VMMismatchException {
checkVM(frame);
StackFrameImpl frameImpl = (StackFrameImpl) frame;
if (!fMethod.equals(frameImpl.location().method()))
throw new IllegalArgumentException(
JDIMessages.LocalVariableImpl_The_stack_frame__s_method_does_not_match_this_variable__s_method_3);
if (fLength == -1) {
// inferred argument - assume visible for entire method
return true;
}
long currentIndex = frameImpl.location().codeIndex();
// Code indexes must be treated as unsigned. This matters if you have to
// compare them.
if (currentIndex >= 0 && fCodeIndex >= 0 && fCodeIndex + fLength >= 0)
return fCodeIndex <= currentIndex
&& currentIndex < fCodeIndex + fLength;
throw new InternalError(
JDIMessages.LocalVariableImpl_Code_indexes_are_assumed_to_be_always_positive_4);
}
/**
* @return Returns the name of the local variable.
*/
@Override
public String name() {
return fName;
}
/**
* @return Returns the signature of the local variable.
*/
@Override
public String signature() {
return fSignature;
}
/**
* @return Returns the type of the this LocalVariable.
*/
@Override
public Type type() throws ClassNotLoadedException {
if (fType == null) {
fType = TypeImpl.create(virtualMachineImpl(), fSignature, method()
.declaringType().classLoader());
}
return fType;
}
/**
* @return Returns a text representation of the declared type of this
* variable.
*/
@Override
public String typeName() {
if (fTypeName == null) {
fTypeName = TypeImpl.signatureToName(fSignature);
}
return fTypeName;
}
/**
* @return Returns the tag of the declared type of this variable.
*/
public byte tag() {
return TypeImpl.signatureToTag(fSignature);
}
/**
* @return Returns the method that holds the local variable.
*/
public MethodImpl method() {
return fMethod;
}
/**
* @return Returns true if the local variable is the 'this' pointer.
*/
public boolean isThis() {
return slot() == 0 && !method().isStatic();
}
/**
* @return Returns description of Mirror object.
*/
@Override
public String toString() {
return fName;
}
@Override
public String genericSignature() {
return fGenericSignature;
}
}