Enhance inspection about SuccessOrFailure (related to KT-25621)

Increase performance by searching first SuccessOrFailure/runCatching/etc
in text of functions without return type.
Remove stdlib false positives, like success() & failure().
For catching extension, check also non-catching members.
Add "rename to *Catching" fix.
This commit is contained in:
Mikhail Glukhikh
2018-08-24 13:17:40 +03:00
parent 7a2d0a3bb2
commit c12f29ae30
16 changed files with 185 additions and 22 deletions
@@ -89,4 +89,22 @@
<problem_class severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function returning SuccessOrFailure</problem_class>
<description>Function returning SuccessOrFailure with a name that does not end with Catching</description>
</problem>
<problem>
<file>test.kt</file>
<line>60</line>
<module>light_idea_test_case</module>
<package>&lt;default&gt;</package>
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
<problem_class severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function returning SuccessOrFailure</problem_class>
<description>Function 'calcComplexCatching' returning 'SuccessOrFailure&lt;Double&gt;' without the corresponding function 'calcComplex' returning 'Double'</description>
</problem>
<problem>
<file>test.kt</file>
<line>67</line>
<module>light_idea_test_case</module>
<package>&lt;default&gt;</package>
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
<problem_class severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function returning SuccessOrFailure</problem_class>
<description>Function 'extensionActCatching' returning 'SuccessOrFailure&lt;Int&gt;' without the corresponding function 'extensionAct' returning 'Int'</description>
</problem>
</problems>
@@ -4,18 +4,18 @@ class SuccessOrFailure<T>(val value: T?) {
fun getOrThrow(): T = value ?: throw AssertionError("")
}
// YES
fun getSuccess() = SuccessOrFailure("123")
fun getSuccess() = success()
// YES
fun getSuccessExplicit(): SuccessOrFailure<Int> = SuccessOrFailure(456)
// NO (noCatching available)
// NO (not catching 'correct' available)
fun correctCatching() = SuccessOrFailure(true)
// NO (not SuccessOrFailure)
fun correct() = true
// YES
fun incorrectCatching() = SuccessOrFailure(3.14)
// YES
fun strangeCatching() = SuccessOrFailure(false)
// YES
fun strangeCatching() = runCatching { false }
// NO (not SuccessOrFailure)
fun strange() = 1
class Container {
@@ -23,7 +23,7 @@ class Container {
fun classGetSuccess() = SuccessOrFailure("123")
// YES
fun classGetSuccessExplicit(): SuccessOrFailure<Int> = SuccessOrFailure(456)
// NO (noCatching available)
// NO (not catching 'classCorrect' available)
fun classCorrectCatching() = SuccessOrFailure(true)
// NO (not SuccessOrFailure)
fun classCorrect() = true
@@ -38,6 +38,30 @@ fun test() {
val anonymous = fun() = SuccessOrFailure(45)
// YES
val lambda = { SuccessOrFailure(true) }
// NO yet
// NO yet (we do not report local *catching functions)
fun localCatching() = SuccessOrFailure(2.72)
}
}
// NO (stdlib)
fun success() = SuccessOrFailure(true)
// NO (stdlib)
fun failure() = SuccessOrFailure(false)
// NO (stdlib)
fun <T> runCatching(block: () -> T) = SuccessOrFailure(block())
// NO (stdlib)
fun <T> SuccessOrFailure<T>.id() = this
class ClassWithExtension() {
// NO (not SuccessOrFailure)
fun calc() = 12345
// NO (not SuccessOrFailure)
fun calcComplex(arg1: Int, arg2: Double): Double = arg1 + arg2
// YES (different parameters)
fun calcComplexCatching() = SuccessOrFailure(0.0)
}
// NO (extension to calc)
fun ClassWithExtension.calcCatching() = SuccessOrFailure(calc())
// NO (not SuccessOrFailure)
fun Container.extensionAct() = 42
// YES (different extension receiver)
fun ClassWithExtension.extensionActCatching() = SuccessOrFailure(42)