diff options
8 files changed, 100 insertions, 21 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java index 1661100..844ff15 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/resources/ResourcesContentAssist.java @@ -17,11 +17,14 @@ package com.android.ide.eclipse.adt.internal.editors.resources; import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME_PREFIX; +import static com.android.ide.common.resources.ResourceResolver.PREFIX_ANDROID_RESOURCE_REF; +import static com.android.ide.common.resources.ResourceResolver.PREFIX_RESOURCE_REF; import static com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor.ATTRIBUTE_ICON_FILENAME; import static com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors.ITEM_TAG; import static com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors.NAME_ATTR; import static com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors.STYLE_ELEMENT; import static com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.DESCRIPTOR_LAYOUT; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_TYPE; import com.android.annotations.VisibleForTesting; import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist; @@ -33,6 +36,7 @@ import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvi import com.android.ide.eclipse.adt.internal.editors.descriptors.SeparatorAttributeDescriptor; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; +import com.android.ide.eclipse.adt.internal.editors.uimodel.UiResourceAttributeNode; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import org.eclipse.jface.text.contentassist.CompletionProposal; @@ -197,6 +201,38 @@ public class ResourcesContentAssist extends AndroidContentAssist { } } } + } else if (parentNode.getNodeName().equals(ITEM_TAG)) { + // Completing text content inside an <item> tag: offer @resource completion. + if (prefix.startsWith(PREFIX_RESOURCE_REF) || prefix.trim().length() == 0) { + String[] choices = UiResourceAttributeNode.computeResourceStringMatches( + mEditor, null /*attributeDescriptor*/, prefix); + if (choices == null || choices.length == 0) { + return; + } + + // If the parent item tag specifies a type, filter the results + Node typeNode = parentNode.getAttributes().getNamedItem(ATTR_TYPE); + if (typeNode != null) { + String value = typeNode.getNodeValue(); + List<String> filtered = new ArrayList<String>(); + for (String s : choices) { + if (s.startsWith(PREFIX_ANDROID_RESOURCE_REF) || + s.startsWith(PREFIX_RESOURCE_REF+ value)) { + filtered.add(s); + } + } + if (filtered.size() > 0) { + choices = filtered.toArray(new String[filtered.size()]); + } + } + + int replaceLength = computeTextReplaceLength(currentNode, offset); + addMatchingProposals(proposals, choices, offset, currentNode, + prefix, (char) 0 /*needTag*/, true /* isAttribute */, false /*isNew*/, + false /* skipEndTag*/, + replaceLength); + + } } } } 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 index 1b3cb3e..2d63835 100644 --- 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 @@ -48,6 +48,7 @@ import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; +@SuppressWarnings("javadoc") public class AndroidContentAssistTest extends AdtProjectTest { private static final String CARET = "^"; //$NON-NLS-1$ @@ -466,6 +467,16 @@ public class AndroidContentAssistTest extends AdtProjectTest { checkManifestCompletion("manifest.xml", "<uses-sdk android:minSdkVersion=\"^11\" />"); } + public void testCompletion70() throws Exception { + checkResourceCompletion("completionvalues2.xml", + "<item name=\"main_layout4\" type=\"layout\">^</item>"); + } + + public void testCompletion71() throws Exception { + checkResourceCompletion("completionvalues2.xml", + "<item name=\"main_layout5\" type=\"string\">@string/^app_name</item>"); + } + // ---- Test *applying* code completion ---- @@ -753,6 +764,11 @@ public class AndroidContentAssistTest extends AdtProjectTest { checkApplyResourceCompletion("completionvalues1.xml", "[^false]", "true"); } + public void testApplyCompletion45() throws Exception { + checkApplyResourceCompletion("completionvalues2.xml", + "@string/^app_name", "@string/hello"); + } + // --- Code Completion test infrastructure ---- private void checkLayoutCompletion(String name, String caretLocation) throws Exception { diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt index 9ac8a52..1ba8a62 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt @@ -10,6 +10,9 @@ Code completion in animator1.xml for android:interpolator="^@android:anim/bounce @android:anim/cycle_interpolator @android: @+id/ +@anim/ +@animator/ +@color/ @drawable/ @id/ @layout/ diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-applyCompletion45.diff b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-applyCompletion45.diff new file mode 100644 index 0000000..6498668 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-applyCompletion45.diff @@ -0,0 +1,4 @@ +Code completion in completionvalues2.xml for @string/^app_name selecting @string/hello: +< <item name="main_layout5" type="string">@string/^app_name</item> +--- +> <item name="main_layout5" type="string">@string/hello^</item> diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion70.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion70.txt new file mode 100644 index 0000000..20f8a74 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion70.txt @@ -0,0 +1,3 @@ +Code completion in completionvalues2.xml for <item name="main_layout4" type="layout">^</item>: +@android: +@layout/ diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt new file mode 100644 index 0000000..641cddb --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt @@ -0,0 +1,3 @@ +Code completion in completionvalues2.xml for <item name="main_layout5" type="string">@string/^app_name</item>: +@string/app_name +@string/hello diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2.xml new file mode 100644 index 0000000..293abc0 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <item name="main_layout" type="layout">@layout/main2</item> + <item name="main_layout2" type="layout"> @layout/main_layout </item> + <item name="main_layout3" type="layout"> </item> + <item name="main_layout4" type="layout"></item> + <item name="main_layout5" type="string">@string/app_name</item> +</resources> diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/UnusedResourceDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/UnusedResourceDetector.java index 13616b7..86f0118 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/UnusedResourceDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/UnusedResourceDetector.java @@ -453,34 +453,40 @@ public class UnusedResourceDetector extends ResourceXmlDetector implements Detec mDeclarationToFile.put(resource, context.file); Handle handle = context.parser.createLocationHandle(context, item); mDeclarationToHandle.put(resource, handle); + + checkChildRefs(item); } } } else { assert TAG_STYLE.equals(element.getTagName()) || TAG_ARRAY.equals(element.getTagName()) || TAG_STRING_ARRAY.equals(element.getTagName()); - // Look for ?attr/ and @dimen/foo etc references in the item children for (Element item : LintUtils.getChildren(element)) { - NodeList childNodes = item.getChildNodes(); - for (int i = 0, n = childNodes.getLength(); i < n; i++) { - Node child = childNodes.item(i); - if (child.getNodeType() == Node.TEXT_NODE) { - String text = child.getNodeValue(); - - int index = text.indexOf(ATTR_REF_PREFIX); - if (index != -1) { - String name = text.substring(index + ATTR_REF_PREFIX.length()).trim(); - mReferences.add(R_PREFIX + RESOURCE_CLZ_ATTR + '.' + name); - } else { - index = text.indexOf('@'); - if (index != -1 && text.indexOf('/', index) != -1 - && !text.startsWith("@android:", index)) { //$NON-NLS-1$ - // Compute R-string, e.g. @string/foo => R.string.foo - String token = text.substring(index + 1).trim().replace('/', '.'); - String r = R_PREFIX + token; - mReferences.add(r); - } - } + checkChildRefs(item); + } + } + } + + private void checkChildRefs(Element item) { + // Look for ?attr/ and @dimen/foo etc references in the item children + NodeList childNodes = item.getChildNodes(); + for (int i = 0, n = childNodes.getLength(); i < n; i++) { + Node child = childNodes.item(i); + if (child.getNodeType() == Node.TEXT_NODE) { + String text = child.getNodeValue(); + + int index = text.indexOf(ATTR_REF_PREFIX); + if (index != -1) { + String name = text.substring(index + ATTR_REF_PREFIX.length()).trim(); + mReferences.add(R_PREFIX + RESOURCE_CLZ_ATTR + '.' + name); + } else { + index = text.indexOf('@'); + if (index != -1 && text.indexOf('/', index) != -1 + && !text.startsWith("@android:", index)) { //$NON-NLS-1$ + // Compute R-string, e.g. @string/foo => R.string.foo + String token = text.substring(index + 1).trim().replace('/', '.'); + String r = R_PREFIX + token; + mReferences.add(r); } } } |