aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-09-18 14:19:15 -0700
committerTor Norbye <tnorbye@google.com>2012-09-18 14:19:15 -0700
commit2e3527410003859ee6bcb3a2971d72bcfdbcc829 (patch)
tree62b70635e6e2bc8daa2318235bfe4966f6b3fa07
parent6184f12fa097e1c5bddfe50700b3b0740c736a5a (diff)
downloadsdk-2e3527410003859ee6bcb3a2971d72bcfdbcc829.zip
sdk-2e3527410003859ee6bcb3a2971d72bcfdbcc829.tar.gz
sdk-2e3527410003859ee6bcb3a2971d72bcfdbcc829.tar.bz2
Improvements to stacktrace handler for constructors
This changeset improves the SourceRevealer for certain types of stacktraces: (1) Constructors. If your class initializes fields using code, these are logically grouped into the constructor, but the linenumbers do not fit the constructor source range. Before this CL, this would cause the revealer to show the constructor method rather than the field initialization line. (2) Class initializers. If you clicked on a class initializer method, the IDE would throw an NPE. There's now some special handling to deal with these. Change-Id: Ibb3b7dcf13a69018f75fd12648d1f6b5c45625cc
-rw-r--r--common/src/com/android/SdkConstants.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java43
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java2
3 files changed, 42 insertions, 4 deletions
diff --git a/common/src/com/android/SdkConstants.java b/common/src/com/android/SdkConstants.java
index 1e1d14f..1aa3853 100644
--- a/common/src/com/android/SdkConstants.java
+++ b/common/src/com/android/SdkConstants.java
@@ -957,6 +957,7 @@ public final class SdkConstants {
// Class Names
public static final String CONSTRUCTOR_NAME = "<init>"; //$NON-NLS-1$
+ public static final String CLASS_CONSTRUCTOR = "<clinit>"; //$NON-NLS-1$
public static final String FRAGMENT = "android/app/Fragment"; //$NON-NLS-1$
public static final String FRAGMENT_V4 = "android/support/v4/app/Fragment"; //$NON-NLS-1$
public static final String ANDROID_APP_ACTIVITY = "android/app/Activity"; //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java
index 85f6992..b1b5390 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt;
+import static com.android.SdkConstants.CLASS_CONSTRUCTOR;
import static com.android.SdkConstants.CONSTRUCTOR_NAME;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
@@ -31,8 +32,10 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.SearchEngine;
@@ -138,9 +141,15 @@ public class SourceRevealer implements ISourceRevealer {
// See if the line number looks like it's inside the given method
ISourceRange sourceRange = method.getSourceRange();
IRegion region = AdtUtils.getRegionOfLine(file, lineNumber - 1);
- if (region != null
- && region.getOffset() >= sourceRange.getOffset()
- && region.getOffset() < sourceRange.getOffset()
+ // When fields are initialized with code, this logically belongs
+ // to the constructor, but the line numbers are outside of the
+ // constructor. In this case we'll trust the line number rather
+ // than the method range.
+ boolean isConstructor = fqmn.endsWith(CONSTRUCTOR_NAME);
+ if (isConstructor
+ || region != null
+ && region.getOffset() >= sourceRange.getOffset()
+ && region.getOffset() < sourceRange.getOffset()
+ sourceRange.getLength()) {
// Yes: use the line number instead
if (perspective != null) {
@@ -167,6 +176,29 @@ public class SourceRevealer implements ISourceRevealer {
if (fileMatches.size() > 0) {
return revealLineMatch(fileMatches, fileName, lineNumber, perspective);
} else {
+ // Last ditch effort: attempt to look up the class corresponding to the fqn
+ // and jump to the line there
+ if (fileMatches.isEmpty() && fqmn.indexOf('.') != -1) {
+ String className = fqmn.substring(0, fqmn.lastIndexOf('.'));
+ for (IJavaProject project : BaseProjectHelper.getAndroidProjects(null)) {
+ IType type;
+ try {
+ type = project.findType(className);
+ if (type != null && type.exists()) {
+ IResource resource = type.getResource();
+ if (resource instanceof IFile) {
+ if (perspective != null) {
+ SourceRevealer.switchToPerspective(perspective);
+ }
+ return displayFile((IFile) resource, lineNumber);
+ }
+ }
+ } catch (JavaModelException e) {
+ AdtPlugin.log(e, null);
+ }
+ }
+ }
+
return false;
}
}
@@ -349,6 +381,11 @@ public class SourceRevealer implements ISourceRevealer {
return searchForPattern(fqmn, IJavaSearchConstants.CONSTRUCTOR,
MATCH_IS_METHOD_PREDICATE);
}
+ if (fqmn.endsWith(CLASS_CONSTRUCTOR)) {
+ // Don't try to search for class init methods: Eclipse will throw NPEs if you do
+ return Collections.emptyList();
+ }
+
return searchForPattern(fqmn, IJavaSearchConstants.METHOD, MATCH_IS_METHOD_PREDICATE);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java
index ed93b73..55cad2b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java
@@ -409,7 +409,7 @@ public class ManifestInfo {
* Returns the minimum SDK version name (which may not be a numeric string, e.g.
* it could be a codename). It will never be null or empty; if no min sdk version
* was specified in the manifest, the return value will be "1". Use
- * {@link #getCodeName()} instead if you want to look up whether there is a code name.
+ * {@link #getMinSdkCodeName()} instead if you want to look up whether there is a code name.
*
* @return the minimum SDK version
*/