AI 146570: am: CL 146336 am: CL 146335 ADT: Rework the Manifest class browser.

For ADT #1603194, it is desirable to select the Instrumentation
  Runner class from the android.jar. The class browser was filtering
  it out. The class browser has been changed like this:
  - include all source & jar package roots
  - a checkbox let the user toggle between searching only sources
  (of the project) or anything in the classpath (thus include jars.)
  The default is to include everything for the instrumentation and only
  the source for other browsers.
  Also improved a bit the filter by not iterating over the hierarchy
  and filtering out abstract classes (which was not needed before.)
  Original author: raphael
  Merged from: //branches/cupcake/...
  Original author: android-build

Automated import of CL 146570
This commit is contained in:
Raphael Moll
2009-04-18 21:01:33 -07:00
committed by The Android Open Source Project
parent d3b2e5bb5e
commit 0930502ee4
5 changed files with 128 additions and 79 deletions

View File

@@ -205,6 +205,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
overrideClassName(overrides, "receiver", AndroidConstants.CLASS_BROADCASTRECEIVER); //$NON-NLS-1$ overrideClassName(overrides, "receiver", AndroidConstants.CLASS_BROADCASTRECEIVER); //$NON-NLS-1$
overrideClassName(overrides, "service", AndroidConstants.CLASS_SERVICE); //$NON-NLS-1$ overrideClassName(overrides, "service", AndroidConstants.CLASS_SERVICE); //$NON-NLS-1$
overrideClassName(overrides, "provider", AndroidConstants.CLASS_CONTENTPROVIDER); //$NON-NLS-1$ overrideClassName(overrides, "provider", AndroidConstants.CLASS_CONTENTPROVIDER); //$NON-NLS-1$
overrideClassName(overrides, "instrumentation", AndroidConstants.CLASS_INSTRUMENTATION); //$NON-NLS-1$
// -- list element nodes already created -- // -- list element nodes already created --
// These elements are referenced by already opened editors, so we want to update them // These elements are referenced by already opened editors, so we want to update them
@@ -244,27 +245,42 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
new DescriptorsUtils.ITextAttributeCreator() { new DescriptorsUtils.ITextAttributeCreator() {
public TextAttributeDescriptor create(String xmlName, String uiName, String nsUri, public TextAttributeDescriptor create(String xmlName, String uiName, String nsUri,
String tooltip) { String tooltip) {
uiName += "*"; //$NON-NLS-1$
if (AndroidConstants.CLASS_ACTIVITY.equals(className)) { if (AndroidConstants.CLASS_ACTIVITY.equals(className)) {
return new ClassAttributeDescriptor( return new ClassAttributeDescriptor(
className, className,
PostActivityCreationAction.getAction(), PostActivityCreationAction.getAction(),
xmlName, uiName + "*", //$NON-NLS-1$ xmlName,
uiName,
nsUri, nsUri,
tooltip, tooltip,
true /*mandatory */); true /*mandatory */,
true /*defaultToProjectOnly*/);
} else if (AndroidConstants.CLASS_BROADCASTRECEIVER.equals(className)) { } else if (AndroidConstants.CLASS_BROADCASTRECEIVER.equals(className)) {
return new ClassAttributeDescriptor( return new ClassAttributeDescriptor(
className, className,
PostReceiverCreationAction.getAction(), PostReceiverCreationAction.getAction(),
xmlName, uiName + "*", //$NON-NLS-1$ xmlName,
uiName,
nsUri, nsUri,
tooltip, tooltip,
true /*mandatory */); true /*mandatory */,
true /*defaultToProjectOnly*/);
} else if (AndroidConstants.CLASS_INSTRUMENTATION.equals(className)) {
return new ClassAttributeDescriptor(
className,
null, // no post action
xmlName,
uiName,
nsUri,
tooltip,
true /*mandatory */,
false /*defaultToProjectOnly*/);
} else { } else {
return new ClassAttributeDescriptor( return new ClassAttributeDescriptor(
className, className,
xmlName, uiName + "*", //$NON-NLS-1$ xmlName,
uiName,
nsUri, nsUri,
tooltip, tooltip,
true /*mandatory */); true /*mandatory */);

View File

@@ -39,6 +39,7 @@ public class ApplicationAttributeDescriptor extends TextAttributeDescriptor {
@Override @Override
public UiAttributeNode createUiNode(UiElementNode uiParent) { public UiAttributeNode createUiNode(UiElementNode uiParent) {
return new UiClassAttributeNode("android.app.Application", //$NON-NLS-1$ return new UiClassAttributeNode("android.app.Application", //$NON-NLS-1$
null /* postCreationAction */, false /* mandatory */, this, uiParent); null /* postCreationAction */, false /* mandatory */, this, uiParent,
true /*defaultToProjectOnly*/);
} }
} }

View File

@@ -37,6 +37,8 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor {
/** indicates if the class parameter is mandatory */ /** indicates if the class parameter is mandatory */
boolean mMandatory; boolean mMandatory;
private final boolean mDefaultToProjectOnly;
/** /**
* Creates a new {@link ClassAttributeDescriptor} * Creates a new {@link ClassAttributeDescriptor}
* @param superClassName the fully qualified name of the superclass of the class represented * @param superClassName the fully qualified name of the superclass of the class represented
@@ -49,10 +51,14 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor {
* @param mandatory indicates if the class attribute is mandatory. * @param mandatory indicates if the class attribute is mandatory.
*/ */
public ClassAttributeDescriptor(String superClassName, public ClassAttributeDescriptor(String superClassName,
String xmlLocalName, String uiName, String nsUri, String xmlLocalName,
String tooltip, boolean mandatory) { String uiName,
String nsUri,
String tooltip,
boolean mandatory) {
super(xmlLocalName, uiName, nsUri, tooltip); super(xmlLocalName, uiName, nsUri, tooltip);
mSuperClassName = superClassName; mSuperClassName = superClassName;
mDefaultToProjectOnly = true;
} }
/** /**
@@ -67,14 +73,21 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor {
* See {@link SdkConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip A non-empty tooltip string or null. * @param tooltip A non-empty tooltip string or null.
* @param mandatory indicates if the class attribute is mandatory. * @param mandatory indicates if the class attribute is mandatory.
* @param defaultToProjectOnly True if only classes from the sources of this project should
* be shown by default in the class browser.
*/ */
public ClassAttributeDescriptor(String superClassName, public ClassAttributeDescriptor(String superClassName,
IPostTypeCreationAction postCreationAction, IPostTypeCreationAction postCreationAction,
String xmlLocalName, String uiName, String nsUri, String xmlLocalName,
String tooltip, boolean mandatory) { String uiName,
String nsUri,
String tooltip,
boolean mandatory,
boolean defaultToProjectOnly) {
super(xmlLocalName, uiName, nsUri, tooltip); super(xmlLocalName, uiName, nsUri, tooltip);
mSuperClassName = superClassName; mSuperClassName = superClassName;
mPostCreationAction = postCreationAction; mPostCreationAction = postCreationAction;
mDefaultToProjectOnly = defaultToProjectOnly;
} }
/** /**
@@ -83,6 +96,6 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor {
@Override @Override
public UiAttributeNode createUiNode(UiElementNode uiParent) { public UiAttributeNode createUiNode(UiElementNode uiParent) {
return new UiClassAttributeNode(mSuperClassName, mPostCreationAction, return new UiClassAttributeNode(mSuperClassName, mPostCreationAction,
mMandatory, this, uiParent); mMandatory, this, uiParent, mDefaultToProjectOnly);
} }
} }

View File

@@ -1,46 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.editors.manifest.descriptors;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.manifest.model.UiClassAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
/**
* Describes a 'Instrumentation' class XML attribute. It is displayed by a
* {@link UiClassAttributeNode}, that restricts creation and selection to classes inheriting from
* android.app.Instrumentation.
*/
public class InstrumentationAttributeDescriptor extends TextAttributeDescriptor {
public InstrumentationAttributeDescriptor(String xmlLocalName, String uiName, String nsUri,
String tooltip) {
super(xmlLocalName, uiName, nsUri, tooltip);
}
/**
* @return A new {@link UiClassAttributeNode} linked to this descriptor.
*/
@Override
public UiAttributeNode createUiNode(UiElementNode uiParent) {
return new UiClassAttributeNode(AndroidConstants.CLASS_INSTRUMENTATION,
null /* postCreationAction */, true /* mandatory */, this, uiParent);
}
}

View File

@@ -16,6 +16,7 @@
package com.android.ide.eclipse.editors.manifest.model; package com.android.ide.eclipse.editors.manifest.model;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser; import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.BaseProjectHelper; import com.android.ide.eclipse.common.project.BaseProjectHelper;
@@ -31,6 +32,7 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IJavaProject;
@@ -63,6 +65,7 @@ import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IFileEditorInput;
@@ -90,20 +93,28 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
private String mReferenceClass; private String mReferenceClass;
private IPostTypeCreationAction mPostCreationAction; private IPostTypeCreationAction mPostCreationAction;
private boolean mMandatory; private boolean mMandatory;
private final boolean mDefaultToProjectOnly;
private class HierarchyTypeSelection extends TypeSelectionExtension { private class HierarchyTypeSelection extends TypeSelectionExtension {
private IJavaProject mJavaProject; private IJavaProject mJavaProject;
private IType mReferenceType;
private Button mProjectOnly;
private boolean mUseProjectOnly;
public HierarchyTypeSelection(IProject project, String referenceClass) { public HierarchyTypeSelection(IProject project, String referenceClass)
throws JavaModelException {
mJavaProject = JavaCore.create(project); mJavaProject = JavaCore.create(project);
mReferenceClass = referenceClass; mReferenceType = mJavaProject.findType(referenceClass);
} }
@Override @Override
public ITypeInfoFilterExtension getFilterExtension() { public ITypeInfoFilterExtension getFilterExtension() {
return new ITypeInfoFilterExtension() { return new ITypeInfoFilterExtension() {
public boolean select(ITypeInfoRequestor typeInfoRequestor) { public boolean select(ITypeInfoRequestor typeInfoRequestor) {
boolean projectOnly = mUseProjectOnly;
String packageName = typeInfoRequestor.getPackageName(); String packageName = typeInfoRequestor.getPackageName();
String typeName = typeInfoRequestor.getTypeName(); String typeName = typeInfoRequestor.getTypeName();
String enclosingType = typeInfoRequestor.getEnclosingName(); String enclosingType = typeInfoRequestor.getEnclosingName();
@@ -121,19 +132,35 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
try { try {
IType type = mJavaProject.findType(className); IType type = mJavaProject.findType(className);
if (type != null) {
// get the type hierarchy
ITypeHierarchy hierarchy = type.newSupertypeHierarchy(
new NullProgressMonitor());
// if the super class is not the reference class, it may inherit from if (type == null) {
// it so we get its supertype. At some point it will be null and we return false;
// will return false; }
IType superType = type;
while ((superType = hierarchy.getSuperclass(superType)) != null) { // don't display abstract classes
if (mReferenceClass.equals(superType.getFullyQualifiedName())) { if ((type.getFlags() & Flags.AccAbstract) != 0) {
return true; return false;
} }
// if project-only is selected, make sure the package fragment is
// an actual source (thus "from this project").
if (projectOnly) {
IPackageFragment frag = type.getPackageFragment();
if (frag == null || frag.getKind() != IPackageFragmentRoot.K_SOURCE) {
return false;
}
}
// get the type hierarchy and reference type is one of the super classes.
ITypeHierarchy hierarchy = type.newSupertypeHierarchy(
new NullProgressMonitor());
IType[] supertypes = hierarchy.getAllSupertypes(type);
int n = supertypes.length;
for (int i = 0; i < n; i++) {
IType st = supertypes[i];
if (mReferenceType.equals(st)) {
return true;
} }
} }
} catch (JavaModelException e) { } catch (JavaModelException e) {
@@ -143,6 +170,29 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
} }
}; };
} }
@Override
public Control createContentArea(Composite parent) {
mProjectOnly = new Button(parent, SWT.CHECK);
mProjectOnly.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mProjectOnly.setText(String.format("Display classes from sources of project '%s' only",
mJavaProject.getProject().getName()));
mUseProjectOnly = mDefaultToProjectOnly;
mProjectOnly.setSelection(mUseProjectOnly);
mProjectOnly.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
super.widgetSelected(e);
mUseProjectOnly = mProjectOnly.getSelection();
getTypeSelectionComponent().triggerSearch();
}
});
return super.createContentArea(parent);
}
} }
/** /**
@@ -165,14 +215,18 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
* modification of the class. * modification of the class.
* @param mandatory indicates if the class value is mandatory * @param mandatory indicates if the class value is mandatory
* @param attributeDescriptor the {@link AttributeDescriptor} object linked to the Ui Node. * @param attributeDescriptor the {@link AttributeDescriptor} object linked to the Ui Node.
* @param defaultToProjectOnly When true display classes of this project only by default.
* When false any class path will be considered. The user can always toggle this.
*/ */
public UiClassAttributeNode(String referenceClass, IPostTypeCreationAction postCreationAction, public UiClassAttributeNode(String referenceClass, IPostTypeCreationAction postCreationAction,
boolean mandatory, AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { boolean mandatory, AttributeDescriptor attributeDescriptor, UiElementNode uiParent,
boolean defaultToProjectOnly) {
super(attributeDescriptor, uiParent); super(attributeDescriptor, uiParent);
mReferenceClass = referenceClass; mReferenceClass = referenceClass;
mPostCreationAction = postCreationAction; mPostCreationAction = postCreationAction;
mMandatory = mandatory; mMandatory = mandatory;
mDefaultToProjectOnly = defaultToProjectOnly;
} }
/* (non-java doc) /* (non-java doc)
@@ -292,8 +346,11 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
// Create a search scope including only the source folder of the current // Create a search scope including only the source folder of the current
// project. // project.
IPackageFragmentRoot[] packageFragmentRoots = getPackageFragmentRoots(project,
true /*include_containers*/);
IJavaSearchScope scope = SearchEngine.createJavaSearchScope( IJavaSearchScope scope = SearchEngine.createJavaSearchScope(
getPackageFragmentRoots(project), false); packageFragmentRoots,
false);
try { try {
SelectionDialog dlg = JavaUI.createTypeDialog(text.getShell(), SelectionDialog dlg = JavaUI.createTypeDialog(text.getShell(),
@@ -301,7 +358,7 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
scope, scope,
IJavaElementSearchConstants.CONSIDER_CLASSES, // style IJavaElementSearchConstants.CONSIDER_CLASSES, // style
false, // no multiple selection false, // no multiple selection
"**", //$NON-NLS-1$ //filter "**", //$NON-NLS-1$ //filter
new HierarchyTypeSelection(project, mReferenceClass)); new HierarchyTypeSelection(project, mReferenceClass));
dlg.setMessage(String.format("Select class name for element %1$s:", dlg.setMessage(String.format("Select class name for element %1$s:",
getUiParent().getBreadcrumbTrailDescription(false /* include_root */))); getUiParent().getBreadcrumbTrailDescription(false /* include_root */)));
@@ -316,6 +373,7 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
} }
} }
} catch (JavaModelException e1) { } catch (JavaModelException e1) {
AdtPlugin.log(e1, "UiClassAttributeNode HandleBrowser failed");
} }
} }
} }
@@ -363,7 +421,9 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
} }
} }
} catch (JavaModelException e) { } catch (JavaModelException e) {
AdtPlugin.log(e, "UiClassAttributeNode HandleLabel failed");
} catch (PartInitException e) { } catch (PartInitException e) {
AdtPlugin.log(e, "UiClassAttributeNode HandleLabel failed");
} }
} }
} }
@@ -403,16 +463,20 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
* Computes and return the {@link IPackageFragmentRoot}s corresponding to the source folders of * Computes and return the {@link IPackageFragmentRoot}s corresponding to the source folders of
* the specified project. * the specified project.
* @param project the project * @param project the project
* @param b
* @return an array of IPackageFragmentRoot. * @return an array of IPackageFragmentRoot.
*/ */
private IPackageFragmentRoot[] getPackageFragmentRoots(IProject project) { private IPackageFragmentRoot[] getPackageFragmentRoots(IProject project,
boolean include_containers) {
ArrayList<IPackageFragmentRoot> result = new ArrayList<IPackageFragmentRoot>(); ArrayList<IPackageFragmentRoot> result = new ArrayList<IPackageFragmentRoot>();
try { try {
IJavaProject javaProject = JavaCore.create(project); IJavaProject javaProject = JavaCore.create(project);
IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots(); IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
for (int i = 0; i < roots.length; i++) { for (int i = 0; i < roots.length; i++) {
IClasspathEntry entry = roots[i].getRawClasspathEntry(); IClasspathEntry entry = roots[i].getRawClasspathEntry();
if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE ||
(include_containers &&
entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER)) {
result.add(roots[i]); result.add(roots[i]);
} }
} }
@@ -457,7 +521,8 @@ public class UiClassAttributeNode extends UiTextAttributeNode {
page.setSuperClass(mReferenceClass, true /* canBeModified */); page.setSuperClass(mReferenceClass, true /* canBeModified */);
// get the source folders as java elements. // get the source folders as java elements.
IPackageFragmentRoot[] roots = getPackageFragmentRoots(getProject()); IPackageFragmentRoot[] roots = getPackageFragmentRoots(getProject(),
true /*include_containers*/);
IPackageFragmentRoot currentRoot = null; IPackageFragmentRoot currentRoot = null;
IPackageFragment currentFragment = null; IPackageFragment currentFragment = null;