diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index 162eec2a368..dc28290787f 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -3428,6 +3428,15 @@ language="kotlin" /> + + diff --git a/idea/resources/inspectionDescriptions/ReplaceGuardClauseWithFunctionCall.html b/idea/resources/inspectionDescriptions/ReplaceGuardClauseWithFunctionCall.html new file mode 100644 index 00000000000..e91b098c42a --- /dev/null +++ b/idea/resources/inspectionDescriptions/ReplaceGuardClauseWithFunctionCall.html @@ -0,0 +1,11 @@ + + +This inspection reports guard clause that can be replaced with kotlin's function call. For example: +

+
+fun test(foo: Int?) {
+    if (foo == null) throw IllegalArgumentException("foo") // Replace guard clause with kotlin's function call
+}
+
+ + \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceGuardClauseWithFunctionCallInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceGuardClauseWithFunctionCallInspection.kt new file mode 100644 index 00000000000..2f3e2bd25d3 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceGuardClauseWithFunctionCallInspection.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.inspections + +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall +import org.jetbrains.kotlin.idea.core.ShortenReferences +import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.idea.intentions.callExpression +import org.jetbrains.kotlin.idea.util.CommentSaver +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe + +class ReplaceGuardClauseWithFunctionCallInspection : AbstractApplicabilityBasedInspection( + KtIfExpression::class.java +) { + companion object { + private const val ILLEGAL_STATE_EXCEPTION = "IllegalStateException" + private const val ILLEGAL_ARGUMENT_EXCEPTION = "IllegalArgumentException" + } + + private enum class KotlinFunction(val functionName: String) { + CHECK("check"), CHECK_NOT_NULL("checkNotNull"), REQUIRE("require"), REQUIRE_NOT_NULL("requireNotNull"); + + val fqName: String + get() = "kotlin.$functionName" + } + + override fun inspectionText(element: KtIfExpression) = "Replace guard clause with kotlin's function call" + + override val defaultFixText = "Replace with kotlin's function call" + + override fun fixText(element: KtIfExpression) = + element.getKotlinFunction()?.let { "Replace with '${it.functionName}()' call" } ?: defaultFixText + + override fun isApplicable(element: KtIfExpression): Boolean { + if (element.condition == null) return false + val call = element.getCallExpression() ?: return false + val calleeText = call.calleeExpression?.text ?: return false + val valueArguments = call.valueArguments + if (valueArguments.size > 1) return false + if (calleeText != ILLEGAL_STATE_EXCEPTION && calleeText != ILLEGAL_ARGUMENT_EXCEPTION) return false + val fqName = call.resolveToCall()?.resultingDescriptor?.fqNameSafe?.parent() + return fqName == FqName("kotlin.$calleeText") || fqName == FqName("java.lang.$calleeText") + } + + override fun applyTo(element: KtIfExpression, project: Project, editor: Editor?) { + val condition = element.condition ?: return + val call = element.getCallExpression() ?: return + val argument = call.valueArguments.firstOrNull()?.getArgumentExpression() + val commentSaver = CommentSaver(element) + val psiFactory = KtPsiFactory(element) + val replaced = when (val kotlinFunction = element.getKotlinFunction(call)) { + KotlinFunction.CHECK, KotlinFunction.REQUIRE -> { + val (excl, newCondition) = if (condition is KtPrefixExpression && condition.operationToken == KtTokens.EXCL) { + "" to (condition.baseExpression ?: return) + } else { + "!" to condition + } + val newExpression = if (argument == null) { + psiFactory.createExpressionByPattern("${kotlinFunction.fqName}($excl$0)", newCondition) + } else { + psiFactory.createExpressionByPattern("${kotlinFunction.fqName}($excl$0) { $1 }", newCondition, argument) + } + val replaced = element.replaced(newExpression) + val newCall = (replaced as? KtDotQualifiedExpression)?.callExpression + val negatedExpression = newCall?.valueArguments?.firstOrNull()?.getArgumentExpression() as? KtPrefixExpression + if (negatedExpression != null) { + SimplifyNegatedBinaryExpressionInspection.simplifyNegatedBinaryExpressionIfNeeded(negatedExpression) + } + replaced + } + KotlinFunction.CHECK_NOT_NULL, KotlinFunction.REQUIRE_NOT_NULL -> { + val nullCheckedExpression = condition.notNullCheckExpression() ?: return + val newExpression = if (argument == null) { + psiFactory.createExpressionByPattern("${kotlinFunction.fqName}($0)", nullCheckedExpression) + } else { + psiFactory.createExpressionByPattern("${kotlinFunction.fqName}($0) { $1 }", nullCheckedExpression, argument) + } + element.replaced(newExpression) + } + else -> return + } + commentSaver.restore(replaced) + ShortenReferences.DEFAULT.process(replaced) + } + + private fun KtIfExpression.getCallExpression(): KtCallExpression? { + val throwExpression = this.then?.let { + it as? KtThrowExpression ?: (it as? KtBlockExpression)?.statements?.singleOrNull() as? KtThrowExpression + } ?: return null + return throwExpression.thrownExpression?.let { + it as? KtCallExpression ?: (it as? KtQualifiedExpression)?.callExpression + } + } + + private fun KtIfExpression.getKotlinFunction(call: KtCallExpression? = getCallExpression()): KotlinFunction? { + val calleeText = call?.calleeExpression?.text ?: return null + val isNotNullCheck = condition.notNullCheckExpression() != null + return when (calleeText) { + ILLEGAL_STATE_EXCEPTION -> if (isNotNullCheck) KotlinFunction.CHECK_NOT_NULL else KotlinFunction.CHECK + ILLEGAL_ARGUMENT_EXCEPTION -> if (isNotNullCheck) KotlinFunction.REQUIRE_NOT_NULL else KotlinFunction.REQUIRE + else -> null + } + } + + private fun KtExpression?.notNullCheckExpression(): KtExpression? { + if (this == null) return null + if (this !is KtBinaryExpression) return null + if (this.operationToken != KtTokens.EQEQ) return null + val left = this.left ?: return null + val right = this.right ?: return null + return when { + right.isNullConstant() -> left + left.isNullConstant() -> right + else -> null + } + } + + private fun KtExpression.isNullConstant(): Boolean { + return (this as? KtConstantExpression)?.text == KtTokens.NULL_KEYWORD.value + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNegatedBinaryExpressionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNegatedBinaryExpressionInspection.kt index aae1b535e80..9272046df9c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNegatedBinaryExpressionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/SimplifyNegatedBinaryExpressionInspection.kt @@ -26,25 +26,6 @@ import org.jetbrains.kotlin.psi.* class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInspection(KtPrefixExpression::class.java) { - private fun IElementType.negate(): KtSingleValueToken? = when (this) { - KtTokens.IN_KEYWORD -> KtTokens.NOT_IN - KtTokens.NOT_IN -> KtTokens.IN_KEYWORD - - KtTokens.IS_KEYWORD -> KtTokens.NOT_IS - KtTokens.NOT_IS -> KtTokens.IS_KEYWORD - - KtTokens.EQEQ -> KtTokens.EXCLEQ - KtTokens.EXCLEQ -> KtTokens.EQEQ - - KtTokens.LT -> KtTokens.GTEQ - KtTokens.GTEQ -> KtTokens.LT - - KtTokens.GT -> KtTokens.LTEQ - KtTokens.LTEQ -> KtTokens.GT - - else -> null - } - override fun inspectionHighlightRangeInElement(element: KtPrefixExpression) = element.operationReference.textRangeIn(element) override fun inspectionText(element: KtPrefixExpression) = "Negated operation should be simplified" @@ -59,31 +40,65 @@ class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInsp } override fun isApplicable(element: KtPrefixExpression): Boolean { - if (element.operationToken != KtTokens.EXCL) return false - - val expression = KtPsiUtil.deparenthesize(element.baseExpression) as? KtOperationExpression ?: return false - when (expression) { - is KtIsExpression -> if (expression.typeReference == null) return false - is KtBinaryExpression -> if (expression.left == null || expression.right == null) return false - else -> return false - } - - return (expression.operationReference.getReferencedNameElementType() as? KtSingleValueToken)?.negate() != null + return element.canBeSimplified() } override fun applyTo(element: KtPrefixExpression, project: Project, editor: Editor?) { - val expression = KtPsiUtil.deparenthesize(element.baseExpression) ?: return - val operation = (expression as KtOperationExpression).operationReference.getReferencedNameElementType().negate()?.value ?: return + element.simplify() + } - val psiFactory = KtPsiFactory(expression) - val newExpression = when (expression) { - is KtIsExpression -> - psiFactory.createExpressionByPattern("$0 $1 $2", expression.leftHandSide, operation, expression.typeReference!!) - is KtBinaryExpression -> - psiFactory.createExpressionByPattern("$0 $1 $2", expression.left!!, operation, expression.right!!) - else -> - throw IllegalArgumentException() + companion object { + fun simplifyNegatedBinaryExpressionIfNeeded(expression: KtPrefixExpression) { + if (expression.canBeSimplified()) expression.simplify() + } + + private fun KtPrefixExpression.canBeSimplified(): Boolean { + if (operationToken != KtTokens.EXCL) return false + + val expression = KtPsiUtil.deparenthesize(baseExpression) as? KtOperationExpression ?: return false + when (expression) { + is KtIsExpression -> if (expression.typeReference == null) return false + is KtBinaryExpression -> if (expression.left == null || expression.right == null) return false + else -> return false + } + + return (expression.operationReference.getReferencedNameElementType() as? KtSingleValueToken)?.negate() != null + } + + private fun KtPrefixExpression.simplify() { + val expression = KtPsiUtil.deparenthesize(baseExpression) ?: return + val operation = + (expression as KtOperationExpression).operationReference.getReferencedNameElementType().negate()?.value ?: return + + val psiFactory = KtPsiFactory(expression) + val newExpression = when (expression) { + is KtIsExpression -> + psiFactory.createExpressionByPattern("$0 $1 $2", expression.leftHandSide, operation, expression.typeReference!!) + is KtBinaryExpression -> + psiFactory.createExpressionByPattern("$0 $1 $2", expression.left ?: return, operation, expression.right ?: return) + else -> + throw IllegalArgumentException() + } + replace(newExpression) + } + + private fun IElementType.negate(): KtSingleValueToken? = when (this) { + KtTokens.IN_KEYWORD -> KtTokens.NOT_IN + KtTokens.NOT_IN -> KtTokens.IN_KEYWORD + + KtTokens.IS_KEYWORD -> KtTokens.NOT_IS + KtTokens.NOT_IS -> KtTokens.IS_KEYWORD + + KtTokens.EQEQ -> KtTokens.EXCLEQ + KtTokens.EXCLEQ -> KtTokens.EQEQ + + KtTokens.LT -> KtTokens.GTEQ + KtTokens.GTEQ -> KtTokens.LT + + KtTokens.GT -> KtTokens.LTEQ + KtTokens.LTEQ -> KtTokens.GT + + else -> null } - element.replace(newExpression) } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2KPostProcessingRegistrarImpl.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2KPostProcessingRegistrarImpl.kt index bc6b1fb877c..52f80ec272a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2KPostProcessingRegistrarImpl.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2KPostProcessingRegistrarImpl.kt @@ -107,6 +107,7 @@ object J2KPostProcessingRegistrarImpl : J2KPostProcessingRegistrar { registerInspectionBasedProcessing(SimplifyAssertNotNullInspection()) registerIntentionBasedProcessing(RemoveRedundantCallsOfConversionMethodsIntention()) registerInspectionBasedProcessing(JavaMapForEachInspection()) + registerInspectionBasedProcessing(ReplaceGuardClauseWithFunctionCallInspection()) registerDiagnosticBasedProcessing(Errors.USELESS_CAST) { element, _ -> diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/.inspection b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/.inspection new file mode 100644 index 00000000000..41d3fe36240 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.ReplaceGuardClauseWithFunctionCallInspection diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt new file mode 100644 index 00000000000..eec7c70354d --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt @@ -0,0 +1,5 @@ +// FIX: Replace with 'check()' call +// WITH_RUNTIME +fun test(b: Boolean) { + if (b) throw IllegalStateException() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt.after new file mode 100644 index 00000000000..9546083d32f --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'check()' call +// WITH_RUNTIME +fun test(b: Boolean) { + check(!b) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt new file mode 100644 index 00000000000..2d8fa0fc42a --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt @@ -0,0 +1,5 @@ +// FIX: Replace with 'checkNotNull()' call +// WITH_RUNTIME +fun test(foo: Int?) { + if (foo == null) throw IllegalStateException() +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt.after new file mode 100644 index 00000000000..7961557161d --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'checkNotNull()' call +// WITH_RUNTIME +fun test(foo: Int?) { + checkNotNull(foo) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/notTargetException.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/notTargetException.kt new file mode 100644 index 00000000000..4da48a73238 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/notTargetException.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +// WITH_RUNTIME +fun test(b: Boolean) { + if (b) throw IndexOutOfBoundsException() +} diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt new file mode 100644 index 00000000000..2ca21befda5 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt @@ -0,0 +1,7 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + if (b) { + throw IllegalArgumentException("test") + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt.after new file mode 100644 index 00000000000..8327b8fbb33 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + require(!b) { "test" } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt new file mode 100644 index 00000000000..9e8dfd42298 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt @@ -0,0 +1,7 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + if (b) { + throw java.lang.IllegalArgumentException("test") + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt.after new file mode 100644 index 00000000000..8327b8fbb33 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + require(!b) { "test" } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt new file mode 100644 index 00000000000..8e825ac3900 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt @@ -0,0 +1,9 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + if (b) { + // comment1 + throw IllegalArgumentException() + // comment2 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt.after new file mode 100644 index 00000000000..32fac69d89a --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt.after @@ -0,0 +1,7 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + // comment1 + // comment2 + require(!b) +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt new file mode 100644 index 00000000000..da6b5d26eb4 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt @@ -0,0 +1,9 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + if (b) { + // comment1 + throw IllegalArgumentException("test") + // comment2 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt.after new file mode 100644 index 00000000000..34e37b56f70 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt.after @@ -0,0 +1,9 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(b: Boolean) { + require(!b) { + // comment1 + "test" + // comment2 + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt new file mode 100644 index 00000000000..32bfcbd08e0 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt @@ -0,0 +1,5 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(foo: Boolean) { + if (!foo) throw IllegalArgumentException("test") +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt.after new file mode 100644 index 00000000000..91e705483ab --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(foo: Boolean) { + require(foo) { "test" } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt new file mode 100644 index 00000000000..956d21220d8 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt @@ -0,0 +1,5 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(foo: Int) { + if (foo != 0) throw IllegalArgumentException("test") +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt.after new file mode 100644 index 00000000000..ffdae9178d8 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'require()' call +// WITH_RUNTIME +fun test(foo: Int) { + require(foo == 0) { "test" } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt new file mode 100644 index 00000000000..ec94eedf7ac --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt @@ -0,0 +1,7 @@ +// FIX: Replace with 'requireNotNull()' call +// WITH_RUNTIME +fun test(foo: Int?) { + if (foo == null) { + throw IllegalArgumentException("test") + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt.after b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt.after new file mode 100644 index 00000000000..c5a9ced25c8 --- /dev/null +++ b/idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt.after @@ -0,0 +1,5 @@ +// FIX: Replace with 'requireNotNull()' call +// WITH_RUNTIME +fun test(foo: Int?) { + requireNotNull(foo) { "test" } +} \ 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 854b01fb2e2..c59481f4902 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -8902,6 +8902,121 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { } } + @TestMetadata("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ReplaceGuardClauseWithFunctionCall extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInReplaceGuardClauseWithFunctionCall() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("notTargetException.kt") + public void testNotTargetException() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/notTargetException.kt"); + } + + @TestMetadata("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Check extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInCheck() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/check/basic.kt"); + } + } + + @TestMetadata("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CheckNotNull extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInCheckNotNull() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/checkNotNull/basic.kt"); + } + } + + @TestMetadata("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Require extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInRequire() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic.kt"); + } + + @TestMetadata("basic2.kt") + public void testBasic2() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/basic2.kt"); + } + + @TestMetadata("comment.kt") + public void testComment() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment.kt"); + } + + @TestMetadata("comment2.kt") + public void testComment2() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/comment2.kt"); + } + + @TestMetadata("not.kt") + public void testNot() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/not.kt"); + } + + @TestMetadata("notEq.kt") + public void testNotEq() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/require/notEq.kt"); + } + } + + @TestMetadata("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class RequireNotNull extends AbstractLocalInspectionTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInRequireNotNull() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("idea/testData/inspectionsLocal/replaceGuardClauseWithFunctionCall/requireNotNull/basic.kt"); + } + } + } + @TestMetadata("idea/testData/inspectionsLocal/replaceJavaStaticMethodWithKotlinAnalog") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/j2k/testData/fileOrElement/postProcessing/GuardClause.java b/j2k/testData/fileOrElement/postProcessing/GuardClause.java new file mode 100644 index 00000000000..bc558320a69 --- /dev/null +++ b/j2k/testData/fileOrElement/postProcessing/GuardClause.java @@ -0,0 +1,7 @@ +public class Test { + void test(String s) { + if (s == null) { + throw new IllegalArgumentException("s should not be null"); + } + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/postProcessing/GuardClause.kt b/j2k/testData/fileOrElement/postProcessing/GuardClause.kt new file mode 100644 index 00000000000..ed8fbcad9d1 --- /dev/null +++ b/j2k/testData/fileOrElement/postProcessing/GuardClause.kt @@ -0,0 +1,5 @@ +class Test { + internal fun test(s: String?) { + requireNotNull(s) { "s should not be null" } + } +} \ No newline at end of file diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index cb3f3b3f9b6..b8794ea26c5 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -3779,6 +3779,11 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo runTest("j2k/testData/fileOrElement/postProcessing/GetOperator.java"); } + @TestMetadata("GuardClause.java") + public void testGuardClause() throws Exception { + runTest("j2k/testData/fileOrElement/postProcessing/GuardClause.java"); + } + @TestMetadata("IfNullReturnToElvis.java") public void testIfNullReturnToElvis() throws Exception { runTest("j2k/testData/fileOrElement/postProcessing/IfNullReturnToElvis.java"); diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index 30112a4c738..bddae0b999b 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -3779,6 +3779,11 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo runTest("j2k/testData/fileOrElement/postProcessing/GetOperator.java"); } + @TestMetadata("GuardClause.java") + public void testGuardClause() throws Exception { + runTest("j2k/testData/fileOrElement/postProcessing/GuardClause.java"); + } + @TestMetadata("IfNullReturnToElvis.java") public void testIfNullReturnToElvis() throws Exception { runTest("j2k/testData/fileOrElement/postProcessing/IfNullReturnToElvis.java");