Skip to content
This repository has been archived by the owner on Mar 16, 2021. It is now read-only.

Bugfix: Lint Checks not Triggering #187

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@ class TiLintRegistry : IssueRegistry() {
}
)

override val api: Int = com.android.tools.lint.detector.api.CURRENT_API
/**
* Lint API Version for which the Checks are build.
*
* See [com.android.tools.lint.detector.api.describeApi] for possible options
*/
override val api: Int = 1
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ abstract class BaseMissingViewDetector : Detector(), Detector.UastScanner {
return tryFindViewImplementation(context, uastContext.getClass(resolvedType), viewInterface)
}
}
return false

val superClass = declaration.superClass

return superClass != null && tryFindViewImplementation(context, superClass, viewInterface)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,22 @@ class MissingViewInThirtyInchDetector : BaseMissingViewDetector() {
.firstOrNull()
?: (type as? PsiClassType)?.let { tryFindViewInterface(it) }
}
?: extendedType.superTypes.firstNotNullResult { superType ->
(superType as? PsiClassType)?.let { tryFindViewInterface(it) }
}
}

override fun allowMissingViewInterface(context: JavaContext, declaration: UClass,
viewInterface: PsiType): Boolean {
// if the superClass is one of the TI base classes, prevent deeper recursive checks
val superClass = declaration.superClass
.let { sClass ->
if (TI_CLASS_NAMES.any { tiName -> tiName == sClass?.qualifiedName }) null else sClass
}

// Interface not implemented; check if provideView() is overridden instead
return declaration.findMethodsByName(PROVIDE_VIEW_METHOD, true)
.any { viewInterface == it.returnType }
return declaration.findMethodsByName(PROVIDE_VIEW_METHOD, false)
.firstNotNullResult { viewInterface == it.returnType }
?: (superClass != null && allowMissingViewInterface(context, superClass, viewInterface))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,226 @@ class MissingViewInThirtyInchDetectorTest : LintDetectorTest() {
).isEqualTo(NO_WARNINGS)
}

fun testJava_Activity_throughTransitiveBaseClass_withBasePresenter_withBaseView_noWarning() {
val baseView = java(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"interface BaseView extends TiView {\n" +
"}"
)

val basePresenter = java(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"abstract class BasePresenter<V extends BaseView> extends TiPresenter<V> {\n" +
"}"
)

val baseActivity = java(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"abstract class BaseActivity<P extends BasePresenter<V>, V extends BaseView> extends TiActivity<P, V> {\n" +
"}"
)

val activity = java(
"package foo;\n" +
"class InformationActivity extends BaseActivity<MyPresenter, MyView> implements MyView {\n" +
"}"
)

val view = java(
"package foo;\n" +
"interface MyView extends BaseView {\n" +
"}"
)

val customPresenter = java(
"package foo;\n" +
"class MyPresenter extends BasePresenter<MyView> {\n" +
"}"
)

assertThat(
lintProject(
tiActivityStub,
tiPresenterStub,
tiViewStub,
baseView,
view,
basePresenter,
customPresenter,
baseActivity,
activity
)
).isEqualTo(NO_WARNINGS)
}

fun testKotlin_Activity_throughTransitiveBaseClass_withBasePresenter_withBaseView_noWarning() {
val baseView = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"interface BaseView : TiView {\n" +
"}"
)

val basePresenter = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"abstract class BasePresenter<V : BaseView> : TiPresenter<V>() {\n" +
"}"
)

val baseActivity = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"abstract class BaseActivity<P : BasePresenter<V>, V : BaseView> : TiActivity<P, V>(), MyView {\n" +
"}"
)

val activity = kotlin(
"package foo\n" +
"class InformationActivity : BaseActivity<MyPresenter, MyView>() {\n" +
"}"
)

val view = kotlin(
"package foo\n" +
"interface MyView : BaseView {\n" +
"}"
)

val customPresenter = kotlin(
"package foo\n" +
"class MyPresenter : BasePresenter<MyView>() {\n" +
"}"
)

assertThat(
lintProject(
tiActivityStub,
tiPresenterStub,
tiViewStub,
baseView,
view,
basePresenter,
customPresenter,
baseActivity,
activity
)
).isEqualTo(NO_WARNINGS)
}

fun testJava_Activity_throughTransitiveBaseClass_withBasePresenter_withBaseView_hasWarning() {
val baseView = java(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"interface BaseView extends TiView {\n" +
"}"
)

val basePresenter = java(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"abstract class BasePresenter<V extends BaseView> extends TiPresenter<V> {\n" +
"}"
)

val baseActivity = java(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"abstract class BaseActivity<P extends BasePresenter<V>, V extends BaseView> extends TiActivity<P, V> {\n" +
"}"
)

val activity = java(
"package foo;\n" +
"class InformationActivity extends BaseActivity<MyPresenter, MyView> {\n" +
"}"
)

val view = java(
"package foo;\n" +
"interface MyView extends BaseView {\n" +
"}"
)

val customPresenter = java(
"package foo;\n" +
"class MyPresenter extends BasePresenter<MyView> {\n" +
"}"
)

assertThat(
lintProject(
tiActivityStub,
tiPresenterStub,
tiViewStub,
baseView,
view,
basePresenter,
customPresenter,
baseActivity,
activity
)
).containsOnlyOnce(TiIssue.MissingView.id)
}

fun testKotlin_Activity_throughTransitiveBaseClass_withBasePresenter_withBaseView_hasWarning() {
val baseView = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"interface BaseView : TiView {\n" +
"}"
)

val basePresenter = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"abstract class BasePresenter<V : BaseView> : TiPresenter<V>() {\n" +
"}"
)

val baseActivity = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"abstract class BaseActivity<P : BasePresenter<V>, V : BaseView> : TiActivity<P, V>() {\n" +
"}"
)

val activity = kotlin(
"package foo\n" +
"class InformationActivity : BaseActivity<MyPresenter, MyView>() {\n" +
"}"
)

val view = kotlin(
"package foo\n" +
"interface MyView : BaseView {\n" +
"}"
)

val customPresenter = kotlin(
"package foo\n" +
"class MyPresenter : BasePresenter<MyView>() {\n" +
"}"
)

assertThat(
lintProject(
tiActivityStub,
tiPresenterStub,
tiViewStub,
baseView,
view,
basePresenter,
customPresenter,
baseActivity,
activity
)
).containsOnlyOnce(TiIssue.MissingView.id)
}

fun testKotlin_Activity_throughBaseClass_noWarning() {
val baseActivity = kotlin(
"package foo;\n" +
Expand Down Expand Up @@ -488,7 +708,7 @@ class MissingViewInThirtyInchDetectorTest : LintDetectorTest() {
val baseActivity = kotlin(
"package foo;\n" +
"import net.grandcentrix.thirtyinch.*;\n" +
"public class BaseActivity : TiActivity<TiPresenter<MyView>, MyView>() {\n" +
"public abstract class BaseActivity : TiActivity<TiPresenter<MyView>, MyView>() {\n" +
"}"
)

Expand Down Expand Up @@ -825,7 +1045,7 @@ class MissingViewInThirtyInchDetectorTest : LintDetectorTest() {
val baseFragment = kotlin(
"package foo\n" +
"import net.grandcentrix.thirtyinch.*\n" +
"class BaseFragment : TiFragment<TiPresenter<MyView>, MyView>() {\n" +
"abstract class BaseFragment : TiFragment<TiPresenter<MyView>, MyView>() {\n" +
"}"
)

Expand Down