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 = {}
|
private val simplify: (KtExpression) -> Unit = {}
|
||||||
) : AbstractKotlinInspection() {
|
) : AbstractKotlinInspection() {
|
||||||
|
|
||||||
protected fun analyzeFunction(function: KtFunction, toReport: PsiElement, holder: ProblemsHolder) {
|
protected fun analyzeFunction(function: KtNamedFunction, toReport: PsiElement, holder: ProblemsHolder) {
|
||||||
if (function is KtConstructor<*>) return
|
if (function is KtConstructor<*>) return
|
||||||
val returnTypeText = function.getReturnTypeReference()?.text
|
val returnTypeText = function.getReturnTypeReference()?.text
|
||||||
if (returnTypeText != null && typeShortName !in returnTypeText) return
|
if (returnTypeText != null && typeShortName !in returnTypeText) return
|
||||||
val name = (function as? KtNamedFunction)?.nameAsName?.asString()
|
val name = function.nameAsName?.asString()
|
||||||
if (name in allowedNames) return
|
if (name == null || name in allowedNames) return
|
||||||
if (function is KtNamedFunction) {
|
val receiverTypeReference = function.receiverTypeReference
|
||||||
val receiverTypeReference = function.receiverTypeReference
|
// Filter given type extensions
|
||||||
// Filter given type extensions
|
if (receiverTypeReference != null && typeShortName in receiverTypeReference.text) return
|
||||||
if (receiverTypeReference != null && typeShortName in receiverTypeReference.text) return
|
if (returnTypeText == null) {
|
||||||
}
|
|
||||||
if (function is KtFunctionLiteral || returnTypeText == null) {
|
|
||||||
// Heuristics to save performance: check if something creates given type in function text
|
// Heuristics to save performance: check if something creates given type in function text
|
||||||
val text = function.bodyExpression?.text
|
val text = function.bodyExpression?.text
|
||||||
if (text != null && allowedNames.none { it in text } && typeShortName !in text && allowedSuffix !in text) return
|
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 returnType = descriptor.returnType ?: return
|
||||||
val returnTypeClass = returnType.constructor.declarationDescriptor as? ClassDescriptor ?: return
|
val returnTypeClass = returnType.constructor.declarationDescriptor as? ClassDescriptor ?: return
|
||||||
if (returnTypeClass.fqNameSafe.asString() != typeFullName) return
|
if (returnTypeClass.fqNameSafe.asString() != typeFullName) return
|
||||||
|
|
||||||
if (name != null && name.endsWith(allowedSuffix)) {
|
if (name.endsWith(allowedSuffix)) {
|
||||||
analyzeFunctionWithAllowedSuffix(name, descriptor, toReport, holder)
|
analyzeFunctionWithAllowedSuffix(name, descriptor, toReport, holder)
|
||||||
} else {
|
} else {
|
||||||
holder.registerProblem(
|
holder.registerProblem(
|
||||||
toReport,
|
toReport,
|
||||||
"Function returning $typeShortName with a name that does not end with $allowedSuffix",
|
"Function returning $typeShortName with a name that does not end with $allowedSuffix",
|
||||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
*listOfNotNull(
|
*listOf(
|
||||||
name?.let { RenameToFix("$it$allowedSuffix") },
|
RenameToFix("$name$allowedSuffix"),
|
||||||
AddCallOrUnwrapTypeFix(
|
AddCallOrUnwrapTypeFix(
|
||||||
withBody = function.hasBody(),
|
withBody = function.hasBody(),
|
||||||
functionName = suggestedFunctionNameToCall,
|
functionName = suggestedFunctionNameToCall,
|
||||||
@@ -75,10 +73,6 @@ abstract class AbstractIsResultInspection(
|
|||||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||||
analyzeFunction(function, function.nameIdentifier ?: function.funKeyword ?: function, holder)
|
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>
|
<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>
|
<description>Function returning Result with a name that does not end with Catching</description>
|
||||||
</problem>
|
</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>
|
<problem>
|
||||||
<file>test.kt</file>
|
<file>test.kt</file>
|
||||||
<line>60</line>
|
<line>60</line>
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ class Container {
|
|||||||
fun test() {
|
fun test() {
|
||||||
// YES
|
// YES
|
||||||
fun localGetSuccess() = Result("123")
|
fun localGetSuccess() = Result("123")
|
||||||
// YES
|
// NO (no name)
|
||||||
val anonymous = fun() = Result(45)
|
val anonymous = fun() = Result(45)
|
||||||
// YES
|
// NO (no name)
|
||||||
val lambda = { Result(true) }
|
val lambda = { Result(true) }
|
||||||
// NO yet (we do not report local *catching functions)
|
// NO yet (we do not report local *catching functions)
|
||||||
fun localCatching() = Result(2.72)
|
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
|
package kotlin
|
||||||
|
|
||||||
fun test() {
|
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
|
package kotlin
|
||||||
|
|
||||||
fun test() {
|
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
|
package kotlin
|
||||||
|
|
||||||
fun test(arg: Boolean) {
|
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
|
package kotlin
|
||||||
|
|
||||||
fun test() {
|
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");
|
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")
|
@TestMetadata("rename.kt")
|
||||||
public void testRename() throws Exception {
|
public void testRename() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/coroutines/deferredIsResult/rename.kt");
|
runTest("idea/testData/inspectionsLocal/coroutines/deferredIsResult/rename.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user