Don't suggest "return type is..." inspections for anonymous functions
#KT-29290 Fixed
This commit is contained in:
+11
-17
@@ -27,37 +27,35 @@ abstract class AbstractIsResultInspection(
|
||||
private val simplify: (KtExpression) -> Unit = {}
|
||||
) : AbstractKotlinInspection() {
|
||||
|
||||
protected fun analyzeFunction(function: KtFunction, toReport: PsiElement, holder: ProblemsHolder) {
|
||||
protected fun analyzeFunction(function: KtNamedFunction, toReport: PsiElement, holder: ProblemsHolder) {
|
||||
if (function is KtConstructor<*>) return
|
||||
val returnTypeText = function.getReturnTypeReference()?.text
|
||||
if (returnTypeText != null && typeShortName !in returnTypeText) return
|
||||
val name = (function as? KtNamedFunction)?.nameAsName?.asString()
|
||||
if (name in allowedNames) return
|
||||
if (function is KtNamedFunction) {
|
||||
val receiverTypeReference = function.receiverTypeReference
|
||||
// Filter given type extensions
|
||||
if (receiverTypeReference != null && typeShortName in receiverTypeReference.text) return
|
||||
}
|
||||
if (function is KtFunctionLiteral || returnTypeText == null) {
|
||||
val name = function.nameAsName?.asString()
|
||||
if (name == null || name in allowedNames) return
|
||||
val receiverTypeReference = function.receiverTypeReference
|
||||
// Filter given type extensions
|
||||
if (receiverTypeReference != null && typeShortName in receiverTypeReference.text) return
|
||||
if (returnTypeText == null) {
|
||||
// Heuristics to save performance: check if something creates given type in function text
|
||||
val text = function.bodyExpression?.text
|
||||
if (text != null && allowedNames.none { it in text } && typeShortName !in text && allowedSuffix !in text) return
|
||||
}
|
||||
|
||||
val descriptor = function.resolveToDescriptorIfAny() as? FunctionDescriptor ?: return
|
||||
val descriptor = function.resolveToDescriptorIfAny() ?: return
|
||||
val returnType = descriptor.returnType ?: return
|
||||
val returnTypeClass = returnType.constructor.declarationDescriptor as? ClassDescriptor ?: return
|
||||
if (returnTypeClass.fqNameSafe.asString() != typeFullName) return
|
||||
|
||||
if (name != null && name.endsWith(allowedSuffix)) {
|
||||
if (name.endsWith(allowedSuffix)) {
|
||||
analyzeFunctionWithAllowedSuffix(name, descriptor, toReport, holder)
|
||||
} else {
|
||||
holder.registerProblem(
|
||||
toReport,
|
||||
"Function returning $typeShortName with a name that does not end with $allowedSuffix",
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
*listOfNotNull(
|
||||
name?.let { RenameToFix("$it$allowedSuffix") },
|
||||
*listOf(
|
||||
RenameToFix("$name$allowedSuffix"),
|
||||
AddCallOrUnwrapTypeFix(
|
||||
withBody = function.hasBody(),
|
||||
functionName = suggestedFunctionNameToCall,
|
||||
@@ -75,10 +73,6 @@ abstract class AbstractIsResultInspection(
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
analyzeFunction(function, function.nameIdentifier ?: function.funKeyword ?: function, holder)
|
||||
}
|
||||
|
||||
override fun visitLambdaExpression(lambdaExpression: KtLambdaExpression) {
|
||||
analyzeFunction(lambdaExpression.functionLiteral, lambdaExpression.functionLiteral.lBrace, holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-18
@@ -71,24 +71,6 @@
|
||||
<problem_class severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function returning Result directly</problem_class>
|
||||
<description>Function returning Result with a name that does not end with Catching</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>38</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<package><default></package>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function returning Result directly</problem_class>
|
||||
<description>Function returning Result with a name that does not end with Catching</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>40</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<package><default></package>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WEAK WARNING" attribute_key="INFO_ATTRIBUTES">Function returning Result directly</problem_class>
|
||||
<description>Function returning Result with a name that does not end with Catching</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>60</line>
|
||||
|
||||
@@ -34,9 +34,9 @@ class Container {
|
||||
fun test() {
|
||||
// YES
|
||||
fun localGetSuccess() = Result("123")
|
||||
// YES
|
||||
// NO (no name)
|
||||
val anonymous = fun() = Result(45)
|
||||
// YES
|
||||
// NO (no name)
|
||||
val lambda = { Result(true) }
|
||||
// NO yet (we do not report local *catching functions)
|
||||
fun localCatching() = Result(2.72)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// WITH_RUNTIME
|
||||
// PROBLEM: none
|
||||
package kotlinx.coroutines
|
||||
|
||||
suspend fun barAsync(): Deferred<String>? {
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun foo() {
|
||||
" ".let <caret>{ barAsync() }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// PROBLEM: none
|
||||
package kotlin
|
||||
|
||||
fun test() {
|
||||
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
package kotlin
|
||||
|
||||
fun test() {
|
||||
val x = fun() = Result("123").getOrThrow()
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// PROBLEM: none
|
||||
package kotlin
|
||||
|
||||
fun test() {
|
||||
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
package kotlin
|
||||
|
||||
fun test() {
|
||||
val x = { Result(true).getOrThrow() }
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// PROBLEM: none
|
||||
package kotlin
|
||||
|
||||
fun test(arg: Boolean) {
|
||||
|
||||
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
package kotlin
|
||||
|
||||
fun test(arg: Boolean) {
|
||||
val x = foo@{
|
||||
(if (!arg) {
|
||||
return@foo Result(true).getOrThrow()
|
||||
} else {
|
||||
Result(false)
|
||||
}).getOrThrow()
|
||||
}
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// PROBLEM: none
|
||||
package kotlin
|
||||
|
||||
fun test() {
|
||||
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
package kotlin
|
||||
|
||||
fun test() {
|
||||
val x = foo@<caret>{ return@foo Result(true).getOrThrow() }
|
||||
}
|
||||
+5
@@ -2160,6 +2160,11 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
||||
runTest("idea/testData/inspectionsLocal/coroutines/deferredIsResult/complex.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambda.kt")
|
||||
public void testLambda() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/coroutines/deferredIsResult/lambda.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("rename.kt")
|
||||
public void testRename() throws Exception {
|
||||
runTest("idea/testData/inspectionsLocal/coroutines/deferredIsResult/rename.kt");
|
||||
|
||||
Reference in New Issue
Block a user