1.3 migration: make inspections working for non-experimental coroutines
This commit is contained in:
+9
-2
@@ -23,10 +23,11 @@ class DeferredResultUnusedInspection(@JvmField var standardOnly: Boolean = true)
|
||||
callChecker = fun(resolvedCall, inspection): Boolean {
|
||||
if (inspection !is DeferredResultUnusedInspection) return false
|
||||
return if (inspection.standardOnly) {
|
||||
resolvedCall.resultingDescriptor.fqNameOrNull() in fqNames
|
||||
resolvedCall.resultingDescriptor.fqNameOrNull() in fqNamesAll
|
||||
} else {
|
||||
val returnTypeClassifier = resolvedCall.resultingDescriptor.returnType?.constructor?.declarationDescriptor
|
||||
returnTypeClassifier?.importableFqName == deferred
|
||||
val importableFqName = returnTypeClassifier?.importableFqName
|
||||
importableFqName == deferred || importableFqName == deferredExperimental
|
||||
}
|
||||
}
|
||||
) {
|
||||
@@ -47,6 +48,12 @@ class DeferredResultUnusedInspection(@JvmField var standardOnly: Boolean = true)
|
||||
|
||||
private val fqNames: Set<FqName> = shortNames.mapTo(mutableSetOf()) { FqName("$COROUTINE_PACKAGE.$it") }
|
||||
|
||||
private val fqNamesExperimental: Set<FqName> = shortNames.mapTo(mutableSetOf()) { FqName("$COROUTINE_EXPERIMENTAL_PACKAGE.$it") }
|
||||
|
||||
private val fqNamesAll = fqNames + fqNamesExperimental
|
||||
|
||||
private val deferred = FqName("$COROUTINE_PACKAGE.Deferred")
|
||||
|
||||
private val deferredExperimental = FqName("$COROUTINE_EXPERIMENTAL_PACKAGE.Deferred")
|
||||
}
|
||||
}
|
||||
+18
-3
@@ -36,7 +36,13 @@ class RedundantAsyncInspection : AbstractCallChainChecker() {
|
||||
if (defaultContext!! && !defaultStart!!) return
|
||||
|
||||
var replacement = conversion.replacement
|
||||
if (defaultContext!! && defaultStart!!) replacement += "($defaultAsyncArgument)"
|
||||
if (defaultContext!! && defaultStart!!) {
|
||||
if (conversion === conversions[0]) {
|
||||
replacement += "($defaultAsyncArgument)"
|
||||
} else {
|
||||
replacement += "($defaultAsyncArgumentExperimental)"
|
||||
}
|
||||
}
|
||||
|
||||
val descriptor = holder.manager.createProblemDescriptor(
|
||||
expression,
|
||||
@@ -57,11 +63,20 @@ class RedundantAsyncInspection : AbstractCallChainChecker() {
|
||||
"$COROUTINE_PACKAGE.async",
|
||||
"$COROUTINE_PACKAGE.Deferred.await",
|
||||
"$COROUTINE_PACKAGE.withContext"
|
||||
),
|
||||
Conversion(
|
||||
"$COROUTINE_EXPERIMENTAL_PACKAGE.async",
|
||||
"$COROUTINE_EXPERIMENTAL_PACKAGE.Deferred.await",
|
||||
"$COROUTINE_EXPERIMENTAL_PACKAGE.withContext"
|
||||
)
|
||||
)
|
||||
|
||||
private val defaultAsyncArgument = "$COROUTINE_PACKAGE.DefaultDispatcher"
|
||||
private const val defaultAsyncArgument = "$COROUTINE_PACKAGE.DefaultDispatcher"
|
||||
|
||||
private const val defaultAsyncArgumentExperimental = "$COROUTINE_EXPERIMENTAL_PACKAGE.DefaultDispatcher"
|
||||
}
|
||||
}
|
||||
|
||||
internal const val COROUTINE_PACKAGE = "kotlinx.coroutines.experimental"
|
||||
internal const val COROUTINE_PACKAGE = "kotlinx.coroutines"
|
||||
|
||||
internal const val COROUTINE_EXPERIMENTAL_PACKAGE = "kotlinx.coroutines.experimental"
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package kotlinx.coroutines.experimental
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
}
|
||||
|
||||
interface CoroutineContext
|
||||
|
||||
object DefaultContext : CoroutineContext
|
||||
|
||||
enum class CoroutineStart {
|
||||
DEFAULT,
|
||||
LAZY,
|
||||
ATOMIC,
|
||||
UNDISPATCHED
|
||||
}
|
||||
|
||||
interface Job
|
||||
|
||||
fun <T> async(
|
||||
context: CoroutineContext = DefaultContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
parent: Job? = null,
|
||||
f: suspend () -> T
|
||||
): Deferred<T> {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
async { 42 }
|
||||
}
|
||||
|
||||
fun useIt(d: Deferred<Int>) {}
|
||||
|
||||
fun falsePositives() {
|
||||
async { 3 }.await()
|
||||
val res = async { 13 }
|
||||
useIt(async { 7 })
|
||||
}
|
||||
|
||||
class User
|
||||
|
||||
interface DbHandler {
|
||||
fun getUser(id: Long): Deferred<User>
|
||||
fun doStuff(): Deferred<Unit>
|
||||
}
|
||||
|
||||
fun DbHandler.test() {
|
||||
getUser(42L)
|
||||
val user = getUser(42L).await()
|
||||
doStuff()
|
||||
doStuff().await()
|
||||
}
|
||||
|
||||
operator fun Deferred<Int>.unaryPlus() = this
|
||||
operator fun Deferred<Int>.plus(arg: Int) = this
|
||||
|
||||
fun moreFalsePositives() {
|
||||
+(async { 0 })
|
||||
async { -1 } + 1
|
||||
}
|
||||
+27
@@ -26,4 +26,31 @@
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Deferred result is never used</problem_class>
|
||||
<description>Deferred result is never used</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>experimental.kt</file>
|
||||
<line>30</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<package><default></package>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/experimental.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Deferred result is never used</problem_class>
|
||||
<description>Deferred result is never used</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>experimental.kt</file>
|
||||
<line>49</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<package><default></package>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/experimental.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Deferred result is never used</problem_class>
|
||||
<description>Deferred result is never used</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>experimental.kt</file>
|
||||
<line>51</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<package><default></package>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/experimental.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Deferred result is never used</problem_class>
|
||||
<description>Deferred result is never used</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -1,4 +1,4 @@
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
}
|
||||
|
||||
interface CoroutineContext
|
||||
|
||||
object DefaultDispatcher : CoroutineContext
|
||||
|
||||
enum class CoroutineStart {
|
||||
DEFAULT,
|
||||
LAZY,
|
||||
ATOMIC,
|
||||
UNDISPATCHED
|
||||
}
|
||||
|
||||
interface Job
|
||||
|
||||
fun <T> async(
|
||||
context: CoroutineContext = DefaultDispatcher,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
parent: Job? = null,
|
||||
f: suspend () -> T
|
||||
): Deferred<T> {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun <T> runBlocking(
|
||||
context: CoroutineContext = DefaultDispatcher,
|
||||
f: suspend () -> T
|
||||
) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
suspend fun <T> withContext(
|
||||
context: CoroutineContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
f: suspend () -> T
|
||||
) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
suspend fun test(ctx: CoroutineContext) {
|
||||
<caret>async(ctx) { 42 }.await()
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
}
|
||||
|
||||
interface CoroutineContext
|
||||
|
||||
object DefaultDispatcher : CoroutineContext
|
||||
|
||||
enum class CoroutineStart {
|
||||
DEFAULT,
|
||||
LAZY,
|
||||
ATOMIC,
|
||||
UNDISPATCHED
|
||||
}
|
||||
|
||||
interface Job
|
||||
|
||||
fun <T> async(
|
||||
context: CoroutineContext = DefaultDispatcher,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
parent: Job? = null,
|
||||
f: suspend () -> T
|
||||
): Deferred<T> {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun <T> runBlocking(
|
||||
context: CoroutineContext = DefaultDispatcher,
|
||||
f: suspend () -> T
|
||||
) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
suspend fun <T> withContext(
|
||||
context: CoroutineContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
f: suspend () -> T
|
||||
) {
|
||||
TODO()
|
||||
}
|
||||
|
||||
suspend fun test(ctx: CoroutineContext) {
|
||||
withContext(ctx) { 42 }
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// PROBLEM: none
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// PROBLEM: none
|
||||
// WITH_RUNTIME
|
||||
|
||||
package kotlinx.coroutines.experimental
|
||||
package kotlinx.coroutines
|
||||
|
||||
interface Deferred<T> {
|
||||
suspend fun await(): T
|
||||
|
||||
+5
@@ -1358,6 +1358,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/coroutines/redundantAsync"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("experimental.kt")
|
||||
public void testExperimental() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/coroutines/redundantAsync/experimental.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/coroutines/redundantAsync/simple.kt");
|
||||
|
||||
Reference in New Issue
Block a user