| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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 { |
| /** 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 var 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. |
| */ |
| 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). |
| */ |
| 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; |
| } |
| |
| /** |
| * @return Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. |
| */ |
| public int compareTo(Object object) { |
| if (object == null || !object.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)object; |
| 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. |
| */ |
| public boolean isArgument() { |
| return fIsArgument; |
| } |
| |
| 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. |
| */ |
| public String name() { |
| return fName; |
| } |
| |
| /** |
| * @return Returns the signature of the local variable. |
| */ |
| public String signature() { |
| return fSignature; |
| } |
| |
| /** |
| * @return Returns the type of the this LocalVariable. |
| */ |
| 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. |
| */ |
| 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. |
| */ |
| public String toString() { |
| return fName; |
| } |
| |
| public String genericSignature() { |
| return fGenericSignature; |
| } |
| |
| } |