Introduce "Useless call on collection type" inspection
Related to KT-12165 Supported functions: filterNotNull, filterIsInstance, mapNotNull, mapNotNullTo, mapIndexedNotNull, mapIndexedNotNullTo Also, "Useless cal on not-null" improved a bit
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This inspection reports filter-like calls on already filtered collections, e.g. listOf("abc").filterNotNull()
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2258,6 +2258,14 @@
|
|||||||
language="kotlin"
|
language="kotlin"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.collections.UselessCallOnCollectionInspection"
|
||||||
|
displayName="Useless call on collection type"
|
||||||
|
groupName="Kotlin"
|
||||||
|
enabledByDefault="true"
|
||||||
|
level="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"/>
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.ProblemsHolder
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
|
abstract class AbstractUselessCallInspection : AbstractKotlinInspection() {
|
||||||
|
|
||||||
|
protected abstract val uselessFqNames: Map<String, Conversion>
|
||||||
|
|
||||||
|
protected abstract val uselessNames: Set<String>
|
||||||
|
|
||||||
|
protected abstract fun QualifiedExpressionVisitor.suggestConversionIfNeeded(
|
||||||
|
expression: KtQualifiedExpression,
|
||||||
|
calleeExpression: KtExpression,
|
||||||
|
context: BindingContext,
|
||||||
|
conversion: Conversion
|
||||||
|
)
|
||||||
|
|
||||||
|
inner class QualifiedExpressionVisitor internal constructor(val holder: ProblemsHolder, val isOnTheFly: Boolean) : KtVisitorVoid() {
|
||||||
|
override fun visitQualifiedExpression(expression: KtQualifiedExpression) {
|
||||||
|
super.visitQualifiedExpression(expression)
|
||||||
|
val selector = expression.selectorExpression as? KtCallExpression ?: return
|
||||||
|
val calleeExpression = selector.calleeExpression ?: return
|
||||||
|
if (calleeExpression.text !in uselessNames) return
|
||||||
|
|
||||||
|
val context = expression.analyze(BodyResolveMode.PARTIAL)
|
||||||
|
val resolvedCall = expression.getResolvedCall(context) ?: return
|
||||||
|
val conversion = uselessFqNames[resolvedCall.resultingDescriptor.fqNameOrNull()?.asString()] ?: return
|
||||||
|
|
||||||
|
suggestConversionIfNeeded(expression, calleeExpression, context, conversion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = QualifiedExpressionVisitor(holder, isOnTheFly)
|
||||||
|
|
||||||
|
|
||||||
|
protected companion object {
|
||||||
|
data class Conversion(val replacementName: String? = null)
|
||||||
|
|
||||||
|
val deleteConversion = Conversion()
|
||||||
|
|
||||||
|
fun Set<String>.toShortNames() = mapTo(mutableSetOf()) { fqName -> fqName.takeLastWhile { it != '.' } }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,10 +20,9 @@ import com.intellij.codeInspection.LocalQuickFix
|
|||||||
import com.intellij.codeInspection.ProblemDescriptor
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.idea.core.replaced
|
import org.jetbrains.kotlin.idea.core.replaced
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression
|
|
||||||
import org.jetbrains.kotlin.psi.createExpressionByPattern
|
|
||||||
|
|
||||||
class RenameUselessCallFix(val newName: String) : LocalQuickFix {
|
class RenameUselessCallFix(val newName: String) : LocalQuickFix {
|
||||||
override fun getName() = "Rename useless call to '$newName'"
|
override fun getName() = "Rename useless call to '$newName'"
|
||||||
@@ -33,8 +32,9 @@ class RenameUselessCallFix(val newName: String) : LocalQuickFix {
|
|||||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||||
(descriptor.psiElement as? KtQualifiedExpression)?.let {
|
(descriptor.psiElement as? KtQualifiedExpression)?.let {
|
||||||
val factory = KtPsiFactory(it)
|
val factory = KtPsiFactory(it)
|
||||||
val sign = if (it is KtSafeQualifiedExpression) "?." else "."
|
val selectorCallExpression = it.selectorExpression as? KtCallExpression
|
||||||
it.replaced(factory.createExpressionByPattern("$0$sign$newName()", it.receiverExpression))
|
val calleeExpression = selectorCallExpression?.calleeExpression ?: return
|
||||||
|
calleeExpression.replaced(factory.createExpression(newName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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.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.KtQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.isFlexible
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
|
||||||
|
class UselessCallOnCollectionInspection : AbstractUselessCallInspection() {
|
||||||
|
override val uselessFqNames = mapOf("kotlin.collections.filterNotNull" to deleteConversion,
|
||||||
|
"kotlin.collections.filterIsInstance" to deleteConversion,
|
||||||
|
"kotlin.collections.mapNotNull" to Conversion("map"),
|
||||||
|
"kotlin.collections.mapNotNullTo" to Conversion("mapTo"),
|
||||||
|
"kotlin.collections.mapIndexedNotNull" to Conversion("mapIndexed"),
|
||||||
|
"kotlin.collections.mapIndexedNotNullTo" to Conversion("mapIndexedTo"))
|
||||||
|
|
||||||
|
override val uselessNames = uselessFqNames.keys.toShortNames()
|
||||||
|
|
||||||
|
override fun QualifiedExpressionVisitor.suggestConversionIfNeeded(
|
||||||
|
expression: KtQualifiedExpression,
|
||||||
|
calleeExpression: KtExpression,
|
||||||
|
context: BindingContext,
|
||||||
|
conversion: Conversion
|
||||||
|
) {
|
||||||
|
val receiverType = expression.receiverExpression.getType(context) ?: return
|
||||||
|
val receiverTypeArgument = receiverType.arguments.singleOrNull()?.type ?: return
|
||||||
|
val resolvedCall = expression.getResolvedCall(context) ?: return
|
||||||
|
if (calleeExpression.text == "filterIsInstance") {
|
||||||
|
val typeParameterDescriptor = resolvedCall.candidateDescriptor.typeParameters.singleOrNull() ?: return
|
||||||
|
val argumentType = resolvedCall.typeArguments[typeParameterDescriptor] ?: return
|
||||||
|
if (receiverTypeArgument.isFlexible() || !receiverTypeArgument.isSubtypeOf(argumentType)) return
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// xxxNotNull
|
||||||
|
if (TypeUtils.isNullableType(receiverTypeArgument)) return
|
||||||
|
if (calleeExpression.text != "filterNotNull") {
|
||||||
|
// Also check last argument functional type to have not-null result
|
||||||
|
val lastParameter = resolvedCall.resultingDescriptor.valueParameters.lastOrNull() ?: 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val newName = conversion.replacementName
|
||||||
|
if (newName != null) {
|
||||||
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
|
expression,
|
||||||
|
TextRange(expression.operationTokenNode.startOffset - expression.startOffset,
|
||||||
|
calleeExpression.endOffset - expression.startOffset),
|
||||||
|
"Call on collection type may be reduced",
|
||||||
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
|
isOnTheFly,
|
||||||
|
RenameUselessCallFix(newName)
|
||||||
|
)
|
||||||
|
holder.registerProblem(descriptor)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
|
expression,
|
||||||
|
TextRange(expression.operationTokenNode.startOffset - expression.startOffset,
|
||||||
|
calleeExpression.endOffset - expression.startOffset),
|
||||||
|
"Useless call on collection type",
|
||||||
|
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||||
|
isOnTheFly,
|
||||||
|
RemoveUselessCallFix()
|
||||||
|
)
|
||||||
|
holder.registerProblem(descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
-69
@@ -18,88 +18,70 @@ package org.jetbrains.kotlin.idea.inspections.collections
|
|||||||
|
|
||||||
import com.intellij.codeInspection.IntentionWrapper
|
import com.intellij.codeInspection.IntentionWrapper
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElementVisitor
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
|
||||||
import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection
|
|
||||||
import org.jetbrains.kotlin.idea.quickfix.ReplaceWithDotCallFix
|
import org.jetbrains.kotlin.idea.quickfix.ReplaceWithDotCallFix
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
class UselessCallOnNotNullInspection : AbstractKotlinInspection() {
|
class UselessCallOnNotNullInspection : AbstractUselessCallInspection() {
|
||||||
|
override val uselessFqNames = mapOf("kotlin.collections.orEmpty" to deleteConversion,
|
||||||
|
"kotlin.text.orEmpty" to deleteConversion,
|
||||||
|
"kotlin.text.isNullOrEmpty" to Conversion("isEmpty"),
|
||||||
|
"kotlin.text.isNullOrBlank" to Conversion("isBlank"))
|
||||||
|
|
||||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
override val uselessNames = uselessFqNames.keys.toShortNames()
|
||||||
return object : KtVisitorVoid() {
|
|
||||||
override fun visitQualifiedExpression(expression: KtQualifiedExpression) {
|
|
||||||
super.visitQualifiedExpression(expression)
|
|
||||||
val selector = expression.selectorExpression as? KtCallExpression ?: return
|
|
||||||
val calleeExpression = selector.calleeExpression ?: return
|
|
||||||
if (calleeExpression.text !in names) return
|
|
||||||
|
|
||||||
val context = expression.analyze(BodyResolveMode.PARTIAL)
|
override fun QualifiedExpressionVisitor.suggestConversionIfNeeded(
|
||||||
val resolvedCall = expression.getResolvedCall(context) ?: return
|
expression: KtQualifiedExpression,
|
||||||
val conversion = fqNames[resolvedCall.resultingDescriptor.fqNameOrNull()?.asString()] ?: return
|
calleeExpression: KtExpression,
|
||||||
val newName = conversion.replacementName
|
context: BindingContext,
|
||||||
|
conversion: Conversion
|
||||||
|
) {
|
||||||
|
val newName = conversion.replacementName
|
||||||
|
|
||||||
val safeExpression = expression as? KtSafeQualifiedExpression
|
val safeExpression = expression as? KtSafeQualifiedExpression
|
||||||
val notNullType = expression.receiverExpression.getType(context)?.let { TypeUtils.isNullableType(it) } == false
|
val notNullType = expression.receiverExpression.getType(context)?.let { TypeUtils.isNullableType(it) } == false
|
||||||
if (newName != null && (notNullType || safeExpression != null)) {
|
val defaultRange = TextRange(expression.operationTokenNode.startOffset, calleeExpression.endOffset)
|
||||||
val descriptor = holder.manager.createProblemDescriptor(
|
.shiftRight(-expression.startOffset)
|
||||||
expression,
|
if (newName != null && (notNullType || safeExpression != null)) {
|
||||||
TextRange(expression.operationTokenNode.startOffset - expression.startOffset,
|
val fixes = listOf(RenameUselessCallFix(newName)) + listOfNotNull(safeExpression?.let {
|
||||||
calleeExpression.endOffset - expression.startOffset),
|
IntentionWrapper(ReplaceWithDotCallFix(safeExpression), safeExpression.containingKtFile)
|
||||||
"Call on not-null type may be reduced",
|
})
|
||||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
isOnTheFly,
|
expression,
|
||||||
RenameUselessCallFix(newName)
|
defaultRange,
|
||||||
)
|
"Call on not-null type may be reduced",
|
||||||
holder.registerProblem(descriptor)
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
}
|
isOnTheFly,
|
||||||
else if (notNullType) {
|
*fixes.toTypedArray()
|
||||||
val descriptor = holder.manager.createProblemDescriptor(
|
)
|
||||||
expression,
|
holder.registerProblem(descriptor)
|
||||||
TextRange(expression.operationTokenNode.startOffset - expression.startOffset,
|
}
|
||||||
calleeExpression.endOffset - expression.startOffset),
|
else if (notNullType) {
|
||||||
"Useless call on not-null type",
|
val descriptor = holder.manager.createProblemDescriptor(
|
||||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
expression,
|
||||||
isOnTheFly,
|
defaultRange,
|
||||||
RemoveUselessCallFix()
|
"Useless call on not-null type",
|
||||||
)
|
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||||
holder.registerProblem(descriptor)
|
isOnTheFly,
|
||||||
}
|
RemoveUselessCallFix()
|
||||||
else if (safeExpression != null) {
|
)
|
||||||
holder.registerProblem(
|
holder.registerProblem(descriptor)
|
||||||
safeExpression.operationTokenNode.psi,
|
}
|
||||||
"This call is useless with ?.",
|
else if (safeExpression != null) {
|
||||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
holder.registerProblem(
|
||||||
IntentionWrapper(ReplaceWithDotCallFix(safeExpression), safeExpression.containingKtFile)
|
safeExpression.operationTokenNode.psi,
|
||||||
)
|
"This call is useless with ?.",
|
||||||
}
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||||
}
|
IntentionWrapper(ReplaceWithDotCallFix(safeExpression), safeExpression.containingKtFile)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private data class Conversion(val replacementName: String? = null)
|
|
||||||
|
|
||||||
private val deleteConversion = Conversion()
|
|
||||||
|
|
||||||
private val fqNames = mapOf("kotlin.collections.orEmpty" to deleteConversion,
|
|
||||||
"kotlin.text.orEmpty" to deleteConversion,
|
|
||||||
"kotlin.text.isNullOrEmpty" to Conversion("isEmpty"),
|
|
||||||
"kotlin.text.isNullOrBlank" to Conversion("isBlank"))
|
|
||||||
|
|
||||||
private val names = fqNames.keys.mapTo(mutableSetOf()) { fqName -> fqName.takeLastWhile { it != '.' } }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.inspections.collections.UselessCallOnCollectionInspection
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>filterIsInstance<String>()
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1")
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(true, "1").<caret>filterIsInstance<String>()
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf(System.getProperty("")).<caret>filterIsInstance<String>()
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>filterIsInstance<Any>()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1")
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", null).<caret>filterIsInstance<Any>()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>filterNotNull()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1")
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val someList = listOf("alpha", "beta").<caret>mapIndexedNotNullTo(destination = hashSetOf()) { index, value -> index + value.length }
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val someList = listOf("alpha", "beta").mapIndexedTo(destination = hashSetOf()) { index, value -> index + value.length }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>mapNotNullTo(mutableSetOf()) { it.toInt() }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").mapTo(mutableSetOf()) { it.toInt() }
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>mapNotNull { it.toInt() }
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").map { it.toInt() }
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>mapNotNull { if (it.isNotEmpty()) it.toInt() else null }
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>mapNotNull(String::toInt)
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1").map(String::toInt)
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun String.toNullableInt(): Int? = null
|
||||||
|
|
||||||
|
val x = listOf("1").<caret>mapNotNull(String::toNullableInt)
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
val x = listOf("1", null).<caret>filterNotNull()
|
||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
// FIX: Rename useless call to 'isBlank'
|
||||||
|
|
||||||
val s: String? = ""
|
val s: String? = ""
|
||||||
val blank = s<caret>?.isNullOrBlank()
|
val blank = s<caret>?.isNullOrBlank()
|
||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
// FIX: Rename useless call to 'isBlank'
|
||||||
|
|
||||||
val s: String? = ""
|
val s: String? = ""
|
||||||
val blank = s?.isBlank()
|
val blank = s?.isBlank()
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FIX: Replace with dot call
|
||||||
|
|
||||||
|
val s: String? = ""
|
||||||
|
val empty = s<caret>?.isNullOrEmpty()
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// FIX: Replace with dot call
|
||||||
|
|
||||||
|
val s: String? = ""
|
||||||
|
val empty = s.isNullOrEmpty()
|
||||||
@@ -59,6 +59,93 @@ 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/uselessCallOnCollection")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class UselessCallOnCollection extends AbstractLocalInspectionTest {
|
||||||
|
public void testAllFilesPresentInUselessCallOnCollection() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections/uselessCallOnCollection"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterIsExactInstance.kt")
|
||||||
|
public void testFilterIsExactInstance() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsExactInstance.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterIsExactInstanceFake.kt")
|
||||||
|
public void testFilterIsExactInstanceFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsExactInstanceFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterIsForFlexible.kt")
|
||||||
|
public void testFilterIsForFlexible() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsForFlexible.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterIsSupertypeInstance.kt")
|
||||||
|
public void testFilterIsSupertypeInstance() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsSupertypeInstance.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterIsSupertypeInstanceFake.kt")
|
||||||
|
public void testFilterIsSupertypeInstanceFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterIsSupertypeInstanceFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("FilterNotNull.kt")
|
||||||
|
public void testFilterNotNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/FilterNotNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("filterNotNullFake.kt")
|
||||||
|
public void testFilterNotNullFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/filterNotNullFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapIndexedNotNullTo.kt")
|
||||||
|
public void testMapIndexedNotNullTo() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapIndexedNotNullTo.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullTo.kt")
|
||||||
|
public void testMapNotNullTo() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullTo.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullWithLambda.kt")
|
||||||
|
public void testMapNotNullWithLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambda.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullWithLambdaFake.kt")
|
||||||
|
public void testMapNotNullWithLambdaFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithLambdaFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullWithReference.kt")
|
||||||
|
public void testMapNotNullWithReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MapNotNullWithReferenceFake.kt")
|
||||||
|
public void testMapNotNullWithReferenceFake() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnCollection/MapNotNullWithReferenceFake.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull")
|
@TestMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -97,6 +184,12 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NullOrEmptySafe.kt")
|
||||||
|
public void testNullOrEmptySafe() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmptySafe.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OrEmptyFake.kt")
|
@TestMetadata("OrEmptyFake.kt")
|
||||||
public void testOrEmptyFake() throws Exception {
|
public void testOrEmptyFake() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user