blob: fb32e7a6ace5306c061abcb0d1f0455c5c392046 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.tools.jdi;
27import com.sun.jdi.*;
28
29public class LocalVariableImpl extends MirrorImpl
30 implements LocalVariable, ValueContainer
31{
32 private final Method method;
33 private final int slot;
34 private final Location scopeStart;
35 private final Location scopeEnd;
36 private final String name;
37 private final String signature;
38 private String genericSignature = null;
39
40 LocalVariableImpl(VirtualMachine vm, Method method,
41 int slot, Location scopeStart, Location scopeEnd,
42 String name, String signature,
43 String genericSignature) {
44 super(vm);
45 this.method = method;
46 this.slot = slot;
47 this.scopeStart = scopeStart;
48 this.scopeEnd = scopeEnd;
49 this.name = name;
50 this.signature = signature;
51 if (genericSignature != null && genericSignature.length() > 0) {
52 this.genericSignature = genericSignature;
53 } else {
54 // The Spec says to return null for non-generic types
55 this.genericSignature = null;
56 }
57 }
58
59 public boolean equals(Object obj) {
60 if ((obj != null) && (obj instanceof LocalVariableImpl)) {
61 LocalVariableImpl other = (LocalVariableImpl)obj;
62 return ((slot() == other.slot()) &&
63 (scopeStart != null) &&
64 (scopeStart.equals(other.scopeStart)) &&
65 (super.equals(obj)));
66 } else {
67 return false;
68 }
69 }
70
71 public int hashCode() {
72 /*
73 * TO DO: Better hash code
74 */
75 return ((scopeStart.hashCode() << 4) + slot());
76 }
77
78 public int compareTo(LocalVariable object) {
79 LocalVariableImpl other = (LocalVariableImpl)object;
80
81 int rc = scopeStart.compareTo(other.scopeStart);
82 if (rc == 0) {
83 rc = slot() - other.slot();
84 }
85 return rc;
86 }
87
88 public String name() {
89 return name;
90 }
91
92 /**
93 * @return a text representation of the declared type
94 * of this variable.
95 */
96 public String typeName() {
97 JNITypeParser parser = new JNITypeParser(signature);
98 return parser.typeName();
99 }
100
101 public Type type() throws ClassNotLoadedException {
102 return findType(signature());
103 }
104
105 public Type findType(String signature) throws ClassNotLoadedException {
106 ReferenceTypeImpl enclosing = (ReferenceTypeImpl)method.declaringType();
107 return enclosing.findType(signature);
108 }
109
110 public String signature() {
111 return signature;
112 }
113
114 public String genericSignature() {
115 return genericSignature;
116 }
117
118 public boolean isVisible(StackFrame frame) {
119 validateMirror(frame);
120 Method frameMethod = frame.location().method();
121
122 if (!frameMethod.equals(method)) {
123 throw new IllegalArgumentException(
124 "frame method different than variable's method");
125 }
126
127 // this is here to cover the possibility that we will
128 // allow LocalVariables for native methods. If we do
129 // so we will have to re-examinine this.
130 if (frameMethod.isNative()) {
131 return false;
132 }
133
134 return ((scopeStart.compareTo(frame.location()) <= 0)
135 && (scopeEnd.compareTo(frame.location()) >= 0));
136 }
137
138 public boolean isArgument() {
139 try {
140 MethodImpl method = (MethodImpl)scopeStart.method();
141 return (slot < method.argSlotCount());
142 } catch (AbsentInformationException e) {
143 // If this variable object exists, there shouldn't be absent info
144 throw new InternalException();
145 }
146 }
147
148 int slot() {
149 return slot;
150 }
151
152 /*
153 * Compilers/VMs can have byte code ranges for variables of the
154 * same names that overlap. This is because the byte code ranges
155 * aren't necessarily scopes; they may have more to do with the
156 * lifetime of the variable's slot, depending on implementation.
157 *
158 * This method determines whether this variable hides an
159 * identically named variable; ie, their byte code ranges overlap
160 * this one starts after the given one. If it returns true this
161 * variable should be preferred when looking for a single variable
162 * with its name when both variables are visible.
163 */
164 boolean hides(LocalVariable other) {
165 LocalVariableImpl otherImpl = (LocalVariableImpl)other;
166 if (!method.equals(otherImpl.method) ||
167 !name.equals(otherImpl.name)) {
168 return false;
169 } else {
170 return (scopeStart.compareTo(otherImpl.scopeStart) > 0);
171 }
172 }
173
174 public String toString() {
175 return name() + " in " + method.toString() +
176 "@" + scopeStart.toString();
177 }
178}