aboutsummaryrefslogtreecommitdiffstats
path: root/lint/libs
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-11-29 16:18:19 -0800
committerTor Norbye <tnorbye@google.com>2012-11-29 16:20:40 -0800
commit4c2c7f656cc57c1f12d0efa1a753ab372b6b69de (patch)
tree7bdd01af267305330f3d0d3033699c149cfefee4 /lint/libs
parente36c788c93fc115415241e31d0d4ea2107aef19b (diff)
downloadsdk-4c2c7f656cc57c1f12d0efa1a753ab372b6b69de.zip
sdk-4c2c7f656cc57c1f12d0efa1a753ab372b6b69de.tar.gz
sdk-4c2c7f656cc57c1f12d0efa1a753ab372b6b69de.tar.bz2
Make inefficient weight detector identify more candidates
The inefficient weight detector looks for horizontal layouts with weights where all the children are layouts. It didn't have a very good heuristic for finding out whether all children are layouts; it just looked for whether the tag name contains "Layout". This changeset generalizes this a bit, adding other layouts, as well as <fragment> tags to the lint check. It also updates the Master/Detail template to set the baseline alignment attribute to false (to avoid triggering the updated lint check), as well as android:textIsSelectable to clear another recent new lint rule. Change-Id: I887962b5e29a9ad0c5b5c01970b0c66f884125d8
Diffstat (limited to 'lint/libs')
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultSdkInfo.java44
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/SdkInfo.java10
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java15
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/InefficientWeightDetectorTest.java9
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml37
5 files changed, 110 insertions, 5 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 b5a1628..2f54659 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
@@ -65,9 +65,12 @@ import static com.android.SdkConstants.WIDGET_PKG_PREFIX;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.google.common.annotations.Beta;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
/**
* Default simple implementation of an {@link SdkInfo}
@@ -155,10 +158,23 @@ class DefaultSdkInfo extends SdkInfo {
return type;
}
+ @Override
+ public boolean isLayout(@NonNull String tag) {
+ // TODO: Read in widgets.txt from the platform install area to look up this information
+ // dynamically instead!
+
+ if (super.isLayout(tag)) {
+ return true;
+ }
+
+ return LAYOUTS.contains(tag);
+ }
+
private static final int CLASS_COUNT = 59;
+ private static final int LAYOUT_COUNT = 20;
- @NonNull
- private static final Map<String, String> PARENTS = new HashMap<String, String>(CLASS_COUNT);
+ private static final Map<String,String> PARENTS = Maps.newHashMapWithExpectedSize(CLASS_COUNT);
+ private static final Set<String> LAYOUTS = Sets.newHashSetWithExpectedSize(CLASS_COUNT);
static {
PARENTS.put(COMPOUND_BUTTON, BUTTON);
@@ -203,8 +219,8 @@ class DefaultSdkInfo extends SdkInfo {
PARENTS.put(WEB_VIEW, ABSOLUTE_LAYOUT);
PARENTS.put(AUTO_COMPLETE_TEXT_VIEW, EDIT_TEXT);
PARENTS.put(MULTI_AUTO_COMPLETE_TEXT_VIEW, AUTO_COMPLETE_TEXT_VIEW);
+ PARENTS.put(CHECKED_TEXT_VIEW, TEXT_VIEW);
- PARENTS.put("CheckedTextView", TEXT_VIEW); //$NON-NLS-1$
PARENTS.put("MediaController", FRAME_LAYOUT); //$NON-NLS-1$
PARENTS.put("SlidingDrawer", VIEW_GROUP); //$NON-NLS-1$
PARENTS.put("DialerFilter", RELATIVE_LAYOUT); //$NON-NLS-1$
@@ -237,6 +253,28 @@ class DefaultSdkInfo extends SdkInfo {
}
}
*/
+
+ LAYOUTS.add(TAB_HOST);
+ LAYOUTS.add(HORIZONTAL_SCROLL_VIEW);
+ LAYOUTS.add(VIEW_SWITCHER);
+ LAYOUTS.add(TAB_WIDGET);
+ LAYOUTS.add(VIEW_ANIMATOR);
+ LAYOUTS.add(SCROLL_VIEW);
+ LAYOUTS.add(GRID_VIEW);
+ LAYOUTS.add(TABLE_ROW);
+ LAYOUTS.add(RADIO_GROUP);
+ LAYOUTS.add(LIST_VIEW);
+ LAYOUTS.add(EXPANDABLE_LIST_VIEW);
+ LAYOUTS.add("MediaController"); //$NON-NLS-1$
+ LAYOUTS.add("DialerFilter"); //$NON-NLS-1$
+ LAYOUTS.add("ViewFlipper"); //$NON-NLS-1$
+ LAYOUTS.add("SlidingDrawer"); //$NON-NLS-1$
+ LAYOUTS.add("StackView"); //$NON-NLS-1$
+ LAYOUTS.add("SearchView"); //$NON-NLS-1$
+ LAYOUTS.add("TextSwitcher"); //$NON-NLS-1$
+ LAYOUTS.add("AdapterViewFlipper"); //$NON-NLS-1$
+ LAYOUTS.add("ImageSwitcher"); //$NON-NLS-1$
+ assert LAYOUTS.size() <= LAYOUT_COUNT : LAYOUTS.size();
}
// Currently using a map; this should really be a list, but using a map until we actually
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/SdkInfo.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/SdkInfo.java
index 5ff7f90..8b3d1e9 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/SdkInfo.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/SdkInfo.java
@@ -76,5 +76,15 @@ public abstract class SdkInfo {
@Nullable
public abstract String getParentViewName(@NonNull String name);
+ /**
+ * Returns true if the given widget name is a layout
+ *
+ * @param tag the XML tag for the view
+ * @return true if the given tag corresponds to a layout
+ */
+ public boolean isLayout(@NonNull String tag) {
+ return tag.endsWith("Layout"); //$NON-NLS-1$
+ }
+
// TODO: Add access to resource resolution here.
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java
index 9c92c4b..39009c6 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java
@@ -23,11 +23,15 @@ import static com.android.SdkConstants.ATTR_LAYOUT_WEIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
import static com.android.SdkConstants.ATTR_ORIENTATION;
import static com.android.SdkConstants.LINEAR_LAYOUT;
+import static com.android.SdkConstants.RADIO_GROUP;
import static com.android.SdkConstants.VALUE_VERTICAL;
import static com.android.SdkConstants.VIEW;
+import static com.android.SdkConstants.VIEW_FRAGMENT;
+import static com.android.SdkConstants.VIEW_INCLUDE;
import static com.android.SdkConstants.VIEW_TAG;
import com.android.annotations.NonNull;
+import com.android.tools.lint.client.api.SdkInfo;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.LayoutDetector;
@@ -170,9 +174,16 @@ public class InefficientWeightDetector extends LayoutDetector {
&& !element.hasAttributeNS(ANDROID_URI, ATTR_BASELINE_ALIGNED)) {
// See if all the children are layouts
boolean allChildrenAreLayouts = children.size() > 0;
+ SdkInfo sdkInfo = context.getClient().getSdkInfo(context.getProject());
for (Element child : children) {
- // TODO: Make better check
- if (!child.getTagName().endsWith("Layout")) { //$NON-NLS-1$
+ String tagName = child.getTagName();
+ if (!(sdkInfo.isLayout(tagName)
+ // RadioGroup is a layout, but one which possibly should be base aligned
+ && !tagName.equals(RADIO_GROUP)
+ // Consider <fragment> tags as layouts for the purposes of this check
+ || VIEW_FRAGMENT.equals(tagName)
+ // Ditto for <include> tags
+ || VIEW_INCLUDE.equals(tagName))) {
allChildrenAreLayouts = false;
}
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/InefficientWeightDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/InefficientWeightDetectorTest.java
index ad0da87..644bb10 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/InefficientWeightDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/InefficientWeightDetectorTest.java
@@ -58,6 +58,15 @@ public class InefficientWeightDetectorTest extends AbstractCheckTest {
lintFiles("res/layout/baseline_weights.xml"));
}
+ public void testWeights4() throws Exception {
+ assertEquals(
+ "res/layout/activity_item_two_pane.xml:1: Warning: Set android:baselineAligned=\"false\" on this element for better performance [DisableBaselineAlignment]\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ "^\n" +
+ "0 errors, 1 warnings\n",
+ lintFiles("res/layout/activity_item_two_pane.xml"));
+ }
+
public void testNoVerticalWeights3() throws Exception {
// Orientation=vertical
assertEquals(
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml
new file mode 100644
index 0000000..b19047a
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/activity_item_two_pane.xml
@@ -0,0 +1,37 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:divider="?android:attr/dividerHorizontal"
+ android:orientation="horizontal"
+ android:showDividers="middle"
+ tools:context=".ItemListActivity" >
+
+ <!--
+ This layout is a two-pane layout for the Items
+ master/detail flow. See res/values-large/refs.xml and
+ res/values-sw600dp/refs.xml for an example of layout aliases
+ that replace the single-pane version of the layout with
+ this two-pane version.
+
+ For more on layout aliases, see:
+ http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters
+ -->
+
+ <fragment
+ android:id="@+id/item_list"
+ android:name="com.example.master.ItemListFragment"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ tools:layout="@android:layout/list_content" />
+
+ <FrameLayout
+ android:id="@+id/item_detail_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="3" />
+
+</LinearLayout>