mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] J2K: Port ReplaceGuardClauseWithFunctionCallInspection postprocessing to JKTree phase
KTIJ-28575 closes https://github.com/JetBrains/intellij-community/pull/2709 GitOrigin-RevId: f63831b7849c563f7f78fc7bd7b13b8e843dafbd
This commit is contained in:
committed by
intellij-monorepo-bot
parent
596e92645d
commit
79af0dbadd
-1
@@ -112,7 +112,6 @@ private val inspectionLikePostProcessingGroup = InspectionLikeProcessingGroup(
|
||||
LiftAssignmentInspectionBasedProcessing(),
|
||||
MayBeConstantInspectionBasedProcessing(),
|
||||
RemoveForExpressionLoopParameterTypeProcessing(),
|
||||
inspectionBasedProcessing(ReplaceGuardClauseWithFunctionCallInspection()),
|
||||
intentionBasedProcessing(ConvertToRawStringTemplateIntention(), additionalChecker = ::shouldConvertToRawString),
|
||||
intentionBasedProcessing(IndentRawStringIntention()),
|
||||
intentionBasedProcessing(JoinDeclarationAndAssignmentIntention()),
|
||||
|
||||
+5
@@ -5116,6 +5116,11 @@ public abstract class NewJavaToKotlinConverterSingleFileTestGenerated extends Ab
|
||||
runTest("../../shared/tests/testData/newJ2k/postProcessing/GuardClause.java");
|
||||
}
|
||||
|
||||
@TestMetadata("GuardClauseBasicMode.java")
|
||||
public void testGuardClauseBasicMode() throws Exception {
|
||||
runTest("../../shared/tests/testData/newJ2k/postProcessing/GuardClauseBasicMode.java");
|
||||
}
|
||||
|
||||
@TestMetadata("IfNullReturnToElvis.java")
|
||||
public void testIfNullReturnToElvis() throws Exception {
|
||||
runTest("../../shared/tests/testData/newJ2k/postProcessing/IfNullReturnToElvis.java");
|
||||
|
||||
+5
@@ -5116,6 +5116,11 @@ public abstract class K2JavaToKotlinConverterSingleFileTestGenerated extends Abs
|
||||
runTest("../../shared/tests/testData/newJ2k/postProcessing/GuardClause.java");
|
||||
}
|
||||
|
||||
@TestMetadata("GuardClauseBasicMode.java")
|
||||
public void testGuardClauseBasicMode() throws Exception {
|
||||
runTest("../../shared/tests/testData/newJ2k/postProcessing/GuardClauseBasicMode.java");
|
||||
}
|
||||
|
||||
@TestMetadata("IfNullReturnToElvis.java")
|
||||
public void testIfNullReturnToElvis() throws Exception {
|
||||
runTest("../../shared/tests/testData/newJ2k/postProcessing/IfNullReturnToElvis.java");
|
||||
|
||||
+85
-6
@@ -5,9 +5,7 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.j2k.Nullability.NotNull
|
||||
import org.jetbrains.kotlin.nj2k.*
|
||||
import org.jetbrains.kotlin.nj2k.tree.*
|
||||
import org.jetbrains.kotlin.nj2k.types.JKJavaDisjunctionType
|
||||
import org.jetbrains.kotlin.nj2k.types.isNull
|
||||
import org.jetbrains.kotlin.nj2k.types.updateNullability
|
||||
import org.jetbrains.kotlin.nj2k.types.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class JavaStatementConversion(context: NewJ2kConverterContext) : RecursiveConversion(context) {
|
||||
@@ -19,6 +17,7 @@ class JavaStatementConversion(context: NewJ2kConverterContext) : RecursiveConver
|
||||
is JKJavaAssertStatement -> convertAssert(element)
|
||||
is JKJavaSynchronizedStatement -> convertSynchronized(element)
|
||||
is JKJavaTryStatement -> convertTry(element)
|
||||
is JKIfElseStatement -> convertGuardStatement(element)
|
||||
else -> element
|
||||
}
|
||||
)
|
||||
@@ -36,7 +35,7 @@ class JavaStatementConversion(context: NewJ2kConverterContext) : RecursiveConver
|
||||
if (element.description is JKStubExpression) null
|
||||
else JKLambdaExpression(JKExpressionStatement(element::description.detached()))
|
||||
|
||||
val expressionComparedToNull = assertion.expressionComparedToNull()
|
||||
val expressionComparedToNull = assertion.expressionComparedToNull(isNegated = true)
|
||||
?: return kotlinAssert(assertion, messageExpression, symbolProvider).asStatement().withFormattingFrom(element)
|
||||
val referencedVariable = (expressionComparedToNull as? JKFieldAccessExpression)?.identifier?.target as? JKLocalVariable
|
||||
val checkNotNullSymbol = symbolProvider.provideMethodSymbol("kotlin.checkNotNull")
|
||||
@@ -75,9 +74,10 @@ class JavaStatementConversion(context: NewJ2kConverterContext) : RecursiveConver
|
||||
return statements.subList(declarationIndex + 1, expressionIndex).all { it.isEmpty() }
|
||||
}
|
||||
|
||||
private fun JKExpression.expressionComparedToNull(): JKExpression? {
|
||||
private fun JKExpression.expressionComparedToNull(isNegated: Boolean = false): JKExpression? {
|
||||
if (this !is JKBinaryExpression) return null
|
||||
if (operator.token.text != "!=") return null
|
||||
if (isNegated && operator.token.text != "!=") return null
|
||||
if (!isNegated && operator.token.text != "==") return null
|
||||
|
||||
val left = left
|
||||
val right = right
|
||||
@@ -167,4 +167,83 @@ class JavaStatementConversion(context: NewJ2kConverterContext) : RecursiveConver
|
||||
tryStatement.catchSections.flatMap(::convertCatchSection)
|
||||
)
|
||||
).withFormattingFrom(tryStatement)
|
||||
|
||||
/**
|
||||
* Replaces some if-then-throw statements with calls to `require` or `check`. For example, a statement like
|
||||
* `if (enabled) throw new IllegalArgumentException("must be enabled")` would become `requireNotNull(s1) { "must be enabled" }`.
|
||||
*
|
||||
* This conversion is analogous to `ReplaceGuardClauseWithFunctionCallInspection` and is disabled in basic mode.
|
||||
*/
|
||||
private fun convertGuardStatement(ifElseStatement: JKIfElseStatement): JKStatement {
|
||||
if (context.settings.basicMode) return ifElseStatement
|
||||
|
||||
val thenExpression = ifElseStatement.thenBranch.statements.singleOrNull() ?: return ifElseStatement
|
||||
if (thenExpression !is JKExpressionStatement) return ifElseStatement
|
||||
|
||||
val thrownExpression = thenExpression.expression.safeAs<JKThrowExpression>()?.exception ?: return ifElseStatement
|
||||
if (thrownExpression !is JKNewExpression || thrownExpression.arguments.arguments.size > 1) {
|
||||
return ifElseStatement
|
||||
}
|
||||
|
||||
val expressionComparedToNull = ifElseStatement.condition.expressionComparedToNull()
|
||||
val exceptionName = thrownExpression.identifier?.name
|
||||
val correspondingMethodName = when (exceptionName) {
|
||||
"IllegalArgumentException" -> if (expressionComparedToNull != null) "kotlin.requireNotNull" else "kotlin.require"
|
||||
"IllegalStateException" -> if (expressionComparedToNull != null) "kotlin.checkNotNull" else "kotlin.check"
|
||||
else -> return ifElseStatement
|
||||
}
|
||||
val exceptionArgument = thrownExpression.arguments.arguments.firstOrNull()
|
||||
if (exceptionArgument != null && exceptionArgument.value.calculateType(typeFactory)?.isStringType() != true) {
|
||||
return ifElseStatement
|
||||
}
|
||||
|
||||
val messageExpression = if (exceptionArgument == null) null else
|
||||
JKLambdaExpression(JKExpressionStatement(exceptionArgument::value.detached()))
|
||||
val methodCallSymbol = symbolProvider.provideMethodSymbol(correspondingMethodName)
|
||||
|
||||
val originalCondition = ifElseStatement::condition.detached()
|
||||
val negatedCondition = if (originalCondition is JKPrefixExpression && originalCondition.operator.token.text == "!") {
|
||||
val conditionExpression = originalCondition::expression.detached()
|
||||
if (conditionExpression is JKParenthesizedExpression) {
|
||||
// now that the `!` prefix has been removed, clean up any superfluous parentheses
|
||||
conditionExpression::expression.detached()
|
||||
} else {
|
||||
conditionExpression
|
||||
}
|
||||
} else {
|
||||
JKPrefixExpression(
|
||||
originalCondition.parenthesizeIfCompoundExpression(),
|
||||
JKKtOperatorImpl(JKOperatorToken.EXCL, typeFactory.types.boolean)
|
||||
)
|
||||
}.withFormattingFrom(originalCondition)
|
||||
|
||||
val newCallExpression = if (expressionComparedToNull != null && ifElseStatement.elseBranch.isEmpty()) {
|
||||
JKCallExpressionImpl(
|
||||
methodCallSymbol,
|
||||
listOfNotNull(
|
||||
expressionComparedToNull.detached(ifElseStatement.condition),
|
||||
messageExpression
|
||||
).toArgumentList()
|
||||
)
|
||||
} else {
|
||||
JKCallExpressionImpl(
|
||||
methodCallSymbol,
|
||||
listOfNotNull(negatedCondition, messageExpression).toArgumentList()
|
||||
)
|
||||
}.asStatement()
|
||||
|
||||
val elseBranch = ifElseStatement::elseBranch.detached()
|
||||
return if (elseBranch.isEmpty()) {
|
||||
newCallExpression
|
||||
} else {
|
||||
val statements = if (elseBranch is JKBlockStatement) {
|
||||
// any newlines that should follow the else block will be attached to the new parent block statement
|
||||
elseBranch.statements.last().lineBreaksAfter = 0
|
||||
listOf(newCallExpression) + elseBranch.statements.map { it.detached(elseBranch.block) }
|
||||
} else {
|
||||
listOf(newCallExpression, elseBranch)
|
||||
}
|
||||
JKBlockStatementWithoutBrackets(statements).withFormattingFrom(ifElseStatement)
|
||||
}.withFormattingFrom(ifElseStatement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Test {
|
||||
fun testRequire(s1: String?, b1: Boolean, b2: Boolean) {
|
||||
fun testRequire(s1: String, b1: Boolean, b2: Boolean) {
|
||||
requireNotNull(s1) { "s should not be null" }
|
||||
|
||||
require(b1)
|
||||
@@ -27,7 +27,7 @@ class Test {
|
||||
}
|
||||
|
||||
fun testDoubles(x: Double, y: Double) {
|
||||
check((x < y))
|
||||
check(x < y)
|
||||
check(!(y < 2 * x))
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// IGNORE_K2
|
||||
// !BASIC_MODE: true
|
||||
public class Test {
|
||||
void testBasicMode(String s1) {
|
||||
if (s1 == null) {
|
||||
throw new IllegalArgumentException("s should not be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// !BASIC_MODE: true
|
||||
class Test {
|
||||
fun testBasicMode(s1: String?) {
|
||||
if (s1 == null) {
|
||||
throw IllegalArgumentException("s should not be null")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user