diff options
Diffstat (limited to 'lint')
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 |