From 0f4ae3b727c6d13dd6fcea8da1df1512983c5651 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 16 Jun 2017 17:14:59 +0300 Subject: [PATCH] Introduce "Useless call on not-null type" inspection #KT-18386 Fixed Supported functions: orEmpty(), isNullOrEmpty(), isNullOrBlank() --- .../UselessCallOnNotNull.html | 8 ++ idea/src/META-INF/plugin.xml | 8 ++ .../collections/RemoveUselessCallFix.kt | 36 ++++++ .../collections/RenameUselessCallFix.kt | 40 +++++++ .../UselessCallOnNotNullInspection.kt | 105 ++++++++++++++++++ .../uselessCallOnNotNull/.inspection | 1 + .../uselessCallOnNotNull/NotNullType.kt | 4 + .../uselessCallOnNotNull/NotNullType.kt.after | 4 + .../uselessCallOnNotNull/NotNullTypeChain.kt | 4 + .../NotNullTypeChain.kt.after | 4 + .../uselessCallOnNotNull/NullOrBlankSafe.kt | 4 + .../NullOrBlankSafe.kt.after | 4 + .../uselessCallOnNotNull/NullOrEmpty.kt | 4 + .../uselessCallOnNotNull/NullOrEmpty.kt.after | 4 + .../uselessCallOnNotNull/NullOrEmptyFake.kt | 5 + .../uselessCallOnNotNull/OrEmptyFake.kt | 5 + .../uselessCallOnNotNull/SafeCall.kt | 4 + .../uselessCallOnNotNull/SafeCall.kt.after | 4 + .../uselessCallOnNotNull/String.kt | 4 + .../uselessCallOnNotNull/String.kt.after | 4 + .../LocalInspectionTestGenerated.java | 66 +++++++++++ 21 files changed, 322 insertions(+) create mode 100644 idea/resources/inspectionDescriptions/UselessCallOnNotNull.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/collections/RemoveUselessCallFix.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/collections/RenameUselessCallFix.kt create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/collections/UselessCallOnNotNullInspection.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/.inspection create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt.after create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt.after create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt.after create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt.after create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmptyFake.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt.after create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt create mode 100644 idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt.after diff --git a/idea/resources/inspectionDescriptions/UselessCallOnNotNull.html b/idea/resources/inspectionDescriptions/UselessCallOnNotNull.html new file mode 100644 index 00000000000..7ec18355771 --- /dev/null +++ b/idea/resources/inspectionDescriptions/UselessCallOnNotNull.html @@ -0,0 +1,8 @@ + + +This inspection reports calls on not-null receiver that make sense only for nullable receiver, e.g. +

+listOf(1).orEmpty()
+
+ + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 0e0e36ff850..e35e97fea4d 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -2242,6 +2242,14 @@ language="kotlin" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/RemoveUselessCallFix.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/RemoveUselessCallFix.kt new file mode 100644 index 00000000000..c4d0882425b --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/RemoveUselessCallFix.kt @@ -0,0 +1,36 @@ +/* + * 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.KtQualifiedExpression + +class RemoveUselessCallFix : LocalQuickFix { + + override fun getName() = "Remove useless call" + + override fun getFamilyName() = name + + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + (descriptor.psiElement as? KtQualifiedExpression)?.let { + it.replaced(it.receiverExpression) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/RenameUselessCallFix.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/RenameUselessCallFix.kt new file mode 100644 index 00000000000..0c5e1108051 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/RenameUselessCallFix.kt @@ -0,0 +1,40 @@ +/* + * 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.KtPsiFactory +import org.jetbrains.kotlin.psi.KtQualifiedExpression +import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression +import org.jetbrains.kotlin.psi.createExpressionByPattern + +class RenameUselessCallFix(val newName: String) : LocalQuickFix { + override fun getName() = "Rename useless call to '$newName'" + + override fun getFamilyName() = name + + override fun applyFix(project: Project, descriptor: ProblemDescriptor) { + (descriptor.psiElement as? KtQualifiedExpression)?.let { + val factory = KtPsiFactory(it) + val sign = if (it is KtSafeQualifiedExpression) "?." else "." + it.replaced(factory.createExpressionByPattern("$0$sign$newName()", it.receiverExpression)) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/UselessCallOnNotNullInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/UselessCallOnNotNullInspection.kt new file mode 100644 index 00000000000..d2904887b02 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/UselessCallOnNotNullInspection.kt @@ -0,0 +1,105 @@ +/* + * 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.IntentionWrapper +import com.intellij.codeInspection.ProblemHighlightType +import com.intellij.codeInspection.ProblemsHolder +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.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtQualifiedExpression +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.startOffset +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +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 + +class UselessCallOnNotNullInspection : AbstractKotlinInspection() { + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { + 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) + val resolvedCall = expression.getResolvedCall(context) ?: return + val conversion = fqNames[resolvedCall.resultingDescriptor.fqNameOrNull()?.asString()] ?: return + val newName = conversion.replacementName + + val safeExpression = expression as? KtSafeQualifiedExpression + val notNullType = expression.receiverExpression.getType(context)?.let { TypeUtils.isNullableType(it) } == false + if (newName != null && (notNullType || safeExpression != null)) { + val descriptor = holder.manager.createProblemDescriptor( + expression, + TextRange(expression.operationTokenNode.startOffset - expression.startOffset, + calleeExpression.endOffset - expression.startOffset), + "Call on not-null type may be reduced", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + isOnTheFly, + RenameUselessCallFix(newName) + ) + holder.registerProblem(descriptor) + } + else if (notNullType) { + val descriptor = holder.manager.createProblemDescriptor( + expression, + TextRange(expression.operationTokenNode.startOffset - expression.startOffset, + calleeExpression.endOffset - expression.startOffset), + "Useless call on not-null type", + ProblemHighlightType.LIKE_UNUSED_SYMBOL, + isOnTheFly, + RemoveUselessCallFix() + ) + holder.registerProblem(descriptor) + } + else if (safeExpression != null) { + holder.registerProblem( + 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 != '.' } } + } +} + diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/.inspection b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/.inspection new file mode 100644 index 00000000000..5cfb7ab7f42 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.collections.UselessCallOnNotNullInspection \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt new file mode 100644 index 00000000000..81605b6c580 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val list1: List = listOf(1) +val list = list1.orEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt.after b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt.after new file mode 100644 index 00000000000..1ead3bb5f09 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val list1: List = listOf(1) +val list = list1 \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt new file mode 100644 index 00000000000..8bb618154d0 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val list1: List = listOf(1) +val list = list1.orEmpty().map { "$it" } \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt.after b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt.after new file mode 100644 index 00000000000..2abb3dd65cf --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val list1: List = listOf(1) +val list = list1.map { "$it" } \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt new file mode 100644 index 00000000000..43fee35ad1e --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val s: String? = "" +val blank = s?.isNullOrBlank() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt.after b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt.after new file mode 100644 index 00000000000..1e519a5c5b3 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val s: String? = "" +val blank = s?.isBlank() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt new file mode 100644 index 00000000000..dcb8d7d1100 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val s = "" +val empty = s.isNullOrEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt.after b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt.after new file mode 100644 index 00000000000..3c3a7834fe9 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val s = "" +val empty = s.isEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmptyFake.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmptyFake.kt new file mode 100644 index 00000000000..451e3d9a002 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmptyFake.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// WITH_RUNTIME + +val s: String? = null +val empty = s.isNullOrEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt new file mode 100644 index 00000000000..a5156836900 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// WITH_RUNTIME + +val list: List? = null +val empty = list.orEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt new file mode 100644 index 00000000000..f5ee86203ff --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val list1: List? = listOf(1) +val list = list1?.orEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt.after b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt.after new file mode 100644 index 00000000000..8e74260c620 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val list1: List? = listOf(1) +val list = list1.orEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt new file mode 100644 index 00000000000..23604ee541f --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val s = "" +val s1 = s.orEmpty() \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt.after b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt.after new file mode 100644 index 00000000000..a8b0c855792 --- /dev/null +++ b/idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt.after @@ -0,0 +1,4 @@ +// WITH_RUNTIME + +val s = "" +val s1 = s \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 7a95a03aae9..f21015a6bbf 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -51,6 +51,72 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { } } + @TestMetadata("idea/testData/inspectionsLocal/collections") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Collections extends AbstractLocalInspectionTest { + public void testAllFilesPresentInCollections() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class UselessCallOnNotNull extends AbstractLocalInspectionTest { + public void testAllFilesPresentInUselessCallOnNotNull() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("NotNullType.kt") + public void testNotNullType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullType.kt"); + doTest(fileName); + } + + @TestMetadata("NotNullTypeChain.kt") + public void testNotNullTypeChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NotNullTypeChain.kt"); + doTest(fileName); + } + + @TestMetadata("NullOrBlankSafe.kt") + public void testNullOrBlankSafe() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrBlankSafe.kt"); + doTest(fileName); + } + + @TestMetadata("NullOrEmpty.kt") + public void testNullOrEmpty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmpty.kt"); + doTest(fileName); + } + + @TestMetadata("NullOrEmptyFake.kt") + public void testNullOrEmptyFake() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/NullOrEmptyFake.kt"); + doTest(fileName); + } + + @TestMetadata("OrEmptyFake.kt") + public void testOrEmptyFake() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/OrEmptyFake.kt"); + doTest(fileName); + } + + @TestMetadata("SafeCall.kt") + public void testSafeCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/SafeCall.kt"); + doTest(fileName); + } + + @TestMetadata("String.kt") + public void testString() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspectionsLocal/collections/uselessCallOnNotNull/String.kt"); + doTest(fileName); + } + } + } + @TestMetadata("idea/testData/inspectionsLocal/copyWithoutNamedArguments") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)