001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal;
011:
012: import com.sun.jdi.ClassNotLoadedException;
013: import com.sun.jdi.LocalVariable;
014: import com.sun.jdi.StackFrame;
015: import com.sun.jdi.Type;
016: import com.sun.jdi.VMMismatchException;
017:
018: /**
019: * this class implements the corresponding interfaces
020: * declared by the JDI specification. See the com.sun.jdi package
021: * for more information.
022: *
023: */
024: public class LocalVariableImpl extends MirrorImpl implements
025: LocalVariable {
026: /** Method that holds local variable. */
027: private MethodImpl fMethod;
028: /** First code index at which the variable is visible (unsigned). */
029: private long fCodeIndex;
030: /** The variable's name. */
031: private String fName;
032: /** The variable type's JNI signature. */
033: private String fSignature;
034: /** The variable type generic signature. */
035: private String fGenericSignature;
036: /** The variable's type */
037: private Type fType;
038: /** The variables type name */
039: private String fTypeName;
040: /**
041: * Unsigned value used in conjunction with codeIndex.
042: * The variable can be get or set only when the current
043: * codeIndex <= current frame code index < code index + length.
044: * <p>
045: * The length is set to -1 when this variable represents an
046: * inferred argument (when local var info is unavailable).
047: * We assume that such arguments are visible for the entire
048: * method.
049: * </p>
050: * */
051: private int fLength;
052: /** The local variable's index in its frame. */
053: private int fSlot;
054: /** Is the local variable an argument of its method? */
055: private boolean fIsArgument;
056:
057: public LocalVariableImpl(VirtualMachineImpl vmImpl,
058: MethodImpl method, long codeIndex, String name,
059: String signature, String genericSignature, int length,
060: int slot, boolean isArgument) {
061: super ("LocalVariable", vmImpl); //$NON-NLS-1$
062: fMethod = method;
063: fCodeIndex = codeIndex;
064: fName = name;
065: fSignature = signature;
066: fGenericSignature = genericSignature;
067: fLength = length;
068: fSlot = slot;
069: fIsArgument = isArgument;
070: }
071:
072: /**
073: * @return Returns local variable's index in its frame.
074: */
075: public int slot() {
076: return fSlot;
077: }
078:
079: /**
080: * @return Returns the hash code value.
081: */
082: public int hashCode() {
083: return fMethod.hashCode() + (int) fCodeIndex + fSlot;
084: }
085:
086: /**
087: * @return Returns true if two mirrors refer to the same entity in the target VM.
088: * @see java.lang.Object#equals(Object).
089: */
090: public boolean equals(Object object) {
091: if (object != null && object.getClass().equals(this .getClass())) {
092: LocalVariableImpl loc = (LocalVariableImpl) object;
093: return fMethod.equals(loc.fMethod)
094: && fCodeIndex == loc.fCodeIndex
095: && fSlot == loc.fSlot;
096: }
097: return false;
098: }
099:
100: /**
101: * @return Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
102: */
103: public int compareTo(Object object) {
104: if (object == null
105: || !object.getClass().equals(this .getClass()))
106: throw new ClassCastException(
107: JDIMessages.LocalVariableImpl_Can__t_compare_local_variable_to_given_object_1);
108:
109: // See if methods are the same, if not return comparison between methods.
110: LocalVariableImpl var2 = (LocalVariableImpl) object;
111: if (!method().equals(var2.method()))
112: return method().compareTo(var2.method());
113:
114: // Return comparison between the index of each local variable in its stack frame.
115: // Code indexes must be treated as unsigned. This matters if you have to compare them.
116: if (fCodeIndex < 0 || var2.fCodeIndex < 0)
117: throw new InternalError(
118: JDIMessages.LocalVariableImpl_Code_indexes_are_assumed_to_be_always_positive_2);
119:
120: long index2 = var2.fCodeIndex;
121: if (fCodeIndex < index2)
122: return -1;
123: else if (fCodeIndex > index2)
124: return 1;
125: else
126: return 0;
127: }
128:
129: /**
130: * @return Returns true if this variable is an argument to its method.
131: */
132: public boolean isArgument() {
133: return fIsArgument;
134: }
135:
136: public boolean isVisible(StackFrame frame)
137: throws IllegalArgumentException, VMMismatchException {
138: checkVM(frame);
139: StackFrameImpl frameImpl = (StackFrameImpl) frame;
140: if (!fMethod.equals(frameImpl.location().method()))
141: throw new IllegalArgumentException(
142: JDIMessages.LocalVariableImpl_The_stack_frame__s_method_does_not_match_this _variable__s_method_3);
143:
144: if (fLength == -1) {
145: // inferred argument - assume visible for entire method
146: return true;
147: }
148: long currentIndex = frameImpl.location().codeIndex();
149:
150: // Code indexes must be treated as unsigned. This matters if you have to compare them.
151: if (currentIndex >= 0 && fCodeIndex >= 0
152: && fCodeIndex + fLength >= 0)
153: return fCodeIndex <= currentIndex
154: && currentIndex < fCodeIndex + fLength;
155:
156: throw new InternalError(
157: JDIMessages.LocalVariableImpl_Code_indexes_are_assumed_to_be_always_positive_4);
158: }
159:
160: /**
161: * @return Returns the name of the local variable.
162: */
163: public String name() {
164: return fName;
165: }
166:
167: /**
168: * @return Returns the signature of the local variable.
169: */
170: public String signature() {
171: return fSignature;
172: }
173:
174: /**
175: * @return Returns the type of the this LocalVariable.
176: */
177: public Type type() throws ClassNotLoadedException {
178: if (fType == null) {
179: fType = TypeImpl.create(virtualMachineImpl(), fSignature,
180: method().declaringType().classLoader());
181: }
182: return fType;
183: }
184:
185: /**
186: * @return Returns a text representation of the declared type of this variable.
187: */
188: public String typeName() {
189: if (fTypeName == null) {
190: fTypeName = TypeImpl.signatureToName(fSignature);
191: }
192: return fTypeName;
193: }
194:
195: /**
196: * @return Returns the tag of the declared type of this variable.
197: */
198: public byte tag() {
199: return TypeImpl.signatureToTag(fSignature);
200: }
201:
202: /**
203: * @return Returns the method that holds the local variable.
204: */
205: public MethodImpl method() {
206: return fMethod;
207: }
208:
209: /**
210: * @return Returns true if the local variable is the 'this' pointer.
211: */
212: public boolean isThis() {
213: return slot() == 0 && !method().isStatic();
214: }
215:
216: /**
217: * @return Returns description of Mirror object.
218: */
219: public String toString() {
220: return fName;
221: }
222:
223: public String genericSignature() {
224: return fGenericSignature;
225: }
226:
227: }
|