|
30 | 30 | import org.eclipse.jdt.core.IPackageFragmentRoot; |
31 | 31 | import org.eclipse.jdt.core.JavaCore; |
32 | 32 | import org.eclipse.jdt.core.JavaModelException; |
| 33 | +import org.eclipse.jdt.core.Signature; |
33 | 34 | import org.eclipse.jdt.launching.IRuntimeClasspathEntry; |
34 | 35 | import org.eclipse.jdt.launching.JavaRuntime; |
35 | 36 | import org.eclipse.jdt.launching.sourcelookup.containers.JavaProjectSourceContainer; |
36 | 37 | import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer; |
37 | 38 |
|
| 39 | +import com.microsoft.java.debug.core.DebugException; |
| 40 | +import com.microsoft.java.debug.core.StackFrameUtility; |
38 | 41 | import com.sun.jdi.AbsentInformationException; |
| 42 | +import com.sun.jdi.ArrayType; |
| 43 | +import com.sun.jdi.ClassNotLoadedException; |
39 | 44 | import com.sun.jdi.Location; |
| 45 | +import com.sun.jdi.ReferenceType; |
40 | 46 | import com.sun.jdi.StackFrame; |
| 47 | +import com.sun.jdi.Type; |
41 | 48 |
|
42 | 49 | public class JdtUtils { |
43 | 50 |
|
@@ -235,29 +242,98 @@ public static Object findSourceElement(String sourcePath, ISourceContainer[] con |
235 | 242 | } |
236 | 243 |
|
237 | 244 | /** |
238 | | - * Given a stack frame, find the target project that the associated source file belongs to. |
| 245 | + * Given a stack frame, find the target java project that the associated source file belongs to. |
239 | 246 | * |
240 | 247 | * @param stackFrame |
241 | 248 | * the stack frame. |
242 | 249 | * @param containers |
243 | 250 | * the source container list. |
244 | | - * @return the context project. |
| 251 | + * @return the java project. |
245 | 252 | */ |
246 | | - public static IProject findProject(StackFrame stackFrame, ISourceContainer[] containers) { |
| 253 | + public static IJavaProject findProject(StackFrame stackFrame, ISourceContainer[] containers) { |
247 | 254 | Location location = stackFrame.location(); |
248 | 255 | try { |
249 | 256 | Object sourceElement = findSourceElement(location.sourcePath(), containers); |
250 | 257 | if (sourceElement instanceof IResource) { |
251 | | - return ((IResource) sourceElement).getProject(); |
| 258 | + return JavaCore.create(((IResource) sourceElement).getProject()); |
252 | 259 | } else if (sourceElement instanceof IClassFile) { |
253 | 260 | IJavaProject javaProject = ((IClassFile) sourceElement).getJavaProject(); |
254 | 261 | if (javaProject != null) { |
255 | | - return javaProject.getProject(); |
| 262 | + return javaProject; |
256 | 263 | } |
257 | 264 | } |
258 | 265 | } catch (AbsentInformationException e) { |
259 | 266 | // When the compiled .class file doesn't contain debug source information, return null. |
260 | 267 | } |
261 | 268 | return null; |
262 | 269 | } |
| 270 | + |
| 271 | + /** |
| 272 | + * Given a stack frame, get the fully qualified type name that associated with the frame. |
| 273 | + * @param frame the stack frame |
| 274 | + * @return the fully qualified type name |
| 275 | + * @throws DebugException debug exception |
| 276 | + */ |
| 277 | + public static String getDeclaringTypeName(StackFrame frame) throws DebugException { |
| 278 | + return getGenericName(StackFrameUtility.getDeclaringType(frame)); |
| 279 | + } |
| 280 | + |
| 281 | + private static String getGenericName(ReferenceType type) throws DebugException { |
| 282 | + if (type instanceof ArrayType) { |
| 283 | + try { |
| 284 | + Type componentType; |
| 285 | + componentType = ((ArrayType) type).componentType(); |
| 286 | + if (componentType instanceof ReferenceType) { |
| 287 | + return getGenericName((ReferenceType) componentType) + "[]"; //$NON-NLS-1$ |
| 288 | + } |
| 289 | + return type.name(); |
| 290 | + } catch (ClassNotLoadedException e) { |
| 291 | + // we cannot create the generic name using the component type, |
| 292 | + // just try to create one with the information |
| 293 | + } |
| 294 | + } |
| 295 | + String signature = type.signature(); |
| 296 | + StringBuffer res = new StringBuffer(getTypeName(signature)); |
| 297 | + String genericSignature = type.genericSignature(); |
| 298 | + if (genericSignature != null) { |
| 299 | + String[] typeParameters = Signature.getTypeParameters(genericSignature); |
| 300 | + if (typeParameters.length > 0) { |
| 301 | + res.append('<').append(Signature.getTypeVariable(typeParameters[0])); |
| 302 | + for (int i = 1; i < typeParameters.length; i++) { |
| 303 | + res.append(',').append(Signature.getTypeVariable(typeParameters[i])); |
| 304 | + } |
| 305 | + res.append('>'); |
| 306 | + } |
| 307 | + } |
| 308 | + return res.toString(); |
| 309 | + } |
| 310 | + |
| 311 | + private static String getTypeName(String genericTypeSignature) { |
| 312 | + int arrayDimension = 0; |
| 313 | + while (genericTypeSignature.charAt(arrayDimension) == '[') { |
| 314 | + arrayDimension++; |
| 315 | + } |
| 316 | + int parameterStart = genericTypeSignature.indexOf('<'); |
| 317 | + StringBuffer name = new StringBuffer(); |
| 318 | + if (parameterStart < 0) { |
| 319 | + name.append(genericTypeSignature.substring(arrayDimension + 1, genericTypeSignature.length() - 1) |
| 320 | + .replace('/', '.')); |
| 321 | + } else { |
| 322 | + if (parameterStart != 0) { |
| 323 | + name.append(genericTypeSignature.substring(arrayDimension + 1, parameterStart).replace('/', '.')); |
| 324 | + } |
| 325 | + try { |
| 326 | + String sig = Signature.toString(genericTypeSignature) |
| 327 | + .substring(Math.max(parameterStart - 1, 0) - arrayDimension); |
| 328 | + name.append(sig.replace('/', '.')); |
| 329 | + } catch (IllegalArgumentException iae) { |
| 330 | + // do nothing |
| 331 | + name.append(genericTypeSignature); |
| 332 | + } |
| 333 | + } |
| 334 | + for (int i = 0; i < arrayDimension; i++) { |
| 335 | + name.append("[]"); //$NON-NLS-1$ |
| 336 | + } |
| 337 | + return name.toString(); |
| 338 | + } |
263 | 339 | } |
0 commit comments