aboutsummaryrefslogtreecommitdiffstats
path: root/lint
diff options
context:
space:
mode:
Diffstat (limited to 'lint')
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/MainTest.java5
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java54
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles2.xml8
-rw-r--r--lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java71
4 files changed, 114 insertions, 24 deletions
diff --git a/lint/cli/src/test/java/com/android/tools/lint/MainTest.java b/lint/cli/src/test/java/com/android/tools/lint/MainTest.java
index 2ff470e..8ba40aa 100644
--- a/lint/cli/src/test/java/com/android/tools/lint/MainTest.java
+++ b/lint/cli/src/test/java/com/android/tools/lint/MainTest.java
@@ -139,6 +139,11 @@ public class MainTest extends AbstractCheckTest {
"@TargetApi(11), such that this check considers 11 rather than your manifest\n" +
"file's minimum SDK as the required API level.\n" +
"\n" +
+ "If you are deliberately setting android: attributes in style definitions, make\n" +
+ "sure you place this in a values-v11 folder in order to avoid running into\n" +
+ "runtime conflicts on certain devices where manufacturers have added custom\n" +
+ "attributes whose ids conflict with the new ones on later platforms.\n" +
+ "\n" +
"Similarly, you can use tools:targetApi=\"11\" in an XML file to indicate that\n" +
"the element will only be inflated in an adequate context.\n" +
"\n" +
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
index 1bcbfaa..a4c7e4a 100644
--- a/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ApiDetectorTest.java
@@ -786,4 +786,58 @@ public class ApiDetectorTest extends AbstractCheckTest {
"apicheck/ApiSourceCheck.class.data=>bin/classes/test/pkg/ApiSourceCheck.class"
));
}
+
+ public void testStyleDeclaration() throws Exception {
+ assertEquals(""
+ + "res/values/styles2.xml:5: Error: android:actionBarStyle requires API level 11 (current min is 10) [NewApi]\n"
+ + " <item name=\"android:actionBarStyle\">...</item>\n"
+ + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+ + "1 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "res/values/styles2.xml"
+ ));
+ }
+
+ public void testStyleDeclarationInV9() throws Exception {
+ assertEquals(""
+ + "res/values-v9/styles2.xml:5: Error: android:actionBarStyle requires API level 11 (current min is 10) [NewApi]\n"
+ + " <item name=\"android:actionBarStyle\">...</item>\n"
+ + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+ + "1 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "res/values/styles2.xml=>res/values-v9/styles2.xml"
+ ));
+ }
+
+ public void testStyleDeclarationInV11() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "res/values/styles2.xml=>res/values-v11/styles2.xml"
+ ));
+ }
+
+ public void testStyleDeclarationInV14() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk10.xml=>AndroidManifest.xml",
+ "project.properties1=>project.properties",
+ "res/values/styles2.xml=>res/values-v14/styles2.xml"
+ ));
+ }
}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles2.xml
new file mode 100644
index 0000000..45422cb
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/res/values/styles2.xml
@@ -0,0 +1,8 @@
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style android:name="MyStyle" parent="android:Theme.Light">
+ <!-- if the minSdk level is less then 11, then this should be a lint error, since android:actionBarStyle is since API 11,
+ unless this is in a -v11 (or better) resource folder -->
+ <item name="android:actionBarStyle">...</item>
+ <item name="android:textColor">#999999</item>
+ </style>
+</resources>
diff --git a/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java b/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java
index ab6e48a..c5b70e7 100644
--- a/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java
+++ b/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ApiDetector.java
@@ -19,9 +19,13 @@ package com.android.tools.lint.checks;
import static com.android.SdkConstants.ANDROID_PREFIX;
import static com.android.SdkConstants.ANDROID_THEME_PREFIX;
import static com.android.SdkConstants.ATTR_CLASS;
+import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.ATTR_TARGET_API;
import static com.android.SdkConstants.CONSTRUCTOR_NAME;
+import static com.android.SdkConstants.PREFIX_ANDROID;
import static com.android.SdkConstants.R_CLASS;
+import static com.android.SdkConstants.TAG_ITEM;
+import static com.android.SdkConstants.TAG_STYLE;
import static com.android.SdkConstants.TARGET_API;
import static com.android.SdkConstants.TOOLS_URI;
import static com.android.SdkConstants.VIEW_TAG;
@@ -146,6 +150,11 @@ public class ApiDetector extends ResourceXmlDetector
"`@TargetApi(11)`, such that this check considers 11 rather than your manifest " +
"file's minimum SDK as the required API level.\n" +
"\n" +
+ "If you are deliberately setting `android:` attributes in style definitions, " +
+ "make sure you place this in a `values-v11` folder in order to avoid running " +
+ "into runtime conflicts on certain devices where manufacturers have added " +
+ "custom attributes whose ids conflict with the new ones on later platforms.\n" +
+ "\n" +
"Similarly, you can use tools:targetApi=\"11\" in an XML file to indicate that " +
"the element will only be inflated in an adequate context.\n" +
"\n" +
@@ -244,42 +253,56 @@ public class ApiDetector extends ResourceXmlDetector
String value = attribute.getValue();
+ String owner = null;
+ String name = null;
+
String prefix;
if (value.startsWith(ANDROID_PREFIX)) {
prefix = ANDROID_PREFIX;
} else if (value.startsWith(ANDROID_THEME_PREFIX)) {
prefix = ANDROID_THEME_PREFIX;
+ } else if (value.startsWith(PREFIX_ANDROID) && ATTR_NAME.equals(attribute.getName())
+ && TAG_ITEM.equals(attribute.getOwnerElement().getTagName())
+ && attribute.getOwnerElement().getParentNode() != null
+ && TAG_STYLE.equals(attribute.getOwnerElement().getParentNode().getNodeName())) {
+ owner = "android/R$attr"; //$NON-NLS-1$
+ name = value.substring(PREFIX_ANDROID.length());
+ prefix = PREFIX_ANDROID;
} else {
return;
}
- // Convert @android:type/foo into android/R$type and "foo"
- int index = value.indexOf('/', prefix.length());
- if (index != -1) {
- String owner = "android/R$" //$NON-NLS-1$
- + value.substring(prefix.length(), index);
- String name = value.substring(index + 1);
- if (name.indexOf('.') != -1) {
- name = name.replace('.', '_');
- }
- int api = mApiDatabase.getFieldVersion(owner, name);
- int minSdk = getMinSdk(context);
- if (api > minSdk && api > context.getFolderVersion()
- && api > getLocalMinSdk(attribute.getOwnerElement())) {
- // Don't complain about resource references in the tools namespace,
- // such as for example "tools:layout="@android:layout/list_content",
- // used only for designtime previews
- if (TOOLS_URI.equals(attribute.getNamespaceURI())) {
- return;
+ if (owner == null) {
+ // Convert @android:type/foo into android/R$type and "foo"
+ int index = value.indexOf('/', prefix.length());
+ if (index != -1) {
+ owner = "android/R$" //$NON-NLS-1$
+ + value.substring(prefix.length(), index);
+ name = value.substring(index + 1);
+ if (name.indexOf('.') != -1) {
+ name = name.replace('.', '_');
}
-
- Location location = context.getLocation(attribute);
- String message = String.format(
- "%1$s requires API level %2$d (current min is %3$d)",
- value, api, minSdk);
- context.report(UNSUPPORTED, attribute, location, message, null);
+ } else {
+ return;
}
}
+ int api = mApiDatabase.getFieldVersion(owner, name);
+ int minSdk = getMinSdk(context);
+ if (api > minSdk && api > context.getFolderVersion()
+ && api > getLocalMinSdk(attribute.getOwnerElement())) {
+ // Don't complain about resource references in the tools namespace,
+ // such as for example "tools:layout="@android:layout/list_content",
+ // used only for designtime previews
+ if (TOOLS_URI.equals(attribute.getNamespaceURI())) {
+ return;
+ }
+
+ Location location = context.getLocation(attribute);
+ String message = String.format(
+ "%1$s requires API level %2$d (current min is %3$d)",
+ value, api, minSdk);
+ context.report(UNSUPPORTED, attribute, location, message, null);
+ }
}
@Override