diff options
author | Tor Norbye <tnorbye@google.com> | 2012-02-17 11:51:48 -0800 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2012-02-21 14:00:21 -0800 |
commit | f78bed2794ecbfe7bb1cea2c3f5faf57a88ea2ba (patch) | |
tree | 657d2e51417257c270471d1d086b3ed8c7dc7a06 /lint | |
parent | 556b907792f0658a6c3f676e23469b83175e3431 (diff) | |
download | sdk-f78bed2794ecbfe7bb1cea2c3f5faf57a88ea2ba.zip sdk-f78bed2794ecbfe7bb1cea2c3f5faf57a88ea2ba.tar.gz sdk-f78bed2794ecbfe7bb1cea2c3f5faf57a88ea2ba.tar.bz2 |
Lint rule to catch edit-usage of TextViews (should be EditText)
TextView provides a number of attributes related to text editing.
However, these are generally intended for the EditText subclass of
EditText. This lint check looks for <TextView> elements in layouts
where one or more of the edit-related attributes (such as inputType)
are defined.
It also updates the deprecation detector to check various deprecated
attributes (it only checked for deprecated elements before this.)
Change-Id: I1b94902d906cd0bee6a6564368125a68b3c9bb2a
Diffstat (limited to 'lint')
9 files changed, 485 insertions, 6 deletions
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultSdkInfo.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultSdkInfo.java index 1c8b74c..930f7a7 100644 --- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultSdkInfo.java +++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultSdkInfo.java @@ -22,6 +22,7 @@ import static com.android.tools.lint.detector.api.LintConstants.ABS_SEEK_BAR; import static com.android.tools.lint.detector.api.LintConstants.ABS_SPINNER; import static com.android.tools.lint.detector.api.LintConstants.ADAPTER_VIEW; import static com.android.tools.lint.detector.api.LintConstants.BUTTON; +import static com.android.tools.lint.detector.api.LintConstants.CHECKED_TEXT_VIEW; import static com.android.tools.lint.detector.api.LintConstants.CHECK_BOX; import static com.android.tools.lint.detector.api.LintConstants.COMPOUND_BUTTON; import static com.android.tools.lint.detector.api.LintConstants.EDIT_TEXT; @@ -42,6 +43,7 @@ import static com.android.tools.lint.detector.api.LintConstants.SCROLL_VIEW; import static com.android.tools.lint.detector.api.LintConstants.SEEK_BAR; import static com.android.tools.lint.detector.api.LintConstants.SPINNER; import static com.android.tools.lint.detector.api.LintConstants.SURFACE_VIEW; +import static com.android.tools.lint.detector.api.LintConstants.SWITCH; import static com.android.tools.lint.detector.api.LintConstants.TABLE_LAYOUT; import static com.android.tools.lint.detector.api.LintConstants.TABLE_ROW; import static com.android.tools.lint.detector.api.LintConstants.TAB_HOST; @@ -126,7 +128,7 @@ class DefaultSdkInfo extends SdkInfo { return false; } - private static final int CLASS_COUNT = 57; + private static final int CLASS_COUNT = 59; @NonNull private static final Map<String, String> PARENTS = new HashMap<String, String>(CLASS_COUNT); @@ -140,6 +142,7 @@ class DefaultSdkInfo extends SdkInfo { PARENTS.put(VIEW_GROUP, VIEW); PARENTS.put(TEXT_VIEW, VIEW); + PARENTS.put(CHECKED_TEXT_VIEW, TEXT_VIEW); PARENTS.put(RADIO_BUTTON, COMPOUND_BUTTON); PARENTS.put(SPINNER, ABS_SPINNER); PARENTS.put(IMAGE_BUTTON, IMAGE_VIEW); @@ -151,6 +154,7 @@ class DefaultSdkInfo extends SdkInfo { PARENTS.put(BUTTON, TEXT_VIEW); PARENTS.put(SEEK_BAR, ABS_SEEK_BAR); PARENTS.put(CHECK_BOX, COMPOUND_BUTTON); + PARENTS.put(SWITCH, COMPOUND_BUTTON); PARENTS.put(GALLERY, ABS_SPINNER); PARENTS.put(SURFACE_VIEW, VIEW); PARENTS.put(ABSOLUTE_LAYOUT, VIEW_GROUP); diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java index 7d2c35a..b3eb1b7 100644 --- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java +++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java @@ -78,9 +78,11 @@ public class LintConstants { public static final String TAB_HOST = "TabHost"; //$NON-NLS-1$ public static final String RADIO_GROUP = "RadioGroup"; //$NON-NLS-1$ public static final String RADIO_BUTTON = "RadioButton"; //$NON-NLS-1$ + public static final String SWITCH = "Switch"; //$NON-NLS-1$ public static final String EDIT_TEXT = "EditText"; //$NON-NLS-1$ public static final String LIST_VIEW = "ListView"; //$NON-NLS-1$ public static final String TEXT_VIEW = "TextView"; //$NON-NLS-1$ + public static final String CHECKED_TEXT_VIEW = "CheckedTextView"; //$NON-NLS-1$ public static final String IMAGE_VIEW = "ImageView"; //$NON-NLS-1$ public static final String SURFACE_VIEW = "SurfaceView"; //$NON-NLS-1$ public static final String ABSOLUTE_LAYOUT = "AbsoluteLayout"; //$NON-NLS-1$ @@ -153,8 +155,26 @@ public class LintConstants { public static final String ATTR_LAYOUT = "layout"; //$NON-NLS-1$ public static final String ATTR_ROW_COUNT = "rowCount"; //$NON-NLS-1$ public static final String ATTR_COLUMN_COUNT = "columnCount"; //$NON-NLS-1$ - public static final String ATTR_BASELINE_ALIGNED = "baselineAligned"; //$NON-NLS-1$ + public static final String ATTR_BASELINE_ALIGNED = "baselineAligned"; //$NON-NLS-1$ public static final String ATTR_CONTENT_DESCRIPTION = "contentDescription"; //$NON-NLS-1$ + public static final String ATTR_IME_ACTION_LABEL = "imeActionLabel"; //$NON-NLS-1$ + public static final String ATTR_PRIVATE_IME_OPTIONS = "privateImeOptions"; //$NON-NLS-1$ + public static final String VALUE_NONE = "none"; //$NON-NLS-1$ + public static final String ATTR_NUMERIC = "numeric"; //$NON-NLS-1$ + public static final String ATTR_IME_ACTION_ID = "imeActionId"; //$NON-NLS-1$ + public static final String ATTR_IME_OPTIONS = "imeOptions"; //$NON-NLS-1$ + public static final String ATTR_FREEZES_TEXT = "freezesText"; //$NON-NLS-1$ + public static final String ATTR_EDITOR_EXTRAS = "editorExtras"; //$NON-NLS-1$ + public static final String ATTR_EDITABLE = "editable"; //$NON-NLS-1$ + public static final String ATTR_DIGITS = "digits"; //$NON-NLS-1$ + public static final String ATTR_CURSOR_VISIBLE = "cursorVisible"; //$NON-NLS-1$ + public static final String ATTR_CAPITALIZE = "capitalize"; //$NON-NLS-1$ + public static final String ATTR_PHONE_NUMBER = "phoneNumber"; //$NON-NLS-1$ + public static final String ATTR_PASSWORD = "password"; //$NON-NLS-1$ + public static final String ATTR_BUFFER_TYPE = "bufferType"; //$NON-NLS-1$ + public static final String ATTR_AUTO_TEXT = "autoText"; //$NON-NLS-1$ + public static final String ATTR_ENABLED = "enabled"; //$NON-NLS-1$ + public static final String ATTR_SINGLE_LINE = "singleLine"; //$NON-NLS-1$ // AbsoluteLayout layout params public static final String ATTR_LAYOUT_Y = "layout_y"; //$NON-NLS-1$ @@ -203,6 +223,7 @@ public class LintConstants { public static final String VALUE_MATCH_PARENT = "match_parent"; //$NON-NLS-1$ public static final String VALUE_VERTICAL = "vertical"; //$NON-NLS-1$ public static final String VALUE_TRUE = "true"; //$NON-NLS-1$ + public static final String VALUE_EDITABLE = "editable"; //$NON-NLS-1$ // Values: Resources diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java index cdb4c12..6f8f19b 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java @@ -53,7 +53,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { private static final List<Issue> sIssues; static { - final int initialCapacity = 79; + final int initialCapacity = 80; List<Issue> issues = new ArrayList<Issue>(initialCapacity); issues.add(AccessibilityDetector.ISSUE); @@ -92,6 +92,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { issues.add(ProguardDetector.ISSUE); issues.add(PxUsageDetector.ISSUE); issues.add(TextFieldDetector.ISSUE); + issues.add(TextViewDetector.ISSUE); issues.add(UnusedResourceDetector.ISSUE); issues.add(UnusedResourceDetector.ISSUE_IDS); issues.add(ExtraTextDetector.ISSUE); diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/DeprecationDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/DeprecationDetector.java index 883afc7..c60c8e0 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/DeprecationDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/DeprecationDetector.java @@ -17,6 +17,16 @@ package com.android.tools.lint.checks; import static com.android.tools.lint.detector.api.LintConstants.ABSOLUTE_LAYOUT; +import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_AUTO_TEXT; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_CAPITALIZE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_EDITABLE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_ENABLED; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_INPUT_METHOD; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_NUMERIC; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_PASSWORD; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_PHONE_NUMBER; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_SINGLE_LINE; import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.Issue; @@ -26,8 +36,10 @@ import com.android.tools.lint.detector.api.Severity; import com.android.tools.lint.detector.api.Speed; import com.android.tools.lint.detector.api.XmlContext; +import org.w3c.dom.Attr; import org.w3c.dom.Element; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -64,8 +76,85 @@ public class DeprecationDetector extends LayoutDetector { } @Override + public Collection<String> getApplicableAttributes() { + return Arrays.asList( + // TODO: fill_parent is deprecated as of API 8. + // We could warn about it, but it will probably be very noisy + // and make people disable the deprecation check; let's focus on + // some older flags for now + //"fill_parent", + + ATTR_EDITABLE, + ATTR_INPUT_METHOD, + ATTR_AUTO_TEXT, + ATTR_CAPITALIZE, + + // This flag is still used a lot and is still properly handled by TextView + // so in the interest of not being too noisy and make people ignore all the + // output, keep quiet about this one -for now-. + //ATTR_SINGLE_LINE, + + ATTR_ENABLED, + ATTR_NUMERIC, + ATTR_PHONE_NUMBER, + ATTR_PASSWORD + + // These attributes are also deprecated; not yet enabled until we + // know the API level to apply the deprecation for: + + // "ignored as of ICS (but deprecated earlier)" + //"fadingEdge", + + // "This attribute is not used by the Android operating system." + //"restoreNeedsApplication", + + // "This will create a non-standard UI appearance, because the search bar UI is + // changing to use only icons for its buttons." + //"searchButtonText", + + ); + } + + @Override public void visitElement(XmlContext context, Element element) { context.report(ISSUE, element, context.getLocation(element), String.format("%1$s is deprecated", element.getTagName()), null); } + + @Override + public void visitAttribute(XmlContext context, Attr attribute) { + if (!ANDROID_URI.equals(attribute.getNamespaceURI())) { + return; + } + + String name = attribute.getLocalName(); + String fix; + int minSdk = 1; + if (name.equals(ATTR_EDITABLE)) { + fix = "Use an <EditText> to make it editable"; + } else if (name.equals(ATTR_ENABLED)) { + fix = "Use state_enabled instead"; + } else if (name.equals(ATTR_SINGLE_LINE)) { + fix = "Use maxLines=\"1\" instead"; + } else { + assert name.equals(ATTR_INPUT_METHOD) + || name.equals(ATTR_CAPITALIZE) + || name.equals(ATTR_NUMERIC) + || name.equals(ATTR_PHONE_NUMBER) + || name.equals(ATTR_PASSWORD) + || name.equals(ATTR_AUTO_TEXT); + fix = "Use inputType instead"; + // The inputType attribute was introduced in API 3 so don't warn about + // deprecation if targeting older platforms + minSdk = 3; + } + + if (context.getProject().getMinSdk() < minSdk) { + return; + } + + context.report(ISSUE, attribute, context.getLocation(attribute), + String.format("%1$s is deprecated: %2$s", + attribute.getName(), fix), null); + } } diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TextViewDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TextViewDetector.java new file mode 100644 index 0000000..09608b1 --- /dev/null +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TextViewDetector.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.tools.lint.checks; + +import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_AUTO_TEXT; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_BUFFER_TYPE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_CAPITALIZE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_CURSOR_VISIBLE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_DIGITS; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_EDITABLE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_EDITOR_EXTRAS; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_IME_ACTION_ID; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_IME_ACTION_LABEL; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_IME_OPTIONS; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_INPUT_METHOD; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_INPUT_TYPE; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_NUMERIC; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_PASSWORD; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_PHONE_NUMBER; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_PRIVATE_IME_OPTIONS; +import static com.android.tools.lint.detector.api.LintConstants.BUTTON; +import static com.android.tools.lint.detector.api.LintConstants.CHECKED_TEXT_VIEW; +import static com.android.tools.lint.detector.api.LintConstants.CHECK_BOX; +import static com.android.tools.lint.detector.api.LintConstants.RADIO_BUTTON; +import static com.android.tools.lint.detector.api.LintConstants.SWITCH; +import static com.android.tools.lint.detector.api.LintConstants.TEXT_VIEW; +import static com.android.tools.lint.detector.api.LintConstants.TOGGLE_BUTTON; +import static com.android.tools.lint.detector.api.LintConstants.VALUE_EDITABLE; +import static com.android.tools.lint.detector.api.LintConstants.VALUE_NONE; +import static com.android.tools.lint.detector.api.LintConstants.VALUE_TRUE; + +import com.android.tools.lint.detector.api.Category; +import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.LayoutDetector; +import com.android.tools.lint.detector.api.Location; +import com.android.tools.lint.detector.api.Scope; +import com.android.tools.lint.detector.api.Severity; +import com.android.tools.lint.detector.api.Speed; +import com.android.tools.lint.detector.api.XmlContext; + +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Checks for cases where a TextView should probably be an EditText instead + */ +public class TextViewDetector extends LayoutDetector { + /** The main issue discovered by this detector */ + public static final Issue ISSUE = Issue.create( + "TextViewEdits", //$NON-NLS-1$ + "Looks for TextViews being used for input", + + "Using a <TextView> to input text is generally an error, you should be " + + "using <EditText> instead. EditText is a subclass of TextView, and some " + + "of the editing support is provided by TextView, so it's possible to set " + + "some input-related properties on a TextView. However, using a TextView " + + "along with input attributes is usually a cut & paste error. To input " + + "text you should be using <EditText>." + + "\n" + + "This check also checks subclasses of TextView, such as Button and CheckBox, " + + "since these have the same issue: they should not be used with editable " + + "attributes.", + + Category.CORRECTNESS, + 7, + Severity.WARNING, + TextViewDetector.class, + Scope.RESOURCE_FILE_SCOPE); + + /** Constructs a new {@link TextViewDetector} */ + public TextViewDetector() { + } + + @Override + public Speed getSpeed() { + return Speed.FAST; + } + + @Override + public Collection<String> getApplicableElements() { + return Arrays.asList( + TEXT_VIEW, + BUTTON, + TOGGLE_BUTTON, + CHECK_BOX, + RADIO_BUTTON, + CHECKED_TEXT_VIEW, + SWITCH + ); + } + + @Override + public void visitElement(XmlContext context, Element element) { + NamedNodeMap attributes = element.getAttributes(); + for (int i = 0, n = attributes.getLength(); i < n; i++) { + Attr attribute = (Attr) attributes.item(i); + String name = attribute.getLocalName(); + if (name == null) { + // Attribute not in a namespace; we only care about the android: ones + continue; + } + + boolean isEditAttribute = false; + switch (name.charAt(0)) { + case 'a': { + isEditAttribute = name.equals(ATTR_AUTO_TEXT); + break; + } + case 'b': { + isEditAttribute = name.equals(ATTR_BUFFER_TYPE) && + attribute.getValue().equals(VALUE_EDITABLE); + break; + } + case 'p': { + isEditAttribute = name.equals(ATTR_PASSWORD) + || name.equals(ATTR_PHONE_NUMBER) + || name.equals(ATTR_PRIVATE_IME_OPTIONS); + break; + } + case 'c': { + isEditAttribute = name.equals(ATTR_CAPITALIZE) + || name.equals(ATTR_CURSOR_VISIBLE); + break; + } + case 'd': { + isEditAttribute = name.equals(ATTR_DIGITS); + break; + } + case 'e': { + if (name.equals(ATTR_EDITABLE)) { + isEditAttribute = attribute.getValue().equals(VALUE_TRUE); + } else { + isEditAttribute = name.equals(ATTR_EDITOR_EXTRAS); + } + break; + } + case 'i': { + if (name.equals(ATTR_INPUT_TYPE)) { + String value = attribute.getValue(); + isEditAttribute = !value.isEmpty() && !value.equals(VALUE_NONE); + } else { + isEditAttribute = name.equals(ATTR_INPUT_TYPE) + || name.equals(ATTR_IME_OPTIONS) + || name.equals(ATTR_IME_ACTION_LABEL) + || name.equals(ATTR_IME_ACTION_ID) + || name.equals(ATTR_INPUT_METHOD); + } + break; + } + case 'n': { + isEditAttribute = name.equals(ATTR_NUMERIC); + break; + } + } + + if (isEditAttribute && ANDROID_URI.equals(attribute.getNamespaceURI())) { + Location location = context.getLocation(attribute); + String message; + String view = element.getTagName(); + if (view.equals(TEXT_VIEW)) { + message = String.format( + "Attribute %1$s should not be used with <TextView>: " + + "Change element type to <EditText> ?", attribute.getName()); + } else { + message = String.format( + "Attribute %1$s should not be used with <%2$s>: " + + "intended for editable text widgets", + attribute.getName(), view); + } + context.report(ISSUE, attribute, location, message, null); + } + } + } +} diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/DeprecationDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/DeprecationDetectorTest.java index b0adceb..88c5f60 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/DeprecationDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/DeprecationDetectorTest.java @@ -25,9 +25,31 @@ public class DeprecationDetectorTest extends AbstractCheckTest { return new DeprecationDetector(); } - public void testAbsoluteLayout() throws Exception { + public void testApi1() throws Exception { assertEquals( - "deprecation.xml:2: Warning: AbsoluteLayout is deprecated", - lintProject("res/layout/deprecation.xml")); + "deprecation.xml:18: Warning: android:editable is deprecated: Use an <EditText> to make it editable\n" + + "deprecation.xml:19: Warning: android:enabled is deprecated: Use state_enabled instead\n" + + "deprecation.xml:2: Warning: AbsoluteLayout is deprecated", + + lintProject( + "apicheck/minsdk1.xml=>AndroidManifest.xml", + "res/layout/deprecation.xml")); + } + + public void testApi4() throws Exception { + assertEquals( + "deprecation.xml:16: Warning: android:autoText is deprecated: Use inputType instead\n" + + "deprecation.xml:17: Warning: android:capitalize is deprecated: Use inputType instead\n" + + "deprecation.xml:18: Warning: android:editable is deprecated: Use an <EditText> to make it editable\n" + + "deprecation.xml:19: Warning: android:enabled is deprecated: Use state_enabled instead\n" + + "deprecation.xml:20: Warning: android:inputMethod is deprecated: Use inputType instead\n" + + "deprecation.xml:21: Warning: android:numeric is deprecated: Use inputType instead\n" + + "deprecation.xml:22: Warning: android:password is deprecated: Use inputType instead\n" + + "deprecation.xml:23: Warning: android:phoneNumber is deprecated: Use inputType instead\n" + + "deprecation.xml:2: Warning: AbsoluteLayout is deprecated", + + lintProject( + "apicheck/minsdk4.xml=>AndroidManifest.xml", + "res/layout/deprecation.xml")); } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TextViewDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TextViewDetectorTest.java new file mode 100644 index 0000000..a0bbb50 --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TextViewDetectorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.tools.lint.checks; + +import com.android.tools.lint.detector.api.Detector; + +@SuppressWarnings("javadoc") +public class TextViewDetectorTest extends AbstractCheckTest { + @Override + protected Detector getDetector() { + return new TextViewDetector(); + } + + public void test() throws Exception { + assertEquals( + "edit_textview.xml:13: Warning: Attribute android:autoText should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:14: Warning: Attribute android:bufferType should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:15: Warning: Attribute android:capitalize should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:16: Warning: Attribute android:cursorVisible should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:17: Warning: Attribute android:digits should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:18: Warning: Attribute android:editable should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:19: Warning: Attribute android:editorExtras should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:22: Warning: Attribute android:imeActionId should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:23: Warning: Attribute android:imeActionLabel should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:24: Warning: Attribute android:imeOptions should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:25: Warning: Attribute android:inputMethod should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:26: Warning: Attribute android:inputType should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:27: Warning: Attribute android:numeric should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:28: Warning: Attribute android:password should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:29: Warning: Attribute android:phoneNumber should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:30: Warning: Attribute android:privateImeOptions should not be used with <TextView>: Change element type to <EditText> ?\n" + + "edit_textview.xml:38: Warning: Attribute android:cursorVisible should not be used with <Button>: intended for editable text widgets\n" + + "edit_textview.xml:44: Warning: Attribute android:cursorVisible should not be used with <CheckedTextView>: intended for editable text widgets\n" + + "edit_textview.xml:50: Warning: Attribute android:cursorVisible should not be used with <CheckBox>: intended for editable text widgets\n" + + "edit_textview.xml:56: Warning: Attribute android:cursorVisible should not be used with <RadioButton>: intended for editable text widgets\n" + + "edit_textview.xml:62: Warning: Attribute android:cursorVisible should not be used with <ToggleButton>: intended for editable text widgets", + + lintFiles("res/layout/edit_textview.xml")); + } +} diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/deprecation.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/deprecation.xml index cbd03df..74a78ff 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/deprecation.xml +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/deprecation.xml @@ -11,4 +11,16 @@ android:layout_y="100dp" android:text="Button" /> + <!-- Deprecated attributes --> + <TextView + android:autoText="true" + android:capitalize="true" + android:editable="true" + android:enabled="true" + android:inputMethod="@+id/foo" + android:numeric="true" + android:password="true" + android:phoneNumber="true" + android:singleLine="true" /> + </AbsoluteLayout> diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/edit_textview.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/edit_textview.xml new file mode 100644 index 0000000..39aa4b7 --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/edit_textview.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <!-- Various attributes that should be set on EditTexts, not TextViews --> + + <TextView + android:id="@+id/textview" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:autoText="true" + android:bufferType="editable" + android:capitalize="words" + android:cursorVisible="true" + android:digits="" + android:editable="true" + android:editorExtras="@+id/foobar" + android:focusable="true" + android:focusableInTouchMode="true" + android:imeActionId="@+id/foo" + android:imeActionLabel="" + android:imeOptions="" + android:inputMethod="" + android:inputType="text" + android:numeric="" + android:password="true" + android:phoneNumber="true" + android:privateImeOptions="" /> + + <!-- Various attributes that should be set on EditTexts, not Buttons --> + + <Button + android:id="@+id/button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:cursorVisible="true" /> + + <CheckedTextView + android:id="@+id/checkedTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:cursorVisible="true" /> + + <CheckBox + android:id="@+id/checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:cursorVisible="true" /> + + <RadioButton + android:id="@+id/radioButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:cursorVisible="true" /> + + <ToggleButton + android:id="@+id/toggleButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:cursorVisible="true" /> + + + <!-- Ok #1 --> + + <TextView + android:id="@+id/okTextView1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:bufferType="spannable" + android:freezesText="true" + android:editable="false" + android:inputType="none" /> + + <!-- Ok #2 --> + + <TextView + android:id="@+id/okTextView2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + +</LinearLayout> |