@@ -29,17 +29,7 @@ import org.jetbrains.kotlin.types.KotlinType
29
29
class JavaCollectionsStaticMethodInspection : AbstractKotlinInspection () {
30
30
override fun buildVisitor (holder : ProblemsHolder , isOnTheFly : Boolean ): PsiElementVisitor {
31
31
return dotQualifiedExpressionVisitor(fun (expression) {
32
- val callExpression = expression.callExpression ? : return
33
- val args = callExpression.valueArguments
34
- val firstArg = args.firstOrNull() ? : return
35
- val context = expression.analyze(BodyResolveMode .PARTIAL )
36
- if (firstArg.getArgumentExpression()?.getType(context)?.isMutableListOrSubtype() != true ) return
37
-
38
- val descriptor = expression.getResolvedCall(context)?.resultingDescriptor as ? JavaMethodDescriptor ? : return
39
- val fqName = descriptor.importableFqName?.asString() ? : return
40
- if (! canReplaceWithStdLib(expression, fqName, args)) return
41
-
42
- val methodName = fqName.split(" ." ).last()
32
+ val (methodName, firstArg) = getTargetMethodOnMutableList(expression) ? : return
43
33
holder.registerProblem(
44
34
expression,
45
35
" Java Collections static method call should be replaced with Kotlin stdlib" ,
@@ -49,23 +39,49 @@ class JavaCollectionsStaticMethodInspection : AbstractKotlinInspection() {
49
39
})
50
40
}
51
41
52
- private fun canReplaceWithStdLib (expression : KtDotQualifiedExpression , fqName : String , args : List <KtValueArgument >): Boolean {
53
- if (! fqName.startsWith(" java.util.Collections." )) return false
54
- val size = args.size
55
- return when (fqName) {
56
- " java.util.Collections.fill" -> checkApiVersion(ApiVersion .KOTLIN_1_2 , expression) && size == 2
57
- " java.util.Collections.reverse" -> size == 1
58
- " java.util.Collections.shuffle" -> checkApiVersion(ApiVersion .KOTLIN_1_2 , expression) && (size == 1 || size == 2 )
59
- " java.util.Collections.sort" -> {
60
- size == 1 || (size == 2 && args.getOrNull(1 )?.getArgumentExpression() is KtLambdaExpression )
42
+ companion object {
43
+ fun getTargetMethodOnImmutableList (expression : KtDotQualifiedExpression ) =
44
+ getTargetMethod(expression) { isListOrSubtype() && ! isMutableListOrSubtype() }
45
+
46
+ private fun getTargetMethodOnMutableList (expression : KtDotQualifiedExpression ) =
47
+ getTargetMethod(expression) { isMutableListOrSubtype() }
48
+
49
+ private fun getTargetMethod (
50
+ expression : KtDotQualifiedExpression ,
51
+ isValidFirstArgument : KotlinType .() -> Boolean
52
+ ): Pair <String , KtValueArgument >? {
53
+ val callExpression = expression.callExpression ? : return null
54
+ val args = callExpression.valueArguments
55
+ val firstArg = args.firstOrNull() ? : return null
56
+ val context = expression.analyze(BodyResolveMode .PARTIAL )
57
+ if (firstArg.getArgumentExpression()?.getType(context)?.isValidFirstArgument() != true ) return null
58
+
59
+ val descriptor = expression.getResolvedCall(context)?.resultingDescriptor as ? JavaMethodDescriptor ? : return null
60
+ val fqName = descriptor.importableFqName?.asString() ? : return null
61
+ if (! canReplaceWithStdLib(expression, fqName, args)) return null
62
+
63
+ val methodName = fqName.split(" ." ).last()
64
+ return methodName to firstArg
65
+ }
66
+
67
+ private fun canReplaceWithStdLib (expression : KtDotQualifiedExpression , fqName : String , args : List <KtValueArgument >): Boolean {
68
+ if (! fqName.startsWith(" java.util.Collections." )) return false
69
+ val size = args.size
70
+ return when (fqName) {
71
+ " java.util.Collections.fill" -> checkApiVersion(ApiVersion .KOTLIN_1_2 , expression) && size == 2
72
+ " java.util.Collections.reverse" -> size == 1
73
+ " java.util.Collections.shuffle" -> checkApiVersion(ApiVersion .KOTLIN_1_2 , expression) && (size == 1 || size == 2 )
74
+ " java.util.Collections.sort" -> {
75
+ size == 1 || (size == 2 && args.getOrNull(1 )?.getArgumentExpression() is KtLambdaExpression )
76
+ }
77
+ else -> false
61
78
}
62
- else -> false
63
79
}
64
- }
65
80
66
- private fun checkApiVersion (requiredVersion : ApiVersion , expression : KtDotQualifiedExpression ): Boolean {
67
- val module = ModuleUtilCore .findModuleForPsiElement(expression) ? : return true
68
- return module.languageVersionSettings.apiVersion >= requiredVersion
81
+ private fun checkApiVersion (requiredVersion : ApiVersion , expression : KtDotQualifiedExpression ): Boolean {
82
+ val module = ModuleUtilCore .findModuleForPsiElement(expression) ? : return true
83
+ return module.languageVersionSettings.apiVersion >= requiredVersion
84
+ }
69
85
}
70
86
71
87
}
@@ -77,6 +93,13 @@ private fun KotlinType.isMutableListOrSubtype(): Boolean {
77
93
return isMutableList() || constructor .supertypes.reversed().any { it.isMutableList() }
78
94
}
79
95
96
+ private fun KotlinType.isList () =
97
+ constructor .declarationDescriptor?.fqNameSafe == KotlinBuiltIns .FQ_NAMES .list
98
+
99
+ private fun KotlinType.isListOrSubtype (): Boolean {
100
+ return isList() || constructor .supertypes.reversed().any { it.isList() }
101
+ }
102
+
80
103
private class ReplaceWithStdLibFix (private val methodName : String , private val receiver : String ) : LocalQuickFix {
81
104
override fun getName () = " Replace with $receiver .$methodName "
82
105
0 commit comments