aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/dictionary.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java310
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidSourceViewerConfig.java93
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/AttributeDescriptor.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java113
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java376
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java152
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java56
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-actual-applyCompletion1.xml19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion1.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion10.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11a.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11b.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion12.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion2.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion3.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion4.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion5.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion6.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7a.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7b.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion8.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion9.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion1.txt3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion10.txt10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt60
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt60
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion2.txt4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion3.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion4.txt7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion5.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion6.txt22
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7a.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7b.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion8.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion9.txt4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1.xml19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13a.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13b.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13c.diff4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13a.txt13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13b.txt4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13c.txt12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2.xml5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion14.txt10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion15.txt3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion16.txt14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion17.txt7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt27
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest.xml19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-changeLayout1a.xml2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1b-expected-changeLayout1b.xml2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-changeLayout5.xml2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java33
60 files changed, 1384 insertions, 193 deletions
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index b92ceb2..b9ccb29 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -205,6 +205,7 @@ tooltip
tooltips
traceview
translucency
+typo
ui
uncomment
undescribed
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java
index c8ce3ac..47fcbd7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/AbsoluteLayoutRule.java
@@ -17,7 +17,7 @@
package com.android.ide.common.layout;
import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
-import static com.android.ide.common.layout.LayoutConstants.VALUE_N_DIP;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_N_DP;
import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.DropFeedback;
@@ -190,9 +190,9 @@ public class AbsoluteLayoutRule extends BaseLayoutRule {
}
newChild.setAttribute(ANDROID_URI, "layout_x", //$NON-NLS-1$
- String.format(VALUE_N_DIP, x));
+ String.format(VALUE_N_DP, x));
newChild.setAttribute(ANDROID_URI, "layout_y", //$NON-NLS-1$
- String.format(VALUE_N_DIP, y));
+ String.format(VALUE_N_DP, y));
addInnerElements(newChild, element, idMap);
}
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 a148836..092b0a5 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
@@ -52,6 +52,7 @@ public class LayoutConstants {
public static final String ATTR_TEXT = "text"; //$NON-NLS-1$
public static final String ATTR_ID = "id"; //$NON-NLS-1$
+ public static final String ATTR_STYLE = "style"; //$NON-NLS-1$
public static final String ATTR_HANDLE = "handle"; //$NON-NLS-1$
public static final String ATTR_CONTENT = "content"; //$NON-NLS-1$
public static final String ATTR_CHECKED = "checked"; //$NON-NLS-1$
@@ -98,7 +99,7 @@ public class LayoutConstants {
public static final String VALUE_FILL_PARENT = "fill_parent"; //$NON-NLS-1$
public static final String VALUE_TRUE = "true"; //$NON-NLS-1$
public static final String VALUE_FALSE= "false"; //$NON-NLS-1$
- public static final String VALUE_N_DIP = "%ddip"; //$NON-NLS-1$
+ public static final String VALUE_N_DP = "%ddp"; //$NON-NLS-1$
public static final String VALUE_CENTER_VERTICAL = "centerVertical"; //$NON-NLS-1$
public static final String VALUE_CENTER_IN_PARENT = "centerInParent"; //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java
index 9bc09ec..61c34bf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssist.java
@@ -16,6 +16,10 @@
package com.android.ide.eclipse.adt.internal.editors;
+import static com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor.ATTRIBUTE_ICON_FILENAME;
+
+import com.android.ide.common.api.IAttributeInfo;
+import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
@@ -32,10 +36,12 @@ import com.android.ide.eclipse.adt.internal.editors.uimodel.UiFlagAttributeNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiResourceAttributeNode;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.sdklib.SdkConstants;
+import com.android.util.Pair;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.contentassist.CompletionProposal;
@@ -50,12 +56,15 @@ import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
+import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -148,29 +157,51 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
return null;
}
+ boolean isNew = true;
+ int replaceLength = 0;
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
parent = currentNode.getNodeName();
- if (wordPrefix.equals(parent)) {
+ // We're not editing the current node name, so we might be editing its
+ // attributes instead...
+ AttribInfo info = parseAttributeInfo(viewer, offset);
+ if (info != null) {
+ isAttribute = true;
+ // We're editing attributes in an element node (either the attributes' names
+ // or their values).
+ choices = getChoicesForAttribute(parent, currentNode, currentUiNode, info);
+
+ if (info.isInValue) {
+ // Note - this must be done before the prefix correction below since
+ // otherwise, when the prefix gets cleared out (for a flag list) we
+ // end up with a wrong count for the prefix length
+ Element element = (Element) currentNode;
+ String attribute = element.getAttribute(info.name);
+ if (attribute != null) { // Eclipse DOM bug
+ replaceLength = attribute.length() - wordPrefix.length();
+ if (info.needTag != 0) {
+ replaceLength += 2;
+ }
+ }
+ } else {
+ replaceLength = info.name.length() - wordPrefix.length();
+ }
+
+ if (info.correctedPrefix != null) {
+ wordPrefix = info.correctedPrefix;
+ }
+ needTag = info.needTag;
+ isNew = info.name.length() == 0;
+ } else if (parent.startsWith(wordPrefix)) {
// We are still editing the element's tag name, not the attributes
// (the element's tag name may not even be complete)
isElement = true;
choices = getChoicesForElement(parent, currentNode);
- } else {
- // We're not editing the current node name, so we might be editing its
- // attributes instead...
- isAttribute = true;
- AttribInfo info = parseAttributeInfo(viewer, offset);
- if (info != null) {
- // We're editing attributes in an element node (either the attributes' names
- // or their values).
- choices = getChoicesForAttribute(parent, currentNode, currentUiNode, info);
-
- if (info.correctedPrefix != null) {
- wordPrefix = info.correctedPrefix;
- }
- needTag = info.needTag;
+ replaceLength = parent.length() - wordPrefix.length();
+ if (wordPrefix.length() == 0) {
+ replaceLength = 0; // Only do this if on <
}
+ isNew = replaceLength == 0;
}
} else if (currentNode.getNodeType() == Node.TEXT_NODE) {
isElement = true;
@@ -201,7 +232,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
}
return computeProposals(offset, currentNode, choices, wordPrefix, needTag,
- isAttribute, selectionLength);
+ isAttribute, isNew, selectionLength + replaceLength);
}
/**
@@ -345,24 +376,31 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
// A "flag" can consist of several values separated by "or" (|).
// If the correct prefix contains such a pipe character, we change
// it so that only the currently edited value is completed.
- pos = value.indexOf('|');
+ pos = value.lastIndexOf('|');
if (pos >= 0) {
attrInfo.correctedPrefix = value = value.substring(pos + 1);
attrInfo.needTag = 0;
}
}
- }
- if (choices == null && value.startsWith("@")) { //$NON-NLS-1$
- // Special case: If the attribute value looks like a reference to a
- // resource, offer to complete it, since in many cases our metadata
- // does not correctly state whether a resource value is allowed. We don't
- // offer these for an empty completion context, but if the user has
- // actually typed "@", in that case list resource matches.
- // For example, for android:minHeight this makes completion on @dimen/
- // possible.
- choices = UiResourceAttributeNode.computeResourceStringMatches(currentUiNode,
- value);
+ // Should we do suffix completion on dimension units etc?
+ choices = completeSuffix(choices, value, currAttrNode);
+
+ // Check to see if the user is attempting resource completion
+ AttributeDescriptor attributeDescriptor = currAttrNode.getDescriptor();
+ IAttributeInfo attributeInfo = attributeDescriptor.getAttributeInfo();
+ if (value.startsWith("@") //$NON-NLS-1$
+ && !Format.REFERENCE.in(attributeInfo.getFormats())) {
+ // Special case: If the attribute value looks like a reference to a
+ // resource, offer to complete it, since in many cases our metadata
+ // does not correctly state whether a resource value is allowed. We don't
+ // offer these for an empty completion context, but if the user has
+ // actually typed "@", in that case list resource matches.
+ // For example, for android:minHeight this makes completion on @dimen/
+ // possible.
+ choices = UiResourceAttributeNode.computeResourceStringMatches(
+ currentUiNode, attributeDescriptor, value);
+ }
}
}
@@ -436,14 +474,16 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
* - AttributeDescriptor: a possible attribute descriptor which XML name should be completed.
* - String: string values to display as-is to the user. Typically those are possible
* values for a given attribute.
+ * - Pair of Strings: the first value is the keyword to insert, and the second value
+ * is the tooltip/help for the value to be displayed in the documentation popup.
*
* @return The ICompletionProposal[] to display to the user.
*/
private ICompletionProposal[] computeProposals(int offset, Node currentNode,
- Object[] choices, String wordPrefix, char need_tag,
- boolean is_attribute, int selectionLength) {
- ArrayList<CompletionProposal> proposals = new ArrayList<CompletionProposal>();
- HashMap<String, String> nsUriMap = new HashMap<String, String>();
+ Object[] choices, String wordPrefix, char needTag,
+ boolean isAttribute, boolean isNew, int replaceLength) {
+ List<CompletionProposal> proposals = new ArrayList<CompletionProposal>();
+ Map<String, String> nsUriMap = new HashMap<String, String>();
for (Object choice : choices) {
String keyword = null;
@@ -481,6 +521,17 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
} else if (choice instanceof String) {
keyword = (String) choice;
+ if (isAttribute) {
+ icon = IconFactory.getInstance().getIcon(ATTRIBUTE_ICON_FILENAME);
+ }
+ } else if (choice instanceof Pair<?, ?>) {
+ @SuppressWarnings("unchecked")
+ Pair<String, String> pair = (Pair<String, String>) choice;
+ keyword = pair.getFirst();
+ tooltip = pair.getSecond();
+ if (isAttribute) {
+ icon = IconFactory.getInstance().getIcon(ATTRIBUTE_ICON_FILENAME);
+ }
} else {
continue; // discard unknown choice
}
@@ -493,18 +544,18 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (nsPrefix != null) {
keyword = nsPrefix + keyword;
}
- String end_tag = ""; //$NON-NLS-1$
- if (need_tag != 0) {
- if (need_tag == '"') {
- keyword = need_tag + keyword;
- end_tag = String.valueOf(need_tag);
- } else if (need_tag == '<') {
+ String endTag = ""; //$NON-NLS-1$
+ if (needTag != 0) {
+ if (needTag == '"') {
+ keyword = needTag + keyword;
+ endTag = String.valueOf(needTag);
+ } else if (needTag == '<') {
if (elementCanHaveChildren(choice)) {
- end_tag = String.format("></%1$s>", keyword); //$NON-NLS-1$
- keyword = need_tag + keyword;
+ endTag = String.format("></%1$s>", keyword); //$NON-NLS-1$
+ keyword = needTag + keyword;
} else {
- keyword = need_tag + keyword;
- end_tag = "/>"; //$NON-NLS-1$
+ keyword = needTag + keyword;
+ endTag = "/>"; //$NON-NLS-1$
}
}
}
@@ -513,13 +564,13 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
// For attributes, automatically insert ns:attribute="" and place the cursor
// inside the quotes.
- if (choice instanceof AttributeDescriptor) {
+ if (choice instanceof AttributeDescriptor && isNew) {
// Special case for attributes: insert ="" stuff and locate caret inside ""
String suffix = "=\"\""; //$NON-NLS-1$
proposal = new CompletionProposal(
keyword + suffix , // String replacementString
offset - wordPrefix.length(), // int replacementOffset
- wordPrefix.length() + selectionLength, // int replacementLength
+ wordPrefix.length() + replaceLength, // int replacementLength
keyword.length() + suffix.length() - 1, // cursorPosition
icon, // Image image
keyword, // displayString - don't include =""
@@ -527,11 +578,16 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
tooltip // String additionalProposalInfo
);
} else {
+ int cursorPosition = keyword.length();
+ if (choice instanceof ElementDescriptor && isNew) {
+ endTag = ' ' + endTag;
+ cursorPosition += 1;
+ }
proposal = new CompletionProposal(
- keyword + end_tag, // String replacementString
+ keyword + endTag, // String replacementString
offset - wordPrefix.length(), // int replacementOffset
- wordPrefix.length() + selectionLength, // int replacementLength
- keyword.length(), // int cursorPosition (rel. to rplcmntOffset)
+ wordPrefix.length() + replaceLength, // int replacementLength
+ cursorPosition, // int cursorPosition (rel. to rplcmntOffset)
icon, // Image image
null, // String displayString
null, // IContextInformation contextInformation
@@ -579,7 +635,8 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
* or if one of the attributes is a TextValueDescriptor.
*
* @param descriptor An ElementDescriptor or an AttributeDescriptor
- * @return True if the descriptor is an ElementDescriptor that can have children or a text value
+ * @return True if the descriptor is an ElementDescriptor that can have children or a text
+ * value
*/
private boolean elementCanHaveChildren(Object descriptor) {
if (descriptor instanceof ElementDescriptor) {
@@ -587,8 +644,8 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (desc.hasChildren()) {
return true;
}
- for (AttributeDescriptor attr_desc : desc.getAttributes()) {
- if (attr_desc instanceof TextValueDescriptor) {
+ for (AttributeDescriptor attrDesc : desc.getAttributes()) {
+ if (attrDesc instanceof TextValueDescriptor) {
return true;
}
}
@@ -729,14 +786,22 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
*/
private AttribInfo parseAttributeInfo(ITextViewer viewer, int offset) {
AttribInfo info = new AttribInfo();
+ int originalOffset = offset;
IDocument document = viewer.getDocument();
int n = document.getLength();
if (offset <= n) {
try {
+ // Look to the right to make sure we aren't sitting on the boundary of the
+ // beginning of a new element with whitespace before it
+ if (offset < n && document.getChar(offset) == '<') {
+ return null;
+ }
+
n = offset;
for (;offset > 0; --offset) {
char ch = document.getChar(offset - 1);
+ if (ch == '>') break;
if (ch == '<') break;
}
@@ -780,6 +845,22 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (pos_equal == -1) {
info.isInValue = false;
info.name = text.trim();
+
+ // info.name is currently just the prefix of the attribute name.
+ // Look at the text buffer to find the complete name (since we need
+ // to know its bounds in order to replace it when a different attribute
+ // that matches this prefix is chosen)
+ IRegion lineInfo = document.getLineInformationOfOffset(originalOffset);
+ String line = document.get(lineInfo.getOffset(), lineInfo.getLength());
+ int nameStart = originalOffset - lineInfo.getOffset();
+ for (int nameEnd = nameStart; nameEnd < line.length(); nameEnd++) {
+ char c = line.charAt(nameEnd);
+ if (!(Character.isLetter(c) || c == ':' || c == '_')) {
+ String nameSuffix = line.substring(nameStart, nameEnd);
+ info.name = text.trim() + nameSuffix;
+ break;
+ }
+ }
} else {
info.isInValue = true;
info.name = text.substring(0, pos_equal).trim();
@@ -831,7 +912,8 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
if (page != null) {
IEditorPart editor = page.getActiveEditor();
if (editor instanceof AndroidXmlEditor) {
- ISourceViewer ssviewer = ((AndroidXmlEditor) editor).getStructuredSourceViewer();
+ ISourceViewer ssviewer =
+ ((AndroidXmlEditor) editor).getStructuredSourceViewer();
if (ssviewer == viewer) {
return (AndroidXmlEditor) editor;
}
@@ -842,6 +924,132 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
return null;
}
+ /**
+ * Fixed list of dimension units, along with user documentation, for use by
+ * {@link #completeSuffix}.
+ */
+ private static final String[] sDimensionUnits = new String[] {
+ "dp", //$NON-NLS-1$
+ "<b>Density-independent Pixels</b> - an abstract unit that is based on the physical "
+ + "density of the screen.",
+
+ "sp", //$NON-NLS-1$
+ "<b>Scale-independent Pixels</b> - this is like the dp unit, but it is also scaled by "
+ + "the user's font size preference.",
+
+ "pt", //$NON-NLS-1$
+ "<b>Points</b> - 1/72 of an inch based on the physical size of the screen.",
+
+ "mm", //$NON-NLS-1$
+ "<b>Millimeters</b> - based on the physical size of the screen.",
+
+ "in", //$NON-NLS-1$
+ "<b>Inches</b> - based on the physical size of the screen.",
+
+ "px", //$NON-NLS-1$
+ "<b>Pixels</b> - corresponds to actual pixels on the screen. Not recommended.",
+ };
+
+ /**
+ * Fixed list of fractional units, along with user documentation, for use by
+ * {@link #completeSuffix}
+ */
+ private static final String[] sFractionUnits = new String[] {
+ "%", //$NON-NLS-1$
+ "<b>Fraction</b> - a percentage of the base size",
+
+ "%p", //$NON-NLS-1$
+ "<b>Fraction</b> - a percentage relative to parent container",
+ };
+ /**
+ * Completes suffixes for applicable types (like dimensions and fractions) such that
+ * after a dimension number you get completion on unit types like "px".
+ */
+ private Object[] completeSuffix(Object[] choices, String value, UiAttributeNode currAttrNode) {
+ IAttributeInfo attributeInfo = currAttrNode.getDescriptor().getAttributeInfo();
+ Format[] formats = attributeInfo.getFormats();
+ List<Object> suffixes = new ArrayList<Object>();
+
+ if (value.length() > 0 && Character.isDigit(value.charAt(0))) {
+ boolean hasDimension = Format.DIMENSION.in(formats);
+ boolean hasFraction = Format.FRACTION.in(formats);
+
+ if (hasDimension || hasFraction) {
+ // Split up the value into a numeric part (the prefix) and the
+ // unit part (the suffix)
+ int suffixBegin = 0;
+ for (; suffixBegin < value.length(); suffixBegin++) {
+ if (!Character.isDigit(value.charAt(suffixBegin))) {
+ break;
+ }
+ }
+ String number = value.substring(0, suffixBegin);
+ String suffix = value.substring(suffixBegin);
+
+ // Add in the matching dimension and/or fraction units, if any
+ if (hasDimension) {
+ // Each item has two entries in the array of strings: the first odd numbered
+ // ones are the unit names and the second even numbered ones are the
+ // corresponding descriptions.
+ for (int i = 0; i < sDimensionUnits.length; i += 2) {
+ String unit = sDimensionUnits[i];
+ if (startsWith(unit, suffix)) {
+ String description = sDimensionUnits[i + 1];
+ suffixes.add(Pair.of(number + unit, description));
+ }
+ }
+ // Allow "dip" completion but don't offer it ("dp" is preferred)
+ if (suffix.startsWith("di") || suffix.startsWith("dip")) { //$NON-NLS-1$ //$NON-NLS-2$
+ suffixes.add(Pair.of(number + "dip", "Alternative name for \"dp\"")); //$NON-NLS-1$
+ }
+ }
+ if (hasFraction) {
+ for (int i = 0; i < sFractionUnits.length; i += 2) {
+ String unit = sFractionUnits[i];
+ if (startsWith(unit, suffix)) {
+ String description = sFractionUnits[i + 1];
+ suffixes.add(Pair.of(number + unit, description));
+ }
+ }
+ }
+ }
+ }
+
+ boolean hasFlag = Format.FLAG.in(formats);
+ if (hasFlag) {
+ boolean isDone = false;
+ String[] flagValues = attributeInfo.getFlagValues();
+ for (String flagValue : flagValues) {
+ if (flagValue.equals(value)) {
+ isDone = true;
+ break;
+ }
+ }
+ if (isDone) {
+ // Add in all the new values with a separator of |
+ String currentValue = currAttrNode.getCurrentValue();
+ for (String flagValue : flagValues) {
+ if (currentValue == null || !currentValue.contains(flagValue)) {
+ suffixes.add(value + '|' + flagValue);
+ }
+ }
+ }
+ }
+
+ if (suffixes.size() > 0) {
+ // Merge previously added choices (from attribute enums etc) with the new matches
+ List<Object> all = new ArrayList<Object>();
+ if (choices != null) {
+ for (Object s : choices) {
+ all.add(s);
+ }
+ }
+ all.addAll(suffixes);
+ choices = all.toArray();
+ }
+
+ return choices;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidSourceViewerConfig.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidSourceViewerConfig.java
index 38d8844..258db03 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidSourceViewerConfig.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidSourceViewerConfig.java
@@ -18,23 +18,28 @@ package com.android.ide.eclipse.adt.internal.editors;
import org.eclipse.jface.text.IAutoEditStrategy;
-import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.formatter.IContentFormatter;
import org.eclipse.jface.text.source.ISourceViewer;
-import org.eclipse.jface.viewers.IInputProvider;
import org.eclipse.wst.sse.core.text.IStructuredPartitions;
import org.eclipse.wst.xml.core.text.IXMLPartitions;
import org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML;
+import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentAssistProcessor;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
/**
* Base Source Viewer Configuration for Android resources.
*/
+@SuppressWarnings("restriction") // XMLContentAssistProcessor
public class AndroidSourceViewerConfig extends StructuredTextViewerConfigurationXML {
/** Content Assist Processor to use for all handled partitions. */
@@ -67,17 +72,6 @@ public class AndroidSourceViewerConfig extends StructuredTextViewerConfiguration
if (partitionType == IStructuredPartitions.UNKNOWN_PARTITION ||
partitionType == IStructuredPartitions.DEFAULT_PARTITION ||
partitionType == IXMLPartitions.XML_DEFAULT) {
- if (sourceViewer instanceof IInputProvider) {
- IInputProvider input = (IInputProvider) sourceViewer;
- Object a = input.getInput();
- if (a != null)
- a.toString();
- }
-
- IDocument doc = sourceViewer.getDocument();
- if (doc != null)
- doc.toString();
-
processors.add(mProcessor);
}
@@ -85,7 +79,13 @@ public class AndroidSourceViewerConfig extends StructuredTextViewerConfiguration
partitionType);
if (others != null && others.length > 0) {
for (IContentAssistProcessor p : others) {
- processors.add(p);
+ // Builtin Eclipse WTP code completion assistant? If so,
+ // wrap it with our own filter which hides some unwanted completions.
+ if (p instanceof XMLContentAssistProcessor) {
+ processors.add(new FilteringContentAssistProcessor(p));
+ } else {
+ processors.add(p);
+ }
}
}
@@ -125,4 +125,69 @@ public class AndroidSourceViewerConfig extends StructuredTextViewerConfiguration
return targets;
}
+ /**
+ * A delegating {@link IContentAssistProcessor} whose purpose is to filter out some
+ * default Eclipse XML completions which are distracting in Android XML files
+ */
+ private class FilteringContentAssistProcessor implements IContentAssistProcessor {
+ private IContentAssistProcessor mDelegate;
+
+ public FilteringContentAssistProcessor(IContentAssistProcessor delegate) {
+ super();
+ mDelegate = delegate;
+ }
+
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+ ICompletionProposal[] result = mDelegate.computeCompletionProposals(viewer, offset);
+ if (result == null) {
+ return null;
+ }
+
+ List<ICompletionProposal> proposals =
+ new ArrayList<ICompletionProposal>(result.length);
+ for (ICompletionProposal proposal : result) {
+ String replacement = proposal.getDisplayString();
+ if (replacement.charAt(0) == '"' &&
+ replacement.charAt(replacement.length() - 1) == '"') {
+ // Filter out attribute values. In Android XML files (where there is no DTD
+ // etc) the default Eclipse XML code completion simply provides the
+ // existing value as a completion. This is often misleading, since if you
+ // for example have a typo, completion will show your current (wrong)
+ // value as a valid completion.
+ } else if (replacement.contains("Namespace") //$NON-NLS-1$
+ || replacement.contains("Schema")) { //$NON-NLS-1$
+ // Eclipse adds in a number of namespace and schema related completions which
+ // are not usually applicable in our files.
+ } else {
+ proposals.add(proposal);
+ }
+ }
+
+ if (proposals.size() == result.length) {
+ return result;
+ } else {
+ return proposals.toArray(new ICompletionProposal[proposals.size()]);
+ }
+ }
+
+ public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
+ return mDelegate.computeContextInformation(viewer, offset);
+ }
+
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return mDelegate.getCompletionProposalAutoActivationCharacters();
+ }
+
+ public char[] getContextInformationAutoActivationCharacters() {
+ return mDelegate.getContextInformationAutoActivationCharacters();
+ }
+
+ public IContextInformationValidator getContextInformationValidator() {
+ return mDelegate.getContextInformationValidator();
+ }
+
+ public String getErrorMessage() {
+ return mDelegate.getErrorMessage();
+ }
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/AttributeDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/AttributeDescriptor.java
index 1cf11e4..e6df2ca 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/AttributeDescriptor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/AttributeDescriptor.java
@@ -35,7 +35,7 @@ import org.eclipse.swt.graphics.Image;
* the correct UiAttributeNode-derived class.
*/
public abstract class AttributeDescriptor {
- private static final String ATTRIBUTE_ICON_FILENAME = "attribute"; //$NON-NLS-1$
+ public static final String ATTRIBUTE_ICON_FILENAME = "attribute"; //$NON-NLS-1$
private final String mXmlLocalName;
private final String mNsUri;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java
index 4b313f6..d55db31 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutContentAssist.java
@@ -16,16 +16,18 @@
package com.android.ide.eclipse.adt.internal.editors.layout;
+import com.android.annotations.VisibleForTesting;
import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
/**
* Content Assist Processor for /res/layout XML files
*/
-class LayoutContentAssist extends AndroidContentAssist {
+@VisibleForTesting
+public final class LayoutContentAssist extends AndroidContentAssist {
/**
- * Constructor for LayoutContentAssist
+ * Constructor for LayoutContentAssist
*/
public LayoutContentAssist() {
super(AndroidTargetData.DESCRIPTOR_LAYOUT);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java
index 6e85412..193c3c0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java
@@ -57,7 +57,7 @@ import static com.android.ide.common.layout.LayoutConstants.LINEAR_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.RELATIVE_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.VALUE_FALSE;
-import static com.android.ide.common.layout.LayoutConstants.VALUE_N_DIP;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_N_DP;
import static com.android.ide.common.layout.LayoutConstants.VALUE_TRUE;
import static com.android.ide.common.layout.LayoutConstants.VALUE_VERTICAL;
import static com.android.ide.common.layout.LayoutConstants.VALUE_WRAP_CONTENT;
@@ -911,7 +911,7 @@ class RelativeLayoutConversionHelper {
view.addHorizConstraint(attachLeftProperty, attachLeftValue);
if (marginLeft > 0) {
view.addHorizConstraint(ATTR_LAYOUT_MARGIN_LEFT,
- String.format(VALUE_N_DIP, marginLeft));
+ String.format(VALUE_N_DP, marginLeft));
marginLeft = 0;
}
} else {
@@ -965,7 +965,7 @@ class RelativeLayoutConversionHelper {
view.addVerticalConstraint(attachTopProperty, attachTopValue);
if (marginTop > 0) {
view.addVerticalConstraint(ATTR_LAYOUT_MARGIN_TOP,
- String.format(VALUE_N_DIP, marginTop));
+ String.format(VALUE_N_DP, marginTop));
marginTop = 0;
}
} else {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java
index 349048f..1c92309 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java
@@ -16,16 +16,18 @@
package com.android.ide.eclipse.adt.internal.editors.manifest;
+import com.android.annotations.VisibleForTesting;
import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
/**
* Content Assist Processor for AndroidManifest.xml
*/
-final class ManifestContentAssist extends AndroidContentAssist {
+@VisibleForTesting
+public final class ManifestContentAssist extends AndroidContentAssist {
/**
- * Constructor for ManifestContentAssist
+ * Constructor for ManifestContentAssist
*/
public ManifestContentAssist() {
super(AndroidTargetData.DESCRIPTOR_MANIFEST);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
index 9032b46..c0ca837 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java
@@ -16,12 +16,17 @@
package com.android.ide.eclipse.adt.internal.editors.uimodel;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_STYLE;
import static com.android.ide.eclipse.adt.AdtConstants.ANDROID_PKG;
+import com.android.ide.common.api.IAttributeInfo;
+import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors;
import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceItem;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
@@ -49,7 +54,10 @@ import org.eclipse.ui.forms.widgets.TableWrapData;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.EnumSet;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -63,6 +71,8 @@ import java.util.regex.Pattern;
* See {@link UiTextAttributeNode} for more information.
*/
public class UiResourceAttributeNode extends UiTextAttributeNode {
+ /** The resource prefix @android: */
+ private static final String ANDROID_RESOURCE_PREFIX = '@' + ANDROID_PKG + ':';
private ResourceType mType;
@@ -198,10 +208,11 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
*/
@Override
public String[] getPossibleValues(String prefix) {
- return computeResourceStringMatches(getUiParent(), prefix);
+ return computeResourceStringMatches(getUiParent(), getDescriptor(), prefix);
}
- public static String[] computeResourceStringMatches(UiElementNode uiNode, String prefix) {
+ public static String[] computeResourceStringMatches(UiElementNode uiNode,
+ AttributeDescriptor attributeDescriptor, String prefix) {
ResourceRepository repository = null;
boolean isSystem = false;
AndroidXmlEditor editor = uiNode.getEditor();
@@ -236,7 +247,7 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
}
// Now collect results
- ArrayList<String> results = new ArrayList<String>();
+ List<String> results = new ArrayList<String>();
if (typeName == null) {
// This prefix does not have a / in it, so the resource string is either empty
@@ -245,13 +256,13 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
for (ResourceType resType : resTypes) {
if (isSystem) {
- results.add("@" + ANDROID_PKG + ':' + resType.getName() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ results.add(ANDROID_RESOURCE_PREFIX + resType.getName() + '/');
} else {
- results.add("@" + resType.getName() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ results.add('@' + resType.getName() + '/');
}
if (resType == ResourceType.ID) {
// Also offer the + version to create an id from scratch
- results.add("@+" + resType.getName() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
+ results.add("@+" + resType.getName() + '/'); //$NON-NLS-1$
}
}
@@ -259,7 +270,7 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
// "@an" we offer to complete it.
if (prefix == null ||
ANDROID_PKG.regionMatches(0, prefix, 1, prefix.length() - 1)) {
- results.add('@' + ANDROID_PKG + ':');
+ results.add(ANDROID_RESOURCE_PREFIX);
}
} else if (repository != null) {
// We have a style name and a repository. Find all resources that match this
@@ -286,6 +297,94 @@ public class UiResourceAttributeNode extends UiTextAttributeNode {
}
}
+ sortAttributeChoices(attributeDescriptor, results);
+
return results.toArray(new String[results.size()]);
}
+
+ /**
+ * Attempts to sort the attribute values to bubble up the most likely choices to
+ * the top.
+ * <p>
+ * For example, if you are editing a style attribute, it's likely that among the
+ * resource values you would rather see @style or @android than @string.
+ */
+ private static void sortAttributeChoices(AttributeDescriptor descriptor,
+ List<String> choices) {
+ final IAttributeInfo attributeInfo = descriptor.getAttributeInfo();
+ Collections.sort(choices, new Comparator<String>() {
+ public int compare(String s1, String s2) {
+ int compare = score(attributeInfo, s1) - score(attributeInfo, s2);
+ if (compare == 0) {
+ // Sort alphabetically as a fallback
+ compare = s1.compareTo(s2);
+ }
+ return compare;
+ }
+ });
+ }
+
+ /** Compute a suitable sorting score for the given */
+ private static final int score(IAttributeInfo attributeInfo, String value) {
+ if (value.equals(ANDROID_RESOURCE_PREFIX)) {
+ return -1;
+ }
+
+ for (Format format : attributeInfo.getFormats()) {
+ String type = null;
+ switch (format) {
+ case BOOLEAN:
+ type = "bool"; //$NON-NLS-1$
+ break;
+ case COLOR:
+ type = "color"; //$NON-NLS-1$
+ break;
+ case DIMENSION:
+ type = "dimen"; //$NON-NLS-1$
+ break;
+ case INTEGER:
+ type = "integer"; //$NON-NLS-1$
+ break;
+ case STRING:
+ type = "string"; //$NON-NLS-1$
+ break;
+ // default: REFERENCE, FLAG, ENUM, etc - don't have type info about individual
+ // elements to help make a decision
+ }
+
+ if (type != null) {
+ if (value.startsWith('@' + type + '/')) {
+ return -2;
+ }
+
+ if (value.startsWith(ANDROID_RESOURCE_PREFIX + type + '/')) {
+ return -2;
+ }
+ }
+ }
+
+ // Handle a few more cases not covered by the Format metadata check
+ String type = null;
+
+ String attribute = attributeInfo.getName();
+ if (attribute.equals(ATTR_ID)) {
+ type = "id"; //$NON-NLS-1$
+ } else if (attribute.equals(ATTR_STYLE)) {
+ type = "style"; //$NON-NLS-1$
+ } else if (attribute.equals(LayoutDescriptors.ATTR_LAYOUT)) {
+ type = "layout"; //$NON-NLS-1$
+ }
+
+ if (type != null) {
+ if (value.startsWith('@' + type + '/')) {
+ return -2;
+ }
+
+ if (value.startsWith(ANDROID_RESOURCE_PREFIX + type + '/')) {
+ return -2;
+ }
+ }
+
+ return 0;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
new file mode 100644
index 0000000..38e3bfd
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2011 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.adt.internal.editors;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.layout.LayoutContentAssist;
+import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;
+import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestContentAssist;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+public class AndroidContentAssistTest extends AdtProjectTest {
+ private static final String CARET = "^"; //$NON-NLS-1$
+
+ public void testStartsWith() {
+ assertTrue(AndroidContentAssist.startsWith("", ""));
+ assertTrue(AndroidContentAssist.startsWith("a", ""));
+ assertTrue(AndroidContentAssist.startsWith("A", ""));
+ assertTrue(AndroidContentAssist.startsWith("A", "a"));
+ assertTrue(AndroidContentAssist.startsWith("A", "A"));
+ assertTrue(AndroidContentAssist.startsWith("Ab", "a"));
+ assertTrue(AndroidContentAssist.startsWith("ab", "A"));
+ assertTrue(AndroidContentAssist.startsWith("ab", "AB"));
+ assertFalse(AndroidContentAssist.startsWith("ab", "ABc"));
+ assertFalse(AndroidContentAssist.startsWith("", "ABc"));
+ }
+
+ public void testCompletion1() throws Exception {
+ // Change attribute name completion
+ checkLayoutCompletion("completion1.xml", "layout_w^idth=\"fill_parent\"");
+ }
+
+ public void testCompletion2() throws Exception {
+ // Check attribute value completion for enum
+ checkLayoutCompletion("completion1.xml", "layout_width=\"^fill_parent\"");
+ }
+
+ public void testCompletion3() throws Exception {
+ // Check attribute value completion for enum with a prefix
+ checkLayoutCompletion("completion1.xml", "layout_width=\"fi^ll_parent\"");
+ }
+
+ public void testCompletion4() throws Exception {
+ // Check attribute value completion on units
+ checkLayoutCompletion("completion1.xml", "marginBottom=\"50^\"");
+ }
+
+ public void testCompletion5() throws Exception {
+ // Check attribute value completion on units with prefix
+ checkLayoutCompletion("completion1.xml", "layout_marginLeft=\"50d^p\"");
+ }
+
+ public void testCompletion6() throws Exception {
+ // Check resource sorting - "style" should bubble to the top for a style attribute
+ checkLayoutCompletion("completion1.xml", "style=\"@android:^style/Widget.Button\"");
+ }
+
+ public void testCompletion7a() throws Exception {
+ // Check flags (multiple values inside a single XML value, separated by | - where
+ // the prefix is reset as soon as you pass each | )
+ checkLayoutCompletion("completion1.xml", "android:gravity=\"l^eft|bottom\"");
+ }
+
+ public void testCompletion7b() throws Exception {
+ checkLayoutCompletion("completion1.xml", "android:gravity=\"left|b^ottom\"");
+ }
+
+ public void testCompletion8() throws Exception {
+ // Test completion right at the "=" sign; this will be taken to be the last
+ // character of the attribute name (the caret is between the last char and before
+ // the = characters), so it should match a single attribute
+ checkLayoutCompletion("completion1.xml", "layout_width^=\"fill_parent\"");
+ }
+
+ public void testCompletion9() throws Exception {
+ // Test completion right after the "=" sign; this will be taken to be the beginning
+ // of the attribute value, but all values will also include a leading quote
+ checkLayoutCompletion("completion1.xml", "layout_width=^\"fill_parent\"");
+ }
+
+ public void testCompletion10() throws Exception {
+ // Test completion of element names
+ checkLayoutCompletion("completion1.xml", "<T^extView");
+ }
+
+ public void testCompletion11() throws Exception {
+ // Test completion of element names at the outside of the <. This should include
+ // all the elements too (along with the leading <).
+ checkLayoutCompletion("completion1.xml", "^<TextView");
+ }
+
+ public void testCompletion12() throws Exception {
+ // Test completion of element names inside a nested XML; ensure that this will
+ // correctly compute element names, not previous attribute
+ checkLayoutCompletion("completion1.xml", "btn_default\">^</FrameLayout>");
+ }
+
+ public void testCompletion13a() throws Exception {
+ checkLayoutCompletion("completion2.xml", "gravity=\"left|bottom|^cen");
+ }
+
+ public void testCompletion13b() throws Exception {
+ checkLayoutCompletion("completion2.xml", "gravity=\"left|bottom|cen^");
+ }
+
+ public void testCompletion13c() throws Exception {
+ checkLayoutCompletion("completion2.xml", "gravity=\"left|bottom^|cen");
+ }
+
+ public void testCompletion14() throws Exception {
+ // Test completion of permissions
+ checkManifestCompletion("manifest.xml", "android.permission.ACC^ESS_NETWORK_STATE");
+ }
+
+ public void testCompletion15() throws Exception {
+ // Test completion of intents
+ checkManifestCompletion("manifest.xml", "android.intent.category.L^AUNCHER");
+ }
+
+ public void testCompletion16() throws Exception {
+ // Test completion of top level elements
+ checkManifestCompletion("manifest.xml", "<^application android:i");
+ }
+
+ public void testCompletion17() throws Exception {
+ // Test completion of attributes on the manifest element
+ checkManifestCompletion("manifest.xml", "^android:versionCode=\"1\"");
+ }
+
+ public void testCompletion18() throws Exception {
+ // Test completion of attributes on the manifest element
+ checkManifestCompletion("manifest.xml",
+ "<activity android:^name=\".TestActivity\"");
+ }
+
+ // ---- Test *applying* code completion ----
+
+ // The following tests check -applying- a specific code completion
+ // match - this verifies that the document is updated correctly, the
+ // caret is moved appropriately, etc.
+
+ public void testApplyCompletion1() throws Exception {
+ // Change attribute name completion
+ checkApplyLayoutCompletion("completion1.xml", "layout_w^idth=\"fill_parent\"",
+ "android:layout_weight");
+ }
+
+ public void testApplyCompletion2() throws Exception {
+ // Check attribute value completion for enum
+ checkApplyLayoutCompletion("completion1.xml", "layout_width=\"^fill_parent\"",
+ "match_parent");
+ }
+
+ public void testApplyCompletion3() throws Exception {
+ // Check attribute value completion for enum with a prefix
+ checkApplyLayoutCompletion("completion1.xml", "layout_width=\"fi^ll_parent\"",
+ "fill_parent");
+ }
+
+ public void testApplyCompletion4() throws Exception {
+ // Check attribute value completion on units
+ checkApplyLayoutCompletion("completion1.xml", "marginBottom=\"50^\"", "50mm");
+ }
+
+ public void testApplyCompletion5() throws Exception {
+ // Check attribute value completion on units with prefix
+ checkApplyLayoutCompletion("completion1.xml", "layout_marginLeft=\"50d^p\"", "50dp");
+ }
+
+ public void testApplyCompletion6() throws Exception {
+ // Check resource sorting - "style" should bubble to the top for a style attribute
+ checkApplyLayoutCompletion("completion1.xml", "style=\"@android:^style/Widget.Button\"",
+ "@android:drawable/");
+ }
+
+ public void testApplyCompletion7a() throws Exception {
+ // Check flags (multiple values inside a single XML value, separated by | - where
+ // the prefix is reset as soon as you pass each | )
+ checkApplyLayoutCompletion("completion1.xml", "android:gravity=\"l^eft|bottom\"",
+ "left");
+ // NOTE - this will replace all flag values with the newly selected value.
+ // That may not be the best behavior - perhaps we should only replace one portion
+ // of the value.
+ }
+
+ public void testApplyCompletion7b() throws Exception {
+ checkApplyLayoutCompletion("completion1.xml", "android:gravity=\"left|b^ottom\"",
+ "bottom");
+ // NOTE - this will replace all flag values with the newly selected value.
+ // That may not be the best behavior - perhaps we should only replace one portion
+ // of the value.
+ }
+
+ public void testApplyCompletion8() throws Exception {
+ // Test completion right at the "=" sign; this will be taken to be the last
+ // character of the attribute name (the caret is between the last char and before
+ // the = characters), so it should match a single attribute
+ checkApplyLayoutCompletion("completion1.xml", "layout_width^=\"fill_parent\"",
+ "android:layout_width");
+ }
+
+ public void testApplyCompletion9() throws Exception {
+ // Test completion right after the "=" sign; this will be taken to be the beginning
+ // of the attribute value, but all values will also include a leading quote
+ checkApplyLayoutCompletion("completion1.xml", "layout_width=^\"fill_parent\"",
+ "\"wrap_content\"");
+ }
+
+ public void testApplyCompletion10() throws Exception {
+ // Test completion of element names
+ checkApplyLayoutCompletion("completion1.xml", "<T^extView", "TableLayout");
+ }
+
+ public void testApplyCompletion11a() throws Exception {
+ // Test completion of element names at the outside of the <. This should include
+ // all the elements too (along with the leading <).
+ checkApplyLayoutCompletion("completion1.xml", "^<TextView", "<RadioGroup ></RadioGroup>");
+ }
+
+ public void testApplyCompletion11b() throws Exception {
+ // Similar to testApplyCompletion11a, but replacing with an element that does not
+ // have children (to test the closing tag insertion code)
+ checkApplyLayoutCompletion("completion1.xml", "^<TextView", "<CheckBox />");
+ }
+
+ public void testApplyCompletion12() throws Exception {
+ // Test completion of element names inside a nested XML; ensure that this will
+ // correctly compute element names, not previous attribute
+ checkApplyLayoutCompletion("completion1.xml", "btn_default\">^</FrameLayout>",
+ "<FrameLayout ></FrameLayout>");
+ }
+
+ public void testApplyCompletion13a() throws Exception {
+ checkApplyLayoutCompletion("completion2.xml", "gravity=\"left|bottom|^cen",
+ "fill_vertical");
+ }
+
+ public void testApplyCompletion13b() throws Exception {
+ checkApplyLayoutCompletion("completion2.xml", "gravity=\"left|bottom|cen^",
+ "center_horizontal");
+ }
+
+ public void testApplyCompletion13c() throws Exception {
+ checkApplyLayoutCompletion("completion2.xml", "gravity=\"left|bottom^|cen",
+ "bottom|fill_horizontal");
+ }
+
+ // --- Code Completion test infrastructure ----
+
+ private void checkLayoutCompletion(String name, String caretLocation) throws Exception {
+ checkCompletion(name, getLayoutFile(getProject(), name), caretLocation,
+ new LayoutContentAssist());
+ }
+
+ private void checkManifestCompletion(String name, String caretLocation) throws Exception {
+ // Manifest files must be named AndroidManifest.xml. Must overwrite to replace
+ // the default manifest created in the test project.
+ IFile file = getTestDataFile(getProject(), name, "AndroidManifest.xml", true);
+
+ checkCompletion(name, file, caretLocation,
+ new ManifestContentAssist());
+ }
+
+ private void checkApplyLayoutCompletion(String name, String caretLocation,
+ String match) throws Exception {
+ checkApplyCompletion(name, getLayoutFile(getProject(), name), caretLocation,
+ new LayoutContentAssist(), match);
+ }
+
+ private ICompletionProposal[] complete(IFile file, String caretLocation,
+ AndroidContentAssist assist) throws Exception {
+
+ // Determine the offset
+ String fileContent = AdtPlugin.readFile(file);
+ int caretDelta = caretLocation.indexOf(CARET);
+ assertTrue(caretLocation, caretDelta != -1);
+ String caretContext = caretLocation.substring(0, caretDelta)
+ + caretLocation.substring(caretDelta + CARET.length());
+ int caretContextIndex = fileContent.indexOf(caretContext);
+ assertTrue("Caret content " + caretContext + " not found in file",
+ caretContextIndex != -1);
+ int offset = caretContextIndex + caretDelta;
+
+ // Open file
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ assertNotNull(page);
+ IEditorPart editor = IDE.openEditor(page, file);
+ assertTrue(editor instanceof AndroidXmlEditor);
+ AndroidXmlEditor layoutEditor = (AndroidXmlEditor) editor;
+ ISourceViewer viewer = layoutEditor.getStructuredSourceViewer();
+
+ // Run code completion
+ ICompletionProposal[] proposals = assist.computeCompletionProposals(viewer, offset);
+ if (proposals == null) {
+ proposals = new ICompletionProposal[0];
+ }
+
+ return proposals;
+ }
+
+ private void checkApplyCompletion(String basename, IFile file, String caretLocation,
+ AndroidContentAssist assist, String match) throws Exception {
+ ICompletionProposal[] proposals = complete(file, caretLocation, assist);
+ ICompletionProposal chosen = null;
+ for (ICompletionProposal proposal : proposals) {
+ if (proposal.getDisplayString().equals(match)) {
+ chosen = proposal;
+ break;
+ }
+ }
+ assertNotNull(chosen);
+ assert chosen != null; // Eclipse null pointer analysis doesn't believe the JUnit assertion
+
+ String fileContent = AdtPlugin.readFile(file);
+ IDocument document = new Document();
+ document.set(fileContent);
+
+ // Apply code completion
+ chosen.apply(document);
+
+ // Insert caret location as well
+ Point location = chosen.getSelection(document);
+ document.replace(location.x, 0, CARET);
+
+ String actual = document.get();
+
+ String diff = getDiff(fileContent, actual);
+ assertTrue(diff.length() > 0 || fileContent.equals(actual));
+
+ StringBuilder summary = new StringBuilder();
+ summary.append("Code completion in " + basename + " for " + caretLocation + " selecting " + match + ":\n");
+ summary.append(diff);
+
+ //assertEqualsGolden(basename, actual);
+ assertEqualsGolden(basename, summary.toString(), "diff");
+ }
+
+ private void checkCompletion(String basename, IFile file, String caretLocation,
+ AndroidContentAssist assist) throws Exception {
+ ICompletionProposal[] proposals = complete(file, caretLocation, assist);
+ StringBuilder sb = new StringBuilder(1000);
+ sb.append("Code completion in " + basename + " for " + caretLocation + ":\n");
+ for (ICompletionProposal proposal : proposals) {
+ sb.append(proposal.getDisplayString());
+ String help = proposal.getAdditionalProposalInfo();
+ if (help != null && help.trim().length() > 0) {
+ sb.append(" : ");
+ sb.append(help.replace('\n', ' '));
+ }
+ sb.append('\n');
+ }
+ assertEqualsGolden(basename, sb.toString(), "txt");
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java
index b18afa1..4281077 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java
@@ -15,6 +15,9 @@
*/
package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
+import static com.android.AndroidConstants.FD_RES_LAYOUT;
+import static com.android.sdklib.SdkConstants.FD_RES;
+
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
@@ -27,13 +30,16 @@ import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizard;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewTestProjectCreationPage;
import com.android.ide.eclipse.tests.SdkTestCase;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.jface.wizard.IWizardPage;
@@ -82,28 +88,53 @@ public class AdtProjectTest extends SdkTestCase {
return getTestDataFile(project, name, name);
}
+ protected IFile getLayoutFile(IProject project, String name) throws Exception {
+ return getTestDataFile(project, name, FD_RES + "/" + FD_RES_LAYOUT + "/" + name);
+ }
+
protected IFile getTestDataFile(IProject project, String sourceName,
String destPath) throws Exception {
+ return getTestDataFile(project, sourceName, destPath, false);
+ }
+
+ protected IFile getTestDataFile(IProject project, String sourceName,
+ String destPath, boolean overwrite) throws Exception {
String[] split = destPath.split("/"); //$NON-NLS-1$
- assertTrue(split.length > 1);
- IFolder folder = project.getFolder(split[0]);
- NullProgressMonitor monitor = new NullProgressMonitor();
- if (!folder.exists()) {
- folder.create(true /* force */, true /* local */, monitor);
+ IContainer parent;
+ String name;
+ if (split.length == 1) {
+ parent = project;
+ name = destPath;
+ } else {
+ IFolder folder = project.getFolder(split[0]);
+ NullProgressMonitor monitor = new NullProgressMonitor();
+ if (!folder.exists()) {
+ folder.create(true /* force */, true /* local */, monitor);
+ }
+ for (int i = 1, n = split.length; i < n -1; i++) {
+ IFolder subFolder = folder.getFolder(split[i]);
+ if (!subFolder.exists()) {
+ subFolder.create(true /* force */, true /* local */, monitor);
+ }
+ folder = subFolder;
+ }
+ name = split[split.length - 1];
+ parent = folder;
}
- for (int i = 1, n = split.length; i < n -1; i++) {
- IFolder subFolder = folder.getFolder(split[i]);
- if (!subFolder.exists()) {
- subFolder.create(true /* force */, true /* local */, monitor);
+ IFile file = parent.getFile(new Path(name));
+ if (overwrite && file.exists()) {
+ String currentContents = AdtPlugin.readFile(file);
+ String newContents = readTestFile(sourceName, true);
+ if (currentContents == null || !currentContents.equals(newContents)) {
+ file.delete(true, new NullProgressMonitor());
+ } else {
+ return file;
}
- folder = subFolder;
}
-
- String name = split[split.length - 1];
- IFile file = folder.getFile(name);
if (!file.exists()) {
String xml = readTestFile(sourceName, true);
InputStream bstream = new ByteArrayInputStream(xml.getBytes("UTF-8")); //$NON-NLS-1$
+ NullProgressMonitor monitor = new NullProgressMonitor();
file.create(bstream, false /* force */, monitor);
}
@@ -161,6 +192,52 @@ public class AdtProjectTest extends SdkTestCase {
return iproject;
}
+ /**
+ * Very primitive line differ, intended for files where there are very minor changes
+ * (such as code completion apply-tests)
+ */
+ protected String getDiff(String before, String after) {
+
+ // Do line by line analysis
+ String[] beforeLines = before.split("\n");
+ String[] afterLines = after.split("\n");
+
+ int firstDelta = 0;
+ for (; firstDelta < Math.min(beforeLines.length, afterLines.length); firstDelta++) {
+ if (!beforeLines[firstDelta].equals(afterLines[firstDelta])) {
+ break;
+ }
+ }
+
+ if (firstDelta == beforeLines.length && firstDelta == afterLines.length) {
+ return "";
+ }
+
+ // Counts from the end of both arrays
+ int lastDelta = 0;
+ for (; lastDelta < Math.min(beforeLines.length, afterLines.length); lastDelta++) {
+ if (!beforeLines[beforeLines.length - 1 - lastDelta].equals(
+ afterLines[afterLines.length - 1 - lastDelta])) {
+ break;
+ }
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = firstDelta; i < beforeLines.length - lastDelta; i++) {
+ sb.append("< ");
+ sb.append(beforeLines[i]);
+ sb.append('\n');
+ }
+ sb.append("---\n");
+ for (int i = firstDelta; i < afterLines.length - lastDelta; i++) {
+ sb.append("> ");
+ sb.append(afterLines[i]);
+ sb.append('\n');
+ }
+
+ return sb.toString();
+ }
+
public static ViewElementDescriptor createDesc(String name, String fqn, boolean hasChildren) {
if (hasChildren) {
return new ViewElementDescriptor(name, name, fqn, "", "", new AttributeDescriptor[0],
@@ -203,6 +280,55 @@ public class AdtProjectTest extends SdkTestCase {
return xml;
}
+ protected void assertEqualsGolden(String basename, String actual) {
+ assertEqualsGolden(basename, actual, basename.substring(basename.lastIndexOf('.') + 1));
+ }
+
+ protected void assertEqualsGolden(String basename, String actual, String newExtension) {
+ String testName = getName();
+ if (testName.startsWith("test")) {
+ testName = testName.substring(4);
+ if (Character.isUpperCase(testName.charAt(0))) {
+ testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1);
+ }
+ }
+ String expectedName;
+ String extension = basename.substring(basename.lastIndexOf('.') + 1);
+ if (newExtension == null) {
+ newExtension = extension;
+ }
+ expectedName = basename.substring(0, basename.indexOf('.'))
+ + "-expected-" + testName + '.' + newExtension;
+ String expected = readTestFile(expectedName, false);
+ if (expected == null) {
+ File expectedPath = new File(getTempDir(), expectedName);
+ AdtPlugin.writeFile(expectedPath, actual);
+ System.out.println("Expected - written to " + expectedPath + ":\n");
+ System.out.println(actual);
+ fail("Did not find golden file (" + expectedName + "): Wrote contents as "
+ + expectedPath);
+ } else {
+ if (!expected.equals(actual)) {
+ File expectedPath = new File(getTempDir(), expectedName);
+ File actualPath = new File(getTempDir(),
+ expectedName.replace("expected", "actual"));
+ AdtPlugin.writeFile(expectedPath, expected);
+ AdtPlugin.writeFile(actualPath, actual);
+ System.out.println("The files differ - see " + expectedPath + " versus "
+ + actualPath);
+ assertEquals("The files differ - see " + expectedPath + " versus " + actualPath,
+ expected, actual);
+ }
+ }
+ }
+
+ protected File getTempDir() {
+ if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
+ return new File("/tmp"); //$NON-NLS-1$
+ }
+ return new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$
+ }
+
/** Special editor context set on the model to be rendered */
protected static class TestLayoutEditor extends LayoutEditor {
private final IFile mFile;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java
index 372026c..947840c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java
@@ -15,21 +15,15 @@
*/
package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
-import static com.android.AndroidConstants.FD_RES_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.ANDROID_WIDGET_PREFIX;
-import static com.android.ide.eclipse.adt.AdtConstants.DOT_XML;
-import static com.android.sdklib.SdkConstants.FD_RES;
import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
@@ -46,7 +40,6 @@ import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.Element;
-import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -59,10 +52,6 @@ import java.util.regex.Pattern;
@SuppressWarnings("restriction")
public class RefactoringTest extends AdtProjectTest {
- protected IFile getLayoutFile(IProject project, String name) throws Exception {
- return getTestDataFile(project, name, FD_RES + "/" + FD_RES_LAYOUT + "/" + name);
- }
-
protected static Element findElementById(Element root, String id) {
if (id.equals(VisualRefactoring.getId(root))) {
return root;
@@ -153,44 +142,6 @@ public class RefactoringTest extends AdtProjectTest {
}
}
- protected void assertEqualsGolden(String basename, String actual) {
- String testName = getName();
- if (testName.startsWith("test")) {
- testName = testName.substring(4);
- if (Character.isUpperCase(testName.charAt(0))) {
- testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1);
- }
- }
- String expectedName;
- if (basename.endsWith(DOT_XML)) {
- expectedName = basename.substring(0, basename.length() - DOT_XML.length())
- + "-expected-" + testName + DOT_XML;
- } else {
- expectedName = basename + ".expected";
- }
- String expected = readTestFile(expectedName, false);
- if (expected == null) {
- File expectedPath = new File(getTempDir(), expectedName);
- AdtPlugin.writeFile(expectedPath, actual);
- System.out.println("Expected - written to " + expectedPath + ":\n");
- System.out.println(actual);
- fail("Did not find golden file (" + expectedName + "): Wrote contents as "
- + expectedPath);
- } else {
- if (!expected.equals(actual)) {
- File expectedPath = new File(getTempDir(), expectedName);
- File actualPath = new File(getTempDir(),
- expectedName.replace("expected", "actual"));
- AdtPlugin.writeFile(expectedPath, expected);
- AdtPlugin.writeFile(actualPath, actual);
- System.out.println("The files differ - see " + expectedPath + " versus "
- + actualPath);
- assertEquals("The files differ - see " + expectedPath + " versus " + actualPath,
- expected, actual);
- }
- }
- }
-
protected UiViewElementNode createModel(UiViewElementNode parent, Element element) {
List<Element> children = DomUtilities.getChildren(element);
String fqcn = ANDROID_WIDGET_PREFIX + element.getTagName();
@@ -260,13 +211,6 @@ public class RefactoringTest extends AdtProjectTest {
return view;
}
- protected File getTempDir() {
- if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
- return new File("/tmp"); //$NON-NLS-1$
- }
- return new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$
- }
-
protected TestContext setupTestContext(IFile file, String relativePath) throws Exception {
IStructuredModel structuredModel = null;
org.w3c.dom.Document domDocument = null;
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-actual-applyCompletion1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-actual-applyCompletion1.xml
new file mode 100644
index 0000000..2413658
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-actual-applyCompletion1.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
+<!--
+ This file deliberately contains errors - it represents partial keyboard
+ typing for interactive code completion
+-->
+ <TextView
+ android:layout_weight^="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@android:dimen/app_icon_size"
+ android:layout_marginLeft="50dp"
+ android:layout_marginBottom="50"
+ android:textColor="#000000"
+ style="@android:style/Widget.Button"
+ android:gravity="left|bottom"
+ android:text="@string/hello"
+ android:hint="hint" />
+ <FrameLayout android:foreground="@android:drawable/btn_default"></FrameLayout>
+</LinearLayout>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion1.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion1.diff
new file mode 100644
index 0000000..08ba349
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion1.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_w^idth="fill_parent" selecting android:layout_weight:
+< android:layout_width="fill_parent"
+---
+> android:layout_weight^="fill_parent"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion10.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion10.diff
new file mode 100644
index 0000000..4cde056
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion10.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for <T^extView selecting TableLayout:
+< <TextView
+---
+> <TableLayout^
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11a.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11a.diff
new file mode 100644
index 0000000..7d1fd13
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11a.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for ^<TextView selecting <RadioGroup ></RadioGroup>:
+< <TextView
+---
+> <RadioGroup ^></RadioGroup><TextView
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11b.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11b.diff
new file mode 100644
index 0000000..62bf772
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion11b.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for ^<TextView selecting <CheckBox />:
+< <TextView
+---
+> <CheckBox ^/><TextView
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion12.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion12.diff
new file mode 100644
index 0000000..2d767a9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion12.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for btn_default">^</FrameLayout> selecting <FrameLayout ></FrameLayout>:
+< <FrameLayout android:foreground="@android:drawable/btn_default"></FrameLayout>
+---
+> <FrameLayout android:foreground="@android:drawable/btn_default"><FrameLayout ^></FrameLayout></FrameLayout>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion2.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion2.diff
new file mode 100644
index 0000000..8e0b3e4
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion2.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_width="^fill_parent" selecting match_parent:
+< android:layout_width="fill_parent"
+---
+> android:layout_width="match_parent^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion3.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion3.diff
new file mode 100644
index 0000000..5b956a5
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion3.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_width="fi^ll_parent" selecting fill_parent:
+< android:layout_width="fill_parent"
+---
+> android:layout_width="fill_parent^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion4.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion4.diff
new file mode 100644
index 0000000..818b1fa
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion4.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for marginBottom="50^" selecting 50mm:
+< android:layout_marginBottom="50"
+---
+> android:layout_marginBottom="50mm^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion5.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion5.diff
new file mode 100644
index 0000000..5571fd7
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion5.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_marginLeft="50d^p" selecting 50dp:
+< android:layout_marginLeft="50dp"
+---
+> android:layout_marginLeft="50dp^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion6.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion6.diff
new file mode 100644
index 0000000..404b2a9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion6.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for style="@android:^style/Widget.Button" selecting @android:drawable/:
+< style="@android:style/Widget.Button"
+---
+> style="@android:drawable/^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7a.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7a.diff
new file mode 100644
index 0000000..e1d019a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7a.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for android:gravity="l^eft|bottom" selecting left:
+< android:gravity="left|bottom"
+---
+> android:gravity="left^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7b.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7b.diff
new file mode 100644
index 0000000..2fbd2e5
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion7b.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for android:gravity="left|b^ottom" selecting bottom:
+< android:gravity="left|bottom"
+---
+> android:gravity="left|bottom^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion8.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion8.diff
new file mode 100644
index 0000000..dafdeff
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion8.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_width^="fill_parent" selecting android:layout_width:
+< android:layout_width="fill_parent"
+---
+> android:layout_width^="fill_parent"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion9.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion9.diff
new file mode 100644
index 0000000..be0c226
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-applyCompletion9.diff
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_width=^"fill_parent" selecting "wrap_content":
+< android:layout_width="fill_parent"
+---
+> android:layout_width="wrap_content^"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion1.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion1.txt
new file mode 100644
index 0000000..949067a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion1.txt
@@ -0,0 +1,3 @@
+Code completion in completion1.xml for layout_w^idth="fill_parent":
+android:layout_width : Specifies the basic width of the view. [dimension, enum]
+android:layout_weight : [float]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion10.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion10.txt
new file mode 100644
index 0000000..68efdfb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion10.txt
@@ -0,0 +1,10 @@
+Code completion in completion1.xml for <T^extView:
+TabHost
+TabWidget
+TableLayout
+TableRow
+TextSwitcher
+TextView
+TimePicker
+ToggleButton
+TwoLineListItem
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt
new file mode 100644
index 0000000..670b03e
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion11.txt
@@ -0,0 +1,60 @@
+Code completion in completion1.xml for ^<TextView:
+<AbsoluteLayout ></AbsoluteLayout>
+<AdapterViewFlipper ></AdapterViewFlipper>
+<DialerFilter ></DialerFilter>
+<ExpandableListView ></ExpandableListView>
+<FrameLayout ></FrameLayout>
+<GridView ></GridView>
+<HorizontalScrollView ></HorizontalScrollView>
+<ImageSwitcher ></ImageSwitcher>
+<LinearLayout ></LinearLayout>
+<ListView ></ListView>
+<MediaController ></MediaController>
+<RadioGroup ></RadioGroup>
+<RelativeLayout ></RelativeLayout>
+<ScrollView ></ScrollView>
+<SearchView ></SearchView>
+<SlidingDrawer ></SlidingDrawer> : SlidingDrawer specific attributes.
+<StackView ></StackView>
+<TabHost ></TabHost>
+<TabWidget ></TabWidget>
+<TableLayout ></TableLayout>
+<TableRow ></TableRow>
+<TextSwitcher ></TextSwitcher>
+<ViewAnimator ></ViewAnimator>
+<ViewFlipper ></ViewFlipper>
+<ViewSwitcher ></ViewSwitcher>
+<GestureOverlayView /> : GestureOverlayView specific attributes.
+<SurfaceView />
+<View /> : Attributes that can be used with android.view.View or any of its subclasses.
+<ViewStub /> : A android.view.ViewStub lets you lazily include other XML layouts inside your application at runtime.
+<WebView />
+<AnalogClock />
+<AutoCompleteTextView />
+<Button />
+<CalendarView />
+<CheckBox />
+<CheckedTextView />
+<Chronometer />
+<DatePicker />
+<DigitalClock />
+<EditText />
+<Gallery />
+<ImageButton />
+<ImageView />
+<MultiAutoCompleteTextView />
+<NumberPicker />
+<ProgressBar />
+<QuickContactBadge />
+<RadioButton />
+<RatingBar />
+<SeekBar />
+<Spinner />
+<TextView />
+<TimePicker />
+<ToggleButton />
+<TwoLineListItem />
+<VideoView />
+<ZoomButton />
+<ZoomControls />
+<include /> : Lets you statically include XML layouts inside other XML layouts.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt
new file mode 100644
index 0000000..4af986b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion12.txt
@@ -0,0 +1,60 @@
+Code completion in completion1.xml for btn_default">^</FrameLayout>:
+<AbsoluteLayout ></AbsoluteLayout>
+<AdapterViewFlipper ></AdapterViewFlipper>
+<DialerFilter ></DialerFilter>
+<ExpandableListView ></ExpandableListView>
+<FrameLayout ></FrameLayout>
+<GridView ></GridView>
+<HorizontalScrollView ></HorizontalScrollView>
+<ImageSwitcher ></ImageSwitcher>
+<LinearLayout ></LinearLayout>
+<ListView ></ListView>
+<MediaController ></MediaController>
+<RadioGroup ></RadioGroup>
+<RelativeLayout ></RelativeLayout>
+<ScrollView ></ScrollView>
+<SearchView ></SearchView>
+<SlidingDrawer ></SlidingDrawer> : SlidingDrawer specific attributes.
+<StackView ></StackView>
+<TabHost ></TabHost>
+<TabWidget ></TabWidget>
+<TableLayout ></TableLayout>
+<TableRow ></TableRow>
+<TextSwitcher ></TextSwitcher>
+<ViewAnimator ></ViewAnimator>
+<ViewFlipper ></ViewFlipper>
+<ViewSwitcher ></ViewSwitcher>
+<GestureOverlayView /> : GestureOverlayView specific attributes.
+<SurfaceView />
+<View /> : Attributes that can be used with android.view.View or any of its subclasses.
+<ViewStub /> : A android.view.ViewStub lets you lazily include other XML layouts inside your application at runtime.
+<WebView />
+<AnalogClock />
+<AutoCompleteTextView />
+<Button />
+<CalendarView />
+<CheckBox />
+<CheckedTextView />
+<Chronometer />
+<DatePicker />
+<DigitalClock />
+<EditText />
+<Gallery />
+<ImageButton />
+<ImageView />
+<MultiAutoCompleteTextView />
+<NumberPicker />
+<ProgressBar />
+<QuickContactBadge />
+<RadioButton />
+<RatingBar />
+<SeekBar />
+<Spinner />
+<TextView />
+<TimePicker />
+<ToggleButton />
+<TwoLineListItem />
+<VideoView />
+<ZoomButton />
+<ZoomControls />
+<include /> : Lets you statically include XML layouts inside other XML layouts.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion2.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion2.txt
new file mode 100644
index 0000000..136a6fe
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion2.txt
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_width="^fill_parent":
+fill_parent
+match_parent
+wrap_content
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion3.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion3.txt
new file mode 100644
index 0000000..09c27ce
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion3.txt
@@ -0,0 +1,2 @@
+Code completion in completion1.xml for layout_width="fi^ll_parent":
+fill_parent
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion4.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion4.txt
new file mode 100644
index 0000000..a9111eb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion4.txt
@@ -0,0 +1,7 @@
+Code completion in completion1.xml for marginBottom="50^":
+50dp : <b>Density-independent Pixels</b> - an abstract unit that is based on the physical density of the screen.
+50sp : <b>Scale-independent Pixels</b> - this is like the dp unit, but it is also scaled by the user's font size preference.
+50pt : <b>Points</b> - 1/72 of an inch based on the physical size of the screen.
+50mm : <b>Millimeters</b> - based on the physical size of the screen.
+50in : <b>Inches</b> - based on the physical size of the screen.
+50px : <b>Pixels</b> - corresponds to actual pixels on the screen. Not recommended.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion5.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion5.txt
new file mode 100644
index 0000000..6b1c993
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion5.txt
@@ -0,0 +1,2 @@
+Code completion in completion1.xml for layout_marginLeft="50d^p":
+50dp : <b>Density-independent Pixels</b> - an abstract unit that is based on the physical density of the screen.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion6.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion6.txt
new file mode 100644
index 0000000..0853a83
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion6.txt
@@ -0,0 +1,22 @@
+Code completion in completion1.xml for style="@android:^style/Widget.Button":
+@android:style/
+@android:anim/
+@android:animator/
+@android:array/
+@android:bool/
+@android:color/
+@android:declare-styleable/
+@android:dimen/
+@android:drawable/
+@android:fraction/
+@android:id/
+@android:integer/
+@android:interpolator/
+@android:layout/
+@android:menu/
+@android:mipmap/
+@android:plurals/
+@android:public/
+@android:raw/
+@android:string/
+@android:xml/
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7a.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7a.txt
new file mode 100644
index 0000000..cf373ad
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7a.txt
@@ -0,0 +1,2 @@
+Code completion in completion1.xml for android:gravity="l^eft|bottom":
+left
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7b.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7b.txt
new file mode 100644
index 0000000..66276d6
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion7b.txt
@@ -0,0 +1,2 @@
+Code completion in completion1.xml for android:gravity="left|b^ottom":
+bottom
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion8.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion8.txt
new file mode 100644
index 0000000..bee7f93
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion8.txt
@@ -0,0 +1,2 @@
+Code completion in completion1.xml for layout_width^="fill_parent":
+android:layout_width : Specifies the basic width of the view. [dimension, enum]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion9.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion9.txt
new file mode 100644
index 0000000..ab6a0d2
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion9.txt
@@ -0,0 +1,4 @@
+Code completion in completion1.xml for layout_width=^"fill_parent":
+"fill_parent"
+"match_parent"
+"wrap_content"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1.xml
new file mode 100644
index 0000000..d523eeb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
+<!--
+ This file deliberately contains errors - it represents partial keyboard
+ typing for interactive code completion
+-->
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@android:dimen/app_icon_size"
+ android:layout_marginLeft="50dp"
+ android:layout_marginBottom="50"
+ android:textColor="#000000"
+ style="@android:style/Widget.Button"
+ android:gravity="left|bottom"
+ android:text="@string/hello"
+ android:hint="hint" />
+ <FrameLayout android:foreground="@android:drawable/btn_default"></FrameLayout>
+</LinearLayout>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13a.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13a.diff
new file mode 100644
index 0000000..e19874b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13a.diff
@@ -0,0 +1,4 @@
+Code completion in completion2.xml for gravity="left|bottom|^cen selecting fill_vertical:
+< <TextView android:gravity="left|bottom|cen"></TextView>
+---
+> <TextView android:gravity="left|bottom|fill_vertical^"></TextView>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13b.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13b.diff
new file mode 100644
index 0000000..ddea7f1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13b.diff
@@ -0,0 +1,4 @@
+Code completion in completion2.xml for gravity="left|bottom|cen^ selecting center_horizontal:
+< <TextView android:gravity="left|bottom|cen"></TextView>
+---
+> <TextView android:gravity="left|bottom|center_horizontal^"></TextView>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13c.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13c.diff
new file mode 100644
index 0000000..dec1691
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-applyCompletion13c.diff
@@ -0,0 +1,4 @@
+Code completion in completion2.xml for gravity="left|bottom^|cen selecting bottom|fill_horizontal:
+< <TextView android:gravity="left|bottom|cen"></TextView>
+---
+> <TextView android:gravity="left|bottom|fill_horizontal^"></TextView>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13a.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13a.txt
new file mode 100644
index 0000000..323bb78
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13a.txt
@@ -0,0 +1,13 @@
+Code completion in completion2.xml for gravity="left|bottom|^cen:
+top
+bottom
+left
+right
+center_vertical
+fill_vertical
+center_horizontal
+fill_horizontal
+center
+fill
+clip_vertical
+clip_horizontal
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13b.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13b.txt
new file mode 100644
index 0000000..8e6d4d8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13b.txt
@@ -0,0 +1,4 @@
+Code completion in completion2.xml for gravity="left|bottom|cen^:
+center_vertical
+center_horizontal
+center
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13c.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13c.txt
new file mode 100644
index 0000000..3e292ce
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2-expected-completion13c.txt
@@ -0,0 +1,12 @@
+Code completion in completion2.xml for gravity="left|bottom^|cen:
+bottom
+bottom|top
+bottom|right
+bottom|center_vertical
+bottom|fill_vertical
+bottom|center_horizontal
+bottom|fill_horizontal
+bottom|center
+bottom|fill
+bottom|clip_vertical
+bottom|clip_horizontal
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2.xml
new file mode 100644
index 0000000..0921674
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Test multiple pipes in the flag value -->
+ <TextView android:gravity="left|bottom|cen"></TextView>
+</LinearLayout>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion14.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion14.txt
new file mode 100644
index 0000000..478e435
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion14.txt
@@ -0,0 +1,10 @@
+Code completion in manifest.xml for android.permission.ACC^ESS_NETWORK_STATE:
+android.permission.ACCESS_CHECKIN_PROPERTIES
+android.permission.ACCESS_COARSE_LOCATION
+android.permission.ACCESS_FINE_LOCATION
+android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
+android.permission.ACCESS_MOCK_LOCATION
+android.permission.ACCESS_NETWORK_STATE
+android.permission.ACCESS_SURFACE_FLINGER
+android.permission.ACCESS_WIFI_STATE
+android.permission.ACCOUNT_MANAGER
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion15.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion15.txt
new file mode 100644
index 0000000..c6b3538
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion15.txt
@@ -0,0 +1,3 @@
+Code completion in manifest.xml for android.intent.category.L^AUNCHER:
+android.intent.category.LAUNCHER
+android.intent.category.LE_DESK_DOCK
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion16.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion16.txt
new file mode 100644
index 0000000..b69522c
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion16.txt
@@ -0,0 +1,14 @@
+Code completion in manifest.xml for <^application android:i:
+application : The "application" tag describes application-level components contained in the package, as well as general application attributes.
+instrumentation : Attributes that can be supplied in an AndroidManifest.xml "instrumentation" tag, a child of the root manifest tag.
+uses-feature : The "uses-feature" tag specifies a specific feature used by the application.
+permission-group : The "permission-group" tag declares a logical grouping of related permissions.
+supports-screens : The "supports-screens" specifies the screen dimensions an application supports.
+protected-broadcast : Private tag to declare system protected broadcast actions.
+uses-configuration : The "uses-configuration" tag specifies a specific hardware configuration value used by the application.
+compatible-screens
+permission : The "permission" tag declares a security permission that can be used to control access from other packages to specific components or features in your package (or other packages).
+uses-sdk : The "uses-sdk" tag describes the SDK features that the containing package must be running on to operate correctly.
+permission-tree : The "permission-tree" tag declares the base of a tree of permission values: it declares that this package has ownership of the given permission name, as well as all names underneath it (separated by '.').
+uses-permission : The "uses-permission" tag requests a "permission" that the containing package must be granted in order for it to operate correctly.
+original-package : Private tag to declare the original package name that this package is based on.
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion17.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion17.txt
new file mode 100644
index 0000000..6d966da
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion17.txt
@@ -0,0 +1,7 @@
+Code completion in manifest.xml for ^android:versionCode="1":
+package : This attribute gives a unique name for the package, using a Java-style naming convention to avoid name collisions. For example, applications published by Google could have names of the form com.google.app.appname
+android:versionCode : Internal version code. [integer]
+android:versionName : The text shown to the user to indicate the version they have. [string]
+android:sharedUserId : Specify the name of a user ID that will be shared between multiple packages. [string]
+android:sharedUserLabel : Specify a label for the shared user UID of this package. [reference]
+android:installLocation : The default install location defined by an application. [enum]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt
new file mode 100644
index 0000000..6fd1096
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt
@@ -0,0 +1,27 @@
+Code completion in manifest.xml for <activity android:^name=".TestActivity":
+android:name : Required name of the class implementing the activity, deriving from android.app.Activity. [string]
+android:theme : The overall theme to use for an activity. [reference]
+android:label : A user-legible name for the given item. [string, reference]
+android:description : Descriptive text for the associated data. [reference]
+android:icon : A Drawable resource providing a graphical representation of its associated item. [reference]
+android:logo : A Drawable resource providing an extended graphical logo for its associated item. [reference]
+android:launchMode : Specify how an activity should be launched. [enum]
+android:screenOrientation : Specify the orientation an activity should be run in. [enum]
+android:configChanges : Specify one or more configuration changes that the activity will handle itself. [flag]
+android:permission : Specify a permission that a client is required to have in order to use the associated object. [string]
+android:multiprocess : Specify whether a component is allowed to have multiple instances of itself running in different processes. [boolean]
+android:process : Specify a specific process that the associated code is to run in. [string]
+android:taskAffinity : Specify a task name that activities have an "affinity" to. [string]
+android:allowTaskReparenting : Specify that an activity can be moved out of a task it is in to the task it has an affinity for when appropriate. [boolean]
+android:finishOnTaskLaunch : Specify whether an activity should be finished when its task is brought to the foreground by relaunching from the home screen. [boolean]
+android:finishOnCloseSystemDialogs : Specify whether an activity should be finished when a "close system windows" request has been made. [boolean]
+android:clearTaskOnLaunch : Specify whether an activity's task should be cleared when it is re-launched from the home screen. [boolean]
+android:noHistory : Specify whether an activity should be kept in its history stack. [boolean]
+android:alwaysRetainTaskState : Specify whether an acitivty's task state should always be maintained by the system, or if it is allowed to reset the task to its initial state in certain situations. [boolean]
+android:stateNotNeeded : Indicates that an Activity does not need to have its freeze state (as returned by onSaveInstanceState retained in order to be restarted. [boolean]
+android:excludeFromRecents : Indicates that an Activity should be excluded from the list of recently launched activities. [boolean]
+android:enabled : Specify whether the activity is enabled or not (that is, can be instantiated by the system). [boolean]
+android:exported : Flag indicating whether the given application component is available to other applications. [boolean]
+android:windowSoftInputMode : Specify the default soft-input mode for the main window of this activity. [flag]
+android:immersive : Flag declaring this activity to be 'immersive'; immersive activities should not be interrupted with other activities or notifications. [boolean]
+android:hardwareAccelerated : <p>Flag indicating whether the application's rendering should be hardware accelerated if possible. [boolean]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest.xml
new file mode 100644
index 0000000..2c0024f
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-sdk android:minSdkVersion="11" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".TestActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-changeLayout1a.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-changeLayout1a.xml
index 98e0a8f..772f82a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-changeLayout1a.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-changeLayout1a.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout1" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<Button android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="FirstButton" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
- <Button android:layout_alignParentLeft="true" android:layout_alignBaseline="@+id/button2" android:layout_below="@+id/button1" android:layout_marginTop="2dip" android:text="SecondButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button2"></Button>
+ <Button android:layout_alignParentLeft="true" android:layout_alignBaseline="@+id/button2" android:layout_below="@+id/button1" android:layout_marginTop="2dp" android:text="SecondButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button2"></Button>
<Button android:layout_toRightOf="@+id/button2" android:layout_alignBaseline="@+id/button2" android:layout_alignTop="@+id/button2" android:text="ThirdButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button3"></Button>
<CheckBox android:layout_toRightOf="@+id/button3" android:layout_alignBaseline="@+id/button2" android:layout_below="@+id/button1" android:id="@+id/checkBox1" android:text="CheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content"></CheckBox>
<Button android:layout_alignParentLeft="true" android:layout_below="@+id/checkBox1" android:layout_height="wrap_content" android:text="FourthButton" android:id="@+id/button4" android:layout_width="match_parent"></Button>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1b-expected-changeLayout1b.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1b-expected-changeLayout1b.xml
index 737e72d..f47e9be 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1b-expected-changeLayout1b.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1b-expected-changeLayout1b.xml
@@ -10,7 +10,7 @@
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
- <Button android:layout_alignParentLeft="true" android:layout_alignBaseline="@+id/button2" android:layout_below="@+id/button1" android:layout_marginTop="2dip"
+ <Button android:layout_alignParentLeft="true" android:layout_alignBaseline="@+id/button2" android:layout_below="@+id/button1" android:layout_marginTop="2dp"
android:text="SecondButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-changeLayout5.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-changeLayout5.xml
index fba3049..225476c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-changeLayout5.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-changeLayout5.xml
@@ -3,7 +3,7 @@
<Button android:layout_centerHorizontal="true" android:layout_alignParentTop="true" android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"></Button>
<Button android:layout_centerHorizontal="true" android:layout_below="@+id/button1" android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"></Button>
<Button android:layout_alignParentRight="true" android:layout_below="@+id/button2" android:text="Button" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right"></Button>
- <Button android:layout_alignParentLeft="true" android:layout_alignBaseline="@+id/button4" android:layout_below="@+id/button3" android:layout_marginTop="70dip" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Button" android:id="@+id/button4" android:layout_width="wrap_content"></Button>
+ <Button android:layout_alignParentLeft="true" android:layout_alignBaseline="@+id/button4" android:layout_below="@+id/button3" android:layout_marginTop="70dp" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Button" android:id="@+id/button4" android:layout_width="wrap_content"></Button>
<Button android:layout_toRightOf="@+id/button4" android:layout_alignBaseline="@+id/button4" android:layout_alignTop="@+id/button4" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="Button" android:id="@+id/button5" android:layout_width="wrap_content"></Button>
<Button android:layout_toRightOf="@+id/button5" android:layout_alignParentBottom="true" android:layout_height="wrap_content" android:text="Button" android:id="@+id/button6" android:layout_width="wrap_content" android:layout_gravity="bottom"></Button>
</RelativeLayout>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java
index f4092eb..62725b8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/AbsoluteLayoutRuleTest.java
@@ -60,8 +60,8 @@ public class AbsoluteLayoutRuleTest extends LayoutTestBase {
// Drop preview
"useStyle(DROP_PREVIEW), drawRect(Rect[30,-10,105,80])");
- assertEquals("30dip", inserted.getStringAttr(ANDROID_URI, "layout_x"));
- assertEquals("-10dip", inserted.getStringAttr(ANDROID_URI, "layout_y"));
+ assertEquals("30dp", inserted.getStringAttr(ANDROID_URI, "layout_x"));
+ assertEquals("-10dp", inserted.getStringAttr(ANDROID_URI, "layout_y"));
// Without drag bounds we should just draw guide lines instead
inserted = dragInto(new Rect(0, 0, 0, 0), new Point(30, -10), 4, -1,
@@ -70,8 +70,8 @@ public class AbsoluteLayoutRuleTest extends LayoutTestBase {
"useStyle(GUIDELINE), drawLine(30,0,30,480), drawLine(0,-10,240,-10)",
// Drop preview
"useStyle(DROP_PREVIEW), drawLine(30,-10,240,-10), drawLine(30,-10,30,480)");
- assertEquals("30dip", inserted.getStringAttr(ANDROID_URI, "layout_x"));
- assertEquals("-10dip", inserted.getStringAttr(ANDROID_URI, "layout_y"));
+ assertEquals("30dp", inserted.getStringAttr(ANDROID_URI, "layout_x"));
+ assertEquals("-10dp", inserted.getStringAttr(ANDROID_URI, "layout_y"));
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
deleted file mode 100644
index 8151f3a..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2011 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.adt.internal.editors;
-
-import junit.framework.TestCase;
-
-public class AndroidContentAssistTest extends TestCase {
- public void testStartsWith() {
- assertTrue(AndroidContentAssist.startsWith("", ""));
- assertTrue(AndroidContentAssist.startsWith("a", ""));
- assertTrue(AndroidContentAssist.startsWith("A", ""));
- assertTrue(AndroidContentAssist.startsWith("A", "a"));
- assertTrue(AndroidContentAssist.startsWith("A", "A"));
- assertTrue(AndroidContentAssist.startsWith("Ab", "a"));
- assertTrue(AndroidContentAssist.startsWith("ab", "A"));
- assertTrue(AndroidContentAssist.startsWith("ab", "AB"));
- assertFalse(AndroidContentAssist.startsWith("ab", "ABc"));
- assertFalse(AndroidContentAssist.startsWith("", "ABc"));
- }
-}