diff options
author | Tor Norbye <tnorbye@google.com> | 2012-10-29 07:54:06 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2012-11-07 11:40:51 -0800 |
commit | 776b48c46e4d65a524b93ff258742099d6ad1650 (patch) | |
tree | 14575d438b28e5ffaface00698093a87008d5fed /lint/libs | |
parent | 088f24a417cf97799a5873016ad939f1a3096161 (diff) | |
download | sdk-776b48c46e4d65a524b93ff258742099d6ad1650.zip sdk-776b48c46e4d65a524b93ff258742099d6ad1650.tar.gz sdk-776b48c46e4d65a524b93ff258742099d6ad1650.tar.bz2 |
39030: Incorrect NewAPI Lint warning: check local methods
Change-Id: I8b22fbb29e014fb3efb434f33924d831003d41ee
Diffstat (limited to 'lint/libs')
5 files changed, 92 insertions, 1 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java index 26ff804..ba93d01 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java @@ -355,6 +355,7 @@ public class ApiDetector extends ResourceXmlDetector implements Detector.ClassSc owner = classNode.superName; } + boolean checkingSuperClass = false; while (owner != null) { int api = mApiDatabase.getCallVersion(owner, name, desc); if (api > minSdk) { @@ -367,6 +368,13 @@ public class ApiDetector extends ResourceXmlDetector implements Detector.ClassSc // calls. break; } + + if (!checkingSuperClass + && node.getOpcode() == Opcodes.INVOKEVIRTUAL + && methodDefinedLocally(classNode, name, desc)) { + break; + } + String fqcn; if (CONSTRUCTOR_NAME.equals(name)) { fqcn = "new " + ClassContext.getFqcn(owner); //$NON-NLS-1$ @@ -409,6 +417,8 @@ public class ApiDetector extends ResourceXmlDetector implements Detector.ClassSc } else { owner = null; } + + checkingSuperClass = true; } } else if (type == AbstractInsnNode.FIELD_INSN) { FieldInsnNode node = (FieldInsnNode) instruction; @@ -451,6 +461,19 @@ public class ApiDetector extends ResourceXmlDetector implements Detector.ClassSc } @SuppressWarnings("rawtypes") // ASM API + private boolean methodDefinedLocally(ClassNode classNode, String name, String desc) { + List methodList = classNode.methods; + for (Object m : methodList) { + MethodNode method = (MethodNode) m; + if (name.equals(method.name) && desc.equals(method.desc)) { + return true; + } + } + + return false; + } + + @SuppressWarnings("rawtypes") // ASM API private void checkSwitchBlock(ClassContext context, ClassNode classNode, FieldInsnNode field, MethodNode method, String name, String owner, int api, int minSdk) { // Switch statements on enums are tricky. The compiler will generate a method diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java index 963ea7c..3ef09aa 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java @@ -705,4 +705,26 @@ public class ApiDetectorTest extends AbstractCheckTest { "apicheck/TestLint.class.data=>bin/classes/TestLint.class" )); } + + public void testAllowLocalMethodsImplementingInaccessible() throws Exception { + // See http://code.google.com/p/android/issues/detail?id=39030 + assertEquals( + "src/test/pkg/ApiCallTest10.java:25: Error: Call requires API level 14 (current min is 4): android.view.View#onPopulateAccessibilityEvent [NewApi]\n" + + " super.onPopulateAccessibilityEvent(event); // Valid lint warning\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/ApiCallTest10.java:31: Error: Call requires API level 14 (current min is 4): android.view.View#dispatchGenericFocusedEvent [NewApi]\n" + + " return super.dispatchGenericFocusedEvent(event); // Should flag this\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/ApiCallTest10.java:40: Error: Call requires API level 14 (current min is 4): android.view.View#dispatchHoverEvent [NewApi]\n" + + " dispatchHoverEvent(null);\n" + + " ~~~~~~~~~~~~~~~~~~\n" + + "3 errors, 0 warnings\n", + + lintProject( + "apicheck/classpath=>.classpath", + "apicheck/minsdk4.xml=>AndroidManifest.xml", + "apicheck/ApiCallTest10.java.txt=>src/test/pkg/ApiCallTest10.java", + "apicheck/ApiCallTest10.class.data=>bin/classes/test/pkg/ApiCallTest10.class" + )); + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SdCardDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SdCardDetectorTest.java index 53272c8..5ad46b9 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SdCardDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SdCardDetectorTest.java @@ -65,7 +65,8 @@ public class SdCardDetectorTest extends AbstractCheckTest { " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + "src/test/pkg/SdCardTest.java:34: Warning: Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead [SdCardPath]\n" + " String s = \"file://sdcard/foo\";\n" + - " ~~~~~~~~~~~~~~~~~~~\n", + " ~~~~~~~~~~~~~~~~~~~\n" + + "0 errors, 13 warnings\n", lintProject("src/test/pkg/SdCardTest.java.txt=>src/test/pkg/SdCardTest.java")); } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data Binary files differnew file mode 100644 index 0000000..23ef1bd --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.class.data diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt new file mode 100644 index 0000000..ae02a81 --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest10.java.txt @@ -0,0 +1,45 @@ +package test.pkg; + +import android.os.Build; +import android.view.MotionEvent; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; + +public class ApiCallTest10 extends View { + public ApiCallTest10() { + super(null, null, 0); + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + onPopulateAccessibilityEvent(event); // Shouldn't warn here: method + // exists locally + return true; + } + return super.dispatchPopulateAccessibilityEvent(event); + } + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + super.onPopulateAccessibilityEvent(event); // Valid lint warning + // Additional override code here: + } + + @Override + protected boolean dispatchGenericFocusedEvent(MotionEvent event) { + return super.dispatchGenericFocusedEvent(event); // Should flag this + } + + protected boolean dispatchHoverEvent(int event) { + return false; + } + + public void test1() { + // Should flag this, because the local method has the wrong signature + dispatchHoverEvent(null); + + // Shouldn't flag this, local method makes it available + dispatchGenericFocusedEvent(null); + } +} |