Introduce "simplifiable call chain on collection" inspection
Related to KT-12165 So #KT-18274 Fixed So #KT-17198 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
bdb9f00c75
commit
36be1fdaef
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This inspection reports two-call chains replaceable by single call, e.g. map {}.filterNotNull() to mapNotNull {}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2266,6 +2266,14 @@
|
|||||||
language="kotlin"
|
language="kotlin"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.collections.SimplifiableCallChainInspection"
|
||||||
|
displayName="Call chain on collection type can be simplified"
|
||||||
|
groupName="Kotlin"
|
||||||
|
enabledByDefault="true"
|
||||||
|
level="WEAK WARNING"
|
||||||
|
language="kotlin"
|
||||||
|
/>
|
||||||
|
|
||||||
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
|
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
|
||||||
|
|
||||||
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.inspections.collections
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
fun KotlinType.isFunctionOfAnyKind() = constructor.declarationDescriptor?.getFunctionalClassKind() != null
|
||||||
|
|
||||||
|
fun ResolvedCall<*>.hasLastFunctionalParameterWithResult(context: BindingContext, predicate: (KotlinType) -> Boolean): Boolean {
|
||||||
|
val lastParameter = resultingDescriptor.valueParameters.lastOrNull() ?: return false
|
||||||
|
val lastArgument = valueArguments[lastParameter]?.arguments?.singleOrNull() ?: return false
|
||||||
|
val functionalType = lastArgument.getArgumentExpression()?.getType(context) ?: return false
|
||||||
|
// Both Function & KFunction must pass here
|
||||||
|
if (!functionalType.isFunctionOfAnyKind()) return false
|
||||||
|
val resultType = functionalType.arguments.lastOrNull()?.type ?: return false
|
||||||
|
return predicate(resultType)
|
||||||
|
}
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.inspections.collections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
|
import com.intellij.codeInspection.ProblemsHolder
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
|
|
||||||
|
class SimplifiableCallChainInspection : AbstractKotlinInspection() {
|
||||||
|
|
||||||
|
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) =
|
||||||
|
object : KtVisitorVoid() {
|
||||||
|
override fun visitQualifiedExpression(expression: KtQualifiedExpression) {
|
||||||
|
super.visitQualifiedExpression(expression)
|
||||||
|
|
||||||
|
val firstQualifiedExpression = expression.receiverExpression as? KtQualifiedExpression ?: return
|
||||||
|
val firstCallExpression = firstQualifiedExpression.selectorExpression as? KtCallExpression ?: return
|
||||||
|
val secondCallExpression = expression.selectorExpression as? KtCallExpression ?: return
|
||||||
|
|
||||||
|
val actualConversions = conversionGroups[
|
||||||
|
firstCallExpression.calleeExpression?.text to secondCallExpression.calleeExpression?.text
|
||||||
|
] ?: return
|
||||||
|
|
||||||
|
val context = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
val firstResolvedCall = firstQualifiedExpression.getResolvedCall(context) ?: return
|
||||||
|
val conversion = actualConversions.firstOrNull {
|
||||||
|
firstResolvedCall.resultingDescriptor.fqNameOrNull()?.asString() == it.firstFqName
|
||||||
|
} ?: return
|
||||||
|
|
||||||
|
val secondResolvedCall = expression.getResolvedCall(context) ?: return
|
||||||
|
val secondResultingDescriptor = secondResolvedCall.resultingDescriptor
|
||||||
|
if (secondResultingDescriptor.fqNameOrNull()?.asString() != conversion.secondFqName) return
|
||||||
|
if (secondResolvedCall.valueArguments.any { (parameter, resolvedArgument) ->
|
||||||
|
parameter.type.isFunctionOfAnyKind() &&
|
||||||
|
resolvedArgument !is DefaultValueArgument
|
||||||
|
}) return
|
||||||
|
|
||||||
|
if (conversion.replacement.startsWith("joinTo")) {
|
||||||
|
// Function parameter in map must have String result type
|
||||||
|
if (!firstResolvedCall.hasLastFunctionalParameterWithResult(context) { KotlinBuiltIns.isString(it) }) return
|
||||||
|
}
|
||||||
|
|
||||||
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
|
expression,
|
||||||
|
TextRange(firstCallExpression.startOffset, firstCallExpression.endOffset).shiftRight(-expression.startOffset),
|
||||||
|
"Call chain on collection type may be simplified",
|
||||||
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
|
isOnTheFly,
|
||||||
|
SimplifyCallChainFix(conversion.replacement)
|
||||||
|
)
|
||||||
|
holder.registerProblem(descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val conversions = listOf(
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.first", "first"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.firstOrNull", "firstOrNull"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.last", "last"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.lastOrNull", "lastOrNull"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.single", "single"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.singleOrNull", "singleOrNull"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.isNotEmpty", "any"),
|
||||||
|
Conversion("kotlin.collections.filter", "kotlin.collections.List.isEmpty", "none"),
|
||||||
|
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.first", "first"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.firstOrNull", "firstOrNull"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.last", "last"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.lastOrNull", "lastOrNull"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.single", "single"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.singleOrNull", "singleOrNull"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.isNotEmpty", "any"),
|
||||||
|
Conversion("kotlin.text.filter", "kotlin.text.isEmpty", "none"),
|
||||||
|
|
||||||
|
Conversion("kotlin.collections.map", "kotlin.collections.joinTo", "joinTo"),
|
||||||
|
Conversion("kotlin.collections.map", "kotlin.collections.joinToString", "joinToString"),
|
||||||
|
Conversion("kotlin.collections.map", "kotlin.collections.filterNotNull", "mapNotNull")
|
||||||
|
)
|
||||||
|
|
||||||
|
private val conversionGroups = conversions.groupBy { it.firstName to it.secondName }
|
||||||
|
|
||||||
|
data class Conversion(val firstFqName: String, val secondFqName: String, val replacement: String) {
|
||||||
|
private fun String.convertToShort() = takeLastWhile { it != '.' }
|
||||||
|
|
||||||
|
val firstName = firstFqName.convertToShort()
|
||||||
|
|
||||||
|
val secondName = secondFqName.convertToShort()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.inspections.collections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.LocalQuickFix
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||||
|
|
||||||
|
class SimplifyCallChainFix(val newName: String) : LocalQuickFix {
|
||||||
|
override fun getName() = "Merge call chain to '$newName'"
|
||||||
|
|
||||||
|
override fun getFamilyName() = name
|
||||||
|
|
||||||
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
|
(descriptor.psiElement as? KtQualifiedExpression)?.let { secondQualifiedExpression ->
|
||||||
|
val factory = KtPsiFactory(secondQualifiedExpression)
|
||||||
|
val firstQualifiedExpression = secondQualifiedExpression.receiverExpression as? KtQualifiedExpression ?: return
|
||||||
|
val operationSign = if (firstQualifiedExpression is KtSafeQualifiedExpression) "?." else "."
|
||||||
|
val firstCallExpression = firstQualifiedExpression.selectorExpression as? KtCallExpression ?: return
|
||||||
|
val secondCallExpression = secondQualifiedExpression.selectorExpression as? KtCallExpression ?: return
|
||||||
|
|
||||||
|
val lastArgumentPrefix = if (newName.startsWith("joinTo")) "transform = " else ""
|
||||||
|
val arguments = secondCallExpression.valueArgumentList?.arguments.orEmpty().map { it.text } +
|
||||||
|
firstCallExpression.valueArgumentList?.arguments.orEmpty().map { "$lastArgumentPrefix${it.text}"}
|
||||||
|
val lambdaArgument = firstCallExpression.lambdaArguments.singleOrNull()
|
||||||
|
|
||||||
|
val argumentsText = arguments.ifNotEmpty { joinToString(prefix = "(", postfix = ")") } ?: ""
|
||||||
|
val newQualifiedExpression = if (lambdaArgument != null) factory.createExpressionByPattern(
|
||||||
|
"$0$1$2 $3 $4",
|
||||||
|
firstQualifiedExpression.receiverExpression,
|
||||||
|
operationSign,
|
||||||
|
newName,
|
||||||
|
argumentsText,
|
||||||
|
lambdaArgument.getLambdaExpression().text
|
||||||
|
)
|
||||||
|
else factory.createExpressionByPattern(
|
||||||
|
"$0$1$2 $3",
|
||||||
|
firstQualifiedExpression.receiverExpression,
|
||||||
|
operationSign,
|
||||||
|
newName,
|
||||||
|
argumentsText
|
||||||
|
)
|
||||||
|
|
||||||
|
secondQualifiedExpression.replaced(newQualifiedExpression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-10
@@ -18,9 +18,6 @@ package org.jetbrains.kotlin.idea.inspections.collections
|
|||||||
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
@@ -61,13 +58,7 @@ class UselessCallOnCollectionInspection : AbstractUselessCallInspection() {
|
|||||||
if (TypeUtils.isNullableType(receiverTypeArgument)) return
|
if (TypeUtils.isNullableType(receiverTypeArgument)) return
|
||||||
if (calleeExpression.text != "filterNotNull") {
|
if (calleeExpression.text != "filterNotNull") {
|
||||||
// Also check last argument functional type to have not-null result
|
// Also check last argument functional type to have not-null result
|
||||||
val lastParameter = resolvedCall.resultingDescriptor.valueParameters.lastOrNull() ?: return
|
if (!resolvedCall.hasLastFunctionalParameterWithResult(context) { !TypeUtils.isNullableType(it) }) return
|
||||||
val lastArgument = resolvedCall.valueArguments[lastParameter]?.arguments?.singleOrNull() ?: return
|
|
||||||
val functionalType = lastArgument.getArgumentExpression()?.getType(context) ?: return
|
|
||||||
// Both Function & KFunction must pass here
|
|
||||||
if (functionalType.constructor.declarationDescriptor?.getFunctionalClassKind() == null) return
|
|
||||||
val resultType = functionalType.arguments.lastOrNull()?.type ?: return
|
|
||||||
if (TypeUtils.isNullableType(resultType)) return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.inspections.collections.SimplifiableCallChainInspection
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val nullableList: List<String>? = listOf("1", "")
|
||||||
|
val x = nullableList?.<caret>filter { it.isNotEmpty() }?.first()
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val nullableList: List<String>? = listOf("1", "")
|
||||||
|
val x = nullableList?.first { it.isNotEmpty() }
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", "").<caret>filter { it.isNotEmpty() }.first { it[0] == 'A' }
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf('1', 'a', 0.toChar()).<caret>filter { it.toInt() != 0 }.first(Char::isLetter)
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", "").<caret>filter(String::isNotEmpty).firstOrNull()
|
||||||
idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterFirstOrNullReference.kt.after
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", "").firstOrNull(String::isNotEmpty)
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).filter <caret>{ it % 2 != 0 }.isEmpty()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).none { it % 2 != 0 }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).filter <caret>{ it % 2 != 0 }.isNotEmpty()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).any { it % 2 != 0 }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", "").filter <caret>{ element -> element.isNotEmpty() }.last()
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", "").last { element -> element.isNotEmpty() }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = "abcdef".fil<caret>ter { it.isDigit() }.isEmpty()
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = "abcdef".none { it.isDigit() }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = "5abc".filter { it.isDigit() }.<caret>singleOrNull()
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = "5abc".singleOrNull { it.isDigit() }
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val x = listOf(1, 2, 3).map { "$it*$it" }.<caret>joinTo(buffer = sb, prefix = "= ", separator = " + ")
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val x = listOf(1, 2, 3).joinTo(buffer = sb, prefix = "= ", separator = " + ") { "$it*$it" }
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val x = listOf(1, 2, 3).map { "$it*$it" }.<caret>joinTo(buffer = sb, prefix = "= ", separator = " + ", transform = String::capitalize)
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val x = listOf(1, 2, 3).map { "$it*$it" }.<caret>joinTo(buffer = sb, prefix = "= ", separator = " + ") { "${it.substring(1)}"}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).map { "$it*$it" }.<caret>joinToString(prefix = "= ", separator = " + ")
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).joinToString(prefix = "= ", separator = " + ") { "$it*$it" }
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).map(Int::toString).<caret>joinToString(prefix = "= ", separator = " + ")
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).joinToString(prefix = "= ", separator = " + ", transform = Int::toString)
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 2, 3).map(Int::toDouble).<caret>joinToString(prefix = "= ", separator = " + ")
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 0, 2).map { if (it != 0) it else null }.<caret>filterNotNull()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(1, 0, 2).mapNotNull { if (it != 0) it else null }
|
||||||
@@ -59,6 +59,111 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class SimplifiableCallChain extends AbstractLocalInspectionTest {
|
||||||
|
public void testAllFilesPresentInSimplifiableCallChain() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections/simplifiableCallChain"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterFirst.kt")
|
||||||
|
public void testFilterFirst() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterFirst.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterFirstFake.kt")
|
||||||
|
public void testFilterFirstFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterFirstFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterFirstFakeReference.kt")
|
||||||
|
public void testFilterFirstFakeReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterFirstFakeReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterFirstOrNullReference.kt")
|
||||||
|
public void testFilterFirstOrNullReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterFirstOrNullReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterIsEmpty.kt")
|
||||||
|
public void testFilterIsEmpty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterIsEmpty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterIsNotEmpty.kt")
|
||||||
|
public void testFilterIsNotEmpty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterIsNotEmpty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterLastExplicit.kt")
|
||||||
|
public void testFilterLastExplicit() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterLastExplicit.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterTextIsEmpty.kt")
|
||||||
|
public void testFilterTextIsEmpty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterTextIsEmpty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterTextSingleOrNull.kt")
|
||||||
|
public void testFilterTextSingleOrNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/filterTextSingleOrNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinTo.kt")
|
||||||
|
public void testJoinTo() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinTo.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToFake.kt")
|
||||||
|
public void testJoinToFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToFakeWithLambda.kt")
|
||||||
|
public void testJoinToFakeWithLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToFakeWithLambda.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToString.kt")
|
||||||
|
public void testJoinToString() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToString.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToStringWithReference.kt")
|
||||||
|
public void testJoinToStringWithReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("joinToStringWithReferenceFake.kt")
|
||||||
|
public void testJoinToStringWithReferenceFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/joinToStringWithReferenceFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("mapNotNull.kt")
|
||||||
|
public void testMapNotNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/simplifiableCallChain/mapNotNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection")
|
@TestMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user