diff options
9 files changed, 99 insertions, 11 deletions
diff --git a/android/src/org/jetbrains/android/inspections/AndroidMissingOnClickHandlerInspection.java b/android/src/org/jetbrains/android/inspections/AndroidMissingOnClickHandlerInspection.java index 8d5b4c41040..d82d81a67ca 100644 --- a/android/src/org/jetbrains/android/inspections/AndroidMissingOnClickHandlerInspection.java +++ b/android/src/org/jetbrains/android/inspections/AndroidMissingOnClickHandlerInspection.java @@ -31,6 +31,7 @@ import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -114,6 +115,7 @@ public class AndroidMissingOnClickHandlerInspection extends LocalInspectionTool return result; } + @Nullable public static PsiClass findActivityClass(@NotNull Module module) { return JavaPsiFacade.getInstance(module.getProject()) .findClass(AndroidUtils.ACTIVITY_BASE_CLASS_NAME, module.getModuleWithDependenciesAndLibrariesScope(false)); @@ -188,13 +190,12 @@ public class AndroidMissingOnClickHandlerInspection extends LocalInspectionTool } } PsiClass activity = null; - for (PsiClass relatedActivity : myRelatedActivities) { - if (!resolvedClasses.contains(relatedActivity)) { + if (!containsOrExtends(resolvedClasses, relatedActivity)) { activity = relatedActivity; break; } - else if (activity == null && resolvedClassesWithMistake.contains(relatedActivity)) { + else if (activity == null && containsOrExtends(resolvedClassesWithMistake, relatedActivity)) { activity = relatedActivity; } } @@ -213,6 +214,22 @@ public class AndroidMissingOnClickHandlerInspection extends LocalInspectionTool } } + /** + * Returns true if the given associated activity class is either found in the given set of + * classes, or (less likely) extends any of the classes in that set + */ + private static boolean containsOrExtends(@NotNull Set<PsiClass> resolvedClasses, @NotNull PsiClass relatedActivity) { + if (resolvedClasses.contains(relatedActivity)) { + return true; + } + for (PsiClass resolvedClass : resolvedClasses) { + if (relatedActivity.isInheritor(resolvedClass, false)) { + return true; + } + } + return false; + } + private void reportMissingOnClickProblem(OnClickConverter.MyReference reference, PsiClass activity, String methodName, @@ -283,12 +300,6 @@ public class AndroidMissingOnClickHandlerInspection extends LocalInspectionTool final String paramType = myConverter.getDefaultMethodParameterType(myClass); AndroidCreateOnClickHandlerAction.addHandlerMethod(project, myClass, myMethodName, paramType); } - - @NotNull - private static String getShortName(@NotNull String fullClassName) { - final int index = fullClassName.lastIndexOf('.'); - return index < 0 ? fullClassName : fullClassName.substring(index + 1); - } } } diff --git a/android/testData/dom/layout/OnClickActivity7.java b/android/testData/dom/layout/OnClickActivity7.java new file mode 100644 index 00000000000..ba411a7c49c --- /dev/null +++ b/android/testData/dom/layout/OnClickActivity7.java @@ -0,0 +1,12 @@ +package p1.p2; + +import android.view.View; + +public abstract class Activity1 extends android.app.Activity { + + public void clickHandler1(View view) { + } + + public void clickHandler2() { + } +} diff --git a/android/testData/dom/layout/OnClickActivity8.java b/android/testData/dom/layout/OnClickActivity8.java new file mode 100644 index 00000000000..8171693512a --- /dev/null +++ b/android/testData/dom/layout/OnClickActivity8.java @@ -0,0 +1,8 @@ +package p1.p2; + +public class Activity2 extends Activity1 { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.onClickHighlighting5); + } +} diff --git a/android/testData/dom/layout/OnClickActivity9.java b/android/testData/dom/layout/OnClickActivity9.java new file mode 100644 index 00000000000..29c01a3d41a --- /dev/null +++ b/android/testData/dom/layout/OnClickActivity9.java @@ -0,0 +1,7 @@ +package p1.p2; + +public class Activity2 extends Activity1 { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } +} diff --git a/android/testData/dom/layout/onClickHighlighting5.xml b/android/testData/dom/layout/onClickHighlighting5.xml new file mode 100644 index 00000000000..dafa52589fd --- /dev/null +++ b/android/testData/dom/layout/onClickHighlighting5.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + tools:context=".Activity2"> +<TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:onClick="clickHandler1"/> + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:onClick="<warning descr="Method 'clickHandler2' is missing in 'Activity2' or has incorrect signature">clickHandler2</warning>"/> +</LinearLayout>
\ No newline at end of file diff --git a/android/testData/dom/layout/onClickHighlighting6.xml b/android/testData/dom/layout/onClickHighlighting6.xml new file mode 100644 index 00000000000..dafa52589fd --- /dev/null +++ b/android/testData/dom/layout/onClickHighlighting6.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + tools:context=".Activity2"> +<TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:onClick="clickHandler1"/> + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:onClick="<warning descr="Method 'clickHandler2' is missing in 'Activity2' or has incorrect signature">clickHandler2</warning>"/> +</LinearLayout>
\ No newline at end of file diff --git a/android/testData/lint/obsoleteDependency_after.gradle b/android/testData/lint/obsoleteDependency_after.gradle index 5c826a95b7e..5cdf89d6b3f 100644 --- a/android/testData/lint/obsoleteDependency_after.gradle +++ b/android/testData/lint/obsoleteDependency_after.gradle @@ -20,6 +20,6 @@ android { } dependencies { - freeCompile 'com.google.guava:guava:17.0.0' + freeCompile 'com.google.guava:guava:18.0.0' compile 'com.android.support:appcompat-v7:13.0.0' }
\ No newline at end of file diff --git a/android/testSrc/org/jetbrains/android/AndroidLintTest.java b/android/testSrc/org/jetbrains/android/AndroidLintTest.java index f56a1f8147d..3c3e81ffcc8 100644 --- a/android/testSrc/org/jetbrains/android/AndroidLintTest.java +++ b/android/testSrc/org/jetbrains/android/AndroidLintTest.java @@ -264,7 +264,7 @@ public class AndroidLintTest extends AndroidTestCase { public void testObsoleteDependency() throws Exception { doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintGradleDependencyInspection(), - "Change to 17.0.0", "build.gradle", "gradle"); + "Change to 18.0.0", "build.gradle", "gradle"); } public void testGradleDeprecation() throws Exception { diff --git a/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java b/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java index c7e7fe76589..32fd84770e1 100644 --- a/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java +++ b/android/testSrc/org/jetbrains/android/dom/AndroidLayoutDomTest.java @@ -714,6 +714,26 @@ public class AndroidLayoutDomTest extends AndroidDomTest { doTestHighlighting(); } + public void testOnClickHighlighting5() throws Throwable { + // Regression test for https://code.google.com/p/android/issues/detail?id=76262 + myFixture.allowTreeAccessForAllFiles(); + myFixture.enableInspections(AndroidMissingOnClickHandlerInspection.class); + myFixture.copyFileToProject(testFolder + "/OnClickActivity7.java", "src/p1/p2/Activity1.java"); + myFixture.copyFileToProject(testFolder + "/OnClickActivity8.java", "src/p1/p2/Activity2.java"); + doTestHighlighting(); + } + + public void testOnClickHighlighting6() throws Throwable { + // Like testOnClickHighlighting5, but instead of having the activity be found + // due to a setContentView call, it's declared explicitly with a tools:context + // attribute instead + myFixture.allowTreeAccessForAllFiles(); + myFixture.enableInspections(AndroidMissingOnClickHandlerInspection.class); + myFixture.copyFileToProject(testFolder + "/OnClickActivity7.java", "src/p1/p2/Activity1.java"); + myFixture.copyFileToProject(testFolder + "/OnClickActivity9.java", "src/p1/p2/Activity2.java"); + doTestHighlighting(); + } + public void testOnClickHighlightingJava() throws Throwable { myFixture.enableInspections(UnusedSymbolLocalInspection.class); final VirtualFile f = myFixture.copyFileToProject(testFolder + "/" + getTestName(true) + ".java", "src/p1/p2/MyActivity1.java"); |