aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2011-02-04 11:59:23 -0800
committerAndroid Code Review <code-review@android.com>2011-02-04 11:59:23 -0800
commit294a06e3c2b1e3f88eb220b5992977432de39f9b (patch)
treed3afd408078aa8581513e868da951f3ca8dfc738 /eclipse
parent1d2909b8ff75a392af9231fe848674378b234bb9 (diff)
parent918af5b309f888804ba6152537a4b5a72a6b5b16 (diff)
downloadsdk-294a06e3c2b1e3f88eb220b5992977432de39f9b.zip
sdk-294a06e3c2b1e3f88eb220b5992977432de39f9b.tar.gz
sdk-294a06e3c2b1e3f88eb220b5992977432de39f9b.tar.bz2
Merge "Support onClick method handlers in Hyperlink navigation"
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java103
2 files changed, 103 insertions, 1 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
index 2a87441..9342f3c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
@@ -32,6 +32,7 @@ public class LayoutConstants {
/** The attribute name in a <code>&lt;view class="..."&gt;</code> element. */
public static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+ public static final String ATTR_ON_CLICK = "onClick"; //$NON-NLS-1$
// Some common layout element names
public static final String RELATIVE_LAYOUT = "RelativeLayout"; //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java
index 54567f3..1765112 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/Hyperlinks.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.xml;
import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_CLASS;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_ON_CLICK;
import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.VIEW;
import static com.android.ide.eclipse.adt.AndroidConstants.ANDROID_PKG;
@@ -49,6 +50,7 @@ import com.android.ide.eclipse.adt.io.IFileWrapper;
import com.android.ide.eclipse.adt.io.IFolderWrapper;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
import com.android.sdklib.io.FileWrapper;
import com.android.sdklib.io.IAbstractFile;
import com.android.sdklib.io.IAbstractFolder;
@@ -72,12 +74,23 @@ import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICodeAssist;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.text.JavaWordFinder;
@@ -129,6 +142,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
/**
@@ -172,7 +186,8 @@ public class Hyperlinks {
return false;
}
- if (isClassAttribute(context) || isActivity(context) || isService(context)) {
+ if (isClassAttribute(context) || isOnClickAttribute(context) || isActivity(context)
+ || isService(context)) {
return true;
}
@@ -231,6 +246,15 @@ public class Hyperlinks {
return ATTR_CLASS.equals(attribute.getLocalName()) && VIEW.equals(tag);
}
+ /** Returns true if this represents an onClick attribute specifying a method handler */
+ private static boolean isOnClickAttribute(XmlContext context) {
+ Attr attribute = context.getAttribute();
+ if (attribute == null) {
+ return false;
+ }
+ return ATTR_ON_CLICK.equals(attribute.getLocalName()) && attribute.getValue().length() > 0;
+ }
+
/** Returns true if this represents a {@code <foo.bar.Baz>} custom view class element */
private static boolean isClassElement(XmlContext context) {
if (context.getAttribute() != null) {
@@ -331,6 +355,8 @@ public class Hyperlinks {
return openJavaClass(project, fqcn);
} else if (isClassElement(context) || isClassAttribute(context)) {
return openJavaClass(project, getClassFqcn(context));
+ } else if (isOnClickAttribute(context)) {
+ return openOnClickMethod(project, context.getAttribute().getValue());
} else {
return false;
}
@@ -443,6 +469,81 @@ public class Hyperlinks {
}
/**
+ * Opens a Java method referenced by the given on click attribute method name
+ *
+ * @param project the project containing the click handler
+ * @param method the method name of the on click handler
+ * @return true if the method was opened, false otherwise
+ */
+ public static boolean openOnClickMethod(IProject project, String method) {
+ // Search for the method in the Java index, filtering by the required click handler
+ // method signature (public and has a single View parameter), and narrowing the scope
+ // first to Activity classes, then to the whole workspace.
+ final AtomicBoolean success = new AtomicBoolean(false);
+ SearchRequestor requestor = new SearchRequestor() {
+ @Override
+ public void acceptSearchMatch(SearchMatch match) throws CoreException {
+ Object element = match.getElement();
+ if (element instanceof IMethod) {
+ IMethod methodElement = (IMethod) element;
+ String[] parameterTypes = methodElement.getParameterTypes();
+ if (parameterTypes != null
+ && parameterTypes.length == 1
+ && ("Qandroid.view.View;".equals(parameterTypes[0]) //$NON-NLS-1$
+ || "QView;".equals(parameterTypes[0]))) { //$NON-NLS-1$
+ // Check that it's public
+ if (Flags.isPublic(methodElement.getFlags())) {
+ JavaUI.openInEditor(methodElement);
+ success.getAndSet(true);
+ }
+ }
+ }
+ }
+ };
+ try {
+ IJavaSearchScope scope = null;
+ IType activityType = null;
+ IJavaProject javaProject = (IJavaProject) project.getNature(JavaCore.NATURE_ID);
+ if (javaProject != null) {
+ activityType = javaProject.findType(SdkConstants.CLASS_ACTIVITY);
+ if (activityType != null) {
+ scope = SearchEngine.createHierarchyScope(activityType);
+ }
+ }
+ if (scope == null) {
+ scope = SearchEngine.createWorkspaceScope();
+ }
+
+ SearchParticipant[] participants = new SearchParticipant[] {
+ SearchEngine.getDefaultSearchParticipant()
+ };
+ int matchRule = SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE;
+ SearchPattern pattern = SearchPattern.createPattern("*." + method,
+ IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, matchRule);
+ SearchEngine engine = new SearchEngine();
+ engine.search(pattern, participants, scope, requestor, new NullProgressMonitor());
+
+ boolean ok = success.get();
+ if (!ok && activityType != null) {
+ // TODO: Create a project+dependencies scope and search only that scope
+
+ // Try searching again with a complete workspace scope this time
+ scope = SearchEngine.createWorkspaceScope();
+ engine.search(pattern, participants, scope, requestor, new NullProgressMonitor());
+
+ // TODO: There could be more than one match; add code to consider them all
+ // and pick the most likely candidate and open only that one.
+
+ ok = success.get();
+ }
+ return ok;
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+ return false;
+ }
+
+ /**
* Returns the current configuration, if the associated UI editor has been initialized
* and has an associated configuration
*