From 0a6fd7387c281876ed719189058da4b5dbf30cc9 Mon Sep 17 00:00:00 2001 From: Tor Norbye Date: Sun, 27 Jan 2013 19:49:51 -0800 Subject: Fix API check via support library This CL fixes the API check such that it properly handles calls in the Android support library (android.support.*). There was an optimization to skip looking up inherited API calls once the API checker reaches the android.* namespace, since at that point all the inherited methods are inlined in the database, but this should not be done if the package starts with android.support.*, since those methods still could be inheriting from the Android APIs without appearing in the database. Change-Id: Iab7b9f98daa5507794a0673a8db53ce953f2bcd9 --- .../android/tools/lint/checks/ApiDetectorTest.java | 23 +++++++++++++++++++++ .../checks/data/apicheck/MyActivityImpl.class.data | Bin 0 -> 512 bytes .../checks/data/apicheck/MyActivityImpl.java.txt | 15 ++++++++++++++ .../data/apicheck/android-support-v4.jar.data | Bin 0 -> 385685 bytes .../com/android/tools/lint/checks/ApiDetector.java | 15 ++++++++++---- 5 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.class.data create mode 100644 lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.java.txt create mode 100644 lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/android-support-v4.jar.data 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 43d3727..947d27b 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 @@ -874,4 +874,27 @@ public class ApiDetectorTest extends AbstractCheckTest { "apicheck/ApiSourceCheck2.class.data=>bin/classes/test/pkg/ApiSourceCheck2.class" )); } + + public void testInheritCompatLibrary() throws Exception { + assertEquals("" + + "src/test/pkg/MyActivityImpl.java:8: Error: Call requires API level 11 (current min is 1): android.app.Activity#isChangingConfigurations [NewApi]\n" + + " boolean isChanging = super.isChangingConfigurations();\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/MyActivityImpl.java:13: Error: Call requires API level 11 (current min is 1): android.app.Activity#isChangingConfigurations [NewApi]\n" + + " return super.isChangingConfigurations();\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/MyActivityImpl.java:12: Error: This method is not overriding anything with the current build target, but will in API level 11 (current target is 3): test.pkg.MyActivityImpl#isChangingConfigurations [Override]\n" + + " public boolean isChangingConfigurations() {\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "3 errors, 0 warnings\n", + + lintProject( + "apicheck/classpath=>.classpath", + "apicheck/minsdk1.xml=>AndroidManifest.xml", + "project.properties1=>project.properties", + "apicheck/MyActivityImpl.java.txt=>src/test/pkg/MyActivityImpl.java", + "apicheck/MyActivityImpl.class.data=>bin/classes/test/pkg/MyActivityImpl.class", + "apicheck/android-support-v4.jar.data=>libs/android-support-v4.jar" + )); + } } diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.class.data new file mode 100644 index 0000000..6ae6b28 Binary files /dev/null and b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.class.data differ diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.java.txt new file mode 100644 index 0000000..e39daf8 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/MyActivityImpl.java.txt @@ -0,0 +1,15 @@ +package test.pkg; + +import android.app.Activity; +import android.support.v4.app.FragmentActivity; + +public class MyActivityImpl extends FragmentActivity { + public void test() { + boolean isChanging = super.isChangingConfigurations(); + } + + @Override + public boolean isChangingConfigurations() { + return super.isChangingConfigurations(); + } +} diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/android-support-v4.jar.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/android-support-v4.jar.data new file mode 100644 index 0000000..6080877 Binary files /dev/null and b/lint/cli/src/test/java/com/android/tools/lint/checks/data/apicheck/android-support-v4.jar.data differ 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 146e9e1..cc2b212 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 @@ -461,9 +461,10 @@ public class ApiDetector extends ResourceXmlDetector while (owner != null) { // For virtual dispatch, walk up the inheritance chain checking // each inherited method - if (owner.startsWith("android/") //$NON-NLS-1$ - || owner.startsWith("java/") //$NON-NLS-1$ - || owner.startsWith("javax/")) { //$NON-NLS-1$ + if ((owner.startsWith("android/") //$NON-NLS-1$ + && !owner.startsWith("android/support/")) //$NON-NLS-1$ + || owner.startsWith("java/") //$NON-NLS-1$ + || owner.startsWith("javax/")) { //$NON-NLS-1$ frameworkParent = owner; break; } @@ -628,7 +629,13 @@ public class ApiDetector extends ResourceXmlDetector || owner.startsWith("javax/")) { //$NON-NLS-1$ // The API map has already inlined all inherited methods // so no need to keep checking up the chain - owner = null; + // -- unless it's the support library which is also in + // the android/ namespace: + if (owner.startsWith("android/support/")) { //$NON-NLS-1$ + owner = context.getDriver().getSuperClass(owner); + } else { + owner = null; + } } else if (owner.startsWith("java/")) { //$NON-NLS-1$ if (owner.equals(LocaleDetector.DATE_FORMAT_OWNER)) { checkSimpleDateFormat(context, method, node, minSdk); -- cgit v1.1