diff --git a/.idea/dictionaries/valentin.xml b/.idea/dictionaries/valentin.xml
index 8fee9efdd5d..fd8f3810478 100644
--- a/.idea/dictionaries/valentin.xml
+++ b/.idea/dictionaries/valentin.xml
@@ -6,6 +6,7 @@
inserter
pparent
processings
+ rbracket
rparenth
selectioner
diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt
index e9da59a840c..ea22b5f9dca 100644
--- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt
+++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/OperatorToFunctionIntention.kt
@@ -57,7 +57,8 @@ public class OperatorToFunctionIntention : JetSelfTargetingIntention(javaC
val expression = element.getTargetExpression(caretOffset) ?: return false
if (expression is JetBlockExpression) return false
- val description = (expression.getParent() as JetContainerNode).description()
+ val description = (expression.getParent() as JetContainerNode).description()!!
setText("Add braces to '$description' statement")
return true
}
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertAssertToIfWithThrowIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertAssertToIfWithThrowIntention.kt
index 9b4f3ffc3d4..37c7035c561 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertAssertToIfWithThrowIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertAssertToIfWithThrowIntention.kt
@@ -28,12 +28,13 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention(javaClass(), "Replace 'assert' with 'if' statement") {
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean {
val callee = element.getCalleeExpression() ?: return false
- if (callee.getText() != "assert") return false
if (!callee.getTextRange().containsOffset(caretOffset)) return false
val argumentSize = element.getValueArguments().size()
if (argumentSize !in 1..2) return false
- if (element.getFunctionLiteralArguments().size() == 1 && argumentSize == 1) return false
+ val functionLiterals = element.getFunctionLiteralArguments()
+ if (functionLiterals.size() > 1) return false
+ if (functionLiterals.size() == 1 && argumentSize == 1) return false // "assert {...}" is incorrect
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return false
return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).asString() == "kotlin.assert"
@@ -42,14 +43,14 @@ public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention args[1]?.getArgumentExpression() ?: return
- functionLiterals.isNotEmpty() -> functionLiterals.first()
+ functionLiteral != null -> functionLiteral!!
else -> psiFactory.createExpression("\"Assertion failed\"")
}
@@ -58,34 +59,27 @@ public class ConvertAssertToIfWithThrowIntention : JetSelfTargetingIntention(javaClass(), "Replace with a for each loop") {
+public class ConvertForEachToForLoopIntention : JetSelfTargetingIntention(javaClass(), "Replace with a for loop") {
override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean {
- val data = extractData(element) ?: return false
- if (data.functionLiteral.getValueParameters().size() > 1) return false
- if (data.functionLiteral.getValueParameters().size() > 1 || data.functionLiteral.getBodyExpression() == null) return false
+ val functionLiteral = extractFunctionLiteral(element) ?: return false
+ if (functionLiteral.getValueParameters().size() > 1) return false
+ if (functionLiteral.getBodyExpression() == null) return false
- if (caretOffset > data.functionLiteral.getTextRange().getStartOffset()) return false // not available within function literal body
+ if (caretOffset > functionLiteral.getTextRange().getStartOffset()) return false // not available within function literal body
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return false
- return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() == "kotlin.forEach"
+ if (DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() != "kotlin.forEach") return false
+ return resolvedCall.getCall().getExplicitReceiver() is ExpressionReceiver
}
override fun applyTo(element: JetExpression, editor: Editor) {
- val data = extractData(element)!!
- val loopText = generateLoopText(data.functionLiteral, data.receiver)
- element.replace(JetPsiFactory(element).createExpression(loopText))
+ val functionLiteral = extractFunctionLiteral(element)!!
+ val receiver = element.getCall(element.analyze())!!.getExplicitReceiver() as ExpressionReceiver
+ val receiverExpression = receiver.getExpression()
+ val loopText = generateLoopText(functionLiteral, receiverExpression)
+ val expressionToReplace = receiverExpression.getParent() // it's correct for both JetDotQualifiedExpression and JetBinaryExpression
+ expressionToReplace.replace(JetPsiFactory(element).createExpression(loopText))
}
- private data class Data(val functionLiteral: JetFunctionLiteralExpression, val receiver: JetExpression)
-
- private fun extractData(element: JetExpression): Data? {
- when (element) {
- is JetDotQualifiedExpression -> {
- val selector = element.getSelectorExpression() as? JetCallExpression ?: return null
- val argument = selector.getValueArguments().singleOrNull() ?: return null
- val functionLiteral = argument.getArgumentExpression() as? JetFunctionLiteralExpression ?: return null
- return Data(functionLiteral, element.getReceiverExpression())
- }
-
- is JetBinaryExpression -> {
- val functionLiteral = element.getRight() as? JetFunctionLiteralExpression ?: return null
- return Data(functionLiteral, element.getLeft() ?: return null)
- }
-
- else -> return null
- }
+ private fun extractFunctionLiteral(element: JetExpression): JetFunctionLiteralExpression? {
+ return when (element) {
+ is JetCallExpression -> element.getValueArguments().singleOrNull()?.getArgumentExpression()
+ is JetBinaryExpression -> element.getRight()
+ else -> null
+ } as? JetFunctionLiteralExpression
}
private fun generateLoopText(functionLiteral: JetFunctionLiteralExpression, receiver: JetExpression): String {
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertNegatedBooleanSequenceIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertNegatedBooleanSequenceIntention.kt
index 5a9404568a4..d5e1ccc850b 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertNegatedBooleanSequenceIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertNegatedBooleanSequenceIntention.kt
@@ -38,7 +38,7 @@ public class ConvertNegatedBooleanSequenceIntention : JetSelfTargetingOffsetInde
val operatorText = when(element.getOperationToken()) {
JetTokens.ANDAND -> JetTokens.OROR.getValue()
JetTokens.OROR -> JetTokens.ANDAND.getValue()
- else -> throw IllegalArgumentException()
+ else -> throw IllegalArgumentException() // checked in isApplicableTo
}
val elements = splitBooleanSequence(element)!!
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToExpressionBodyIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToExpressionBodyIntention.kt
index d820a34632e..b5dc1077e85 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToExpressionBodyIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToExpressionBodyIntention.kt
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import kotlin.platform.platformName
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToForEachFunctionCallIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToForEachFunctionCallIntention.kt
index f44f6075017..6549009f932 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToForEachFunctionCallIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToForEachFunctionCallIntention.kt
@@ -35,17 +35,10 @@ public class ConvertToForEachFunctionCallIntention : JetSelfTargetingIntention body.getStatements().map { it.getText() }.joinToString("\n")
else -> body.getText()
}
- val bodyText = buildFunctionLiteralBodyText(loopParameter, functionBodyText)
+ val bodyText = "${loopParameter.getText()} -> $functionBodyText"
val foreachExpression = factory.createExpression("x.forEach { $bodyText }") as JetDotQualifiedExpression
foreachExpression.getReceiverExpression().replace(element.getLoopRange()!!)
element.replace(foreachExpression)
}
-
- private fun buildFunctionLiteralBodyText(loopParameter: JetParameter, functionBodyText: String): String {
- return when {
- loopParameter.getTypeReference() != null -> " (${loopParameter.getText()}) -> $functionBodyText"
- else -> "${loopParameter.getText()} -> $functionBodyText"
- }
- }
}
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveBracesIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveBracesIntention.kt
index 00a2c383bcc..449fad1e2f1 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveBracesIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveBracesIntention.kt
@@ -32,7 +32,8 @@ public class RemoveBracesIntention : JetSelfTargetingIntentionx.reverse().forEach { it }
+ x.reverse().forEach { it }
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertForEachToForLoop/explicitFunctionLiteral.kt b/idea/testData/intentions/convertForEachToForLoop/explicitFunctionLiteral.kt
index c801e547fda..7edcaea43af 100644
--- a/idea/testData/intentions/convertForEachToForLoop/explicitFunctionLiteral.kt
+++ b/idea/testData/intentions/convertForEachToForLoop/explicitFunctionLiteral.kt
@@ -2,5 +2,5 @@
fun foo() {
val x = 1..4
- x.forEach({ y -> y })
+ x.forEach({ y -> y })
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertForEachToForLoop/implicitFunctionLiteralParameter.kt b/idea/testData/intentions/convertForEachToForLoop/implicitFunctionLiteralParameter.kt
index e6ba3880d2d..d163c979777 100644
--- a/idea/testData/intentions/convertForEachToForLoop/implicitFunctionLiteralParameter.kt
+++ b/idea/testData/intentions/convertForEachToForLoop/implicitFunctionLiteralParameter.kt
@@ -2,5 +2,5 @@
fun foo() {
val x = 1..4
- x.forEach { it }
+ x.forEach { it }
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertForEachToForLoop/parenthesizedExpression.kt b/idea/testData/intentions/convertForEachToForLoop/parenthesizedExpression.kt
index a6137d098a9..67b40498721 100644
--- a/idea/testData/intentions/convertForEachToForLoop/parenthesizedExpression.kt
+++ b/idea/testData/intentions/convertForEachToForLoop/parenthesizedExpression.kt
@@ -1,4 +1,4 @@
// WITH_RUNTIME
fun main() {
- (1 rangeTo 2).forEach { x -> x }
+ (1 rangeTo 2).forEach { x -> x }
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertForEachToForLoop/simple.kt b/idea/testData/intentions/convertForEachToForLoop/simple.kt
index fec99e3a5a8..54a3627b76d 100644
--- a/idea/testData/intentions/convertForEachToForLoop/simple.kt
+++ b/idea/testData/intentions/convertForEachToForLoop/simple.kt
@@ -2,5 +2,5 @@
fun foo() {
val x = 1..4
- x.forEach { it.equals(1) }
+ x.forEach { it.equals(1) }
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertForEachToForLoop/typeArgumentPresent.kt b/idea/testData/intentions/convertForEachToForLoop/typeArgumentPresent.kt
index 543204fe6a8..d5cc7b393fb 100644
--- a/idea/testData/intentions/convertForEachToForLoop/typeArgumentPresent.kt
+++ b/idea/testData/intentions/convertForEachToForLoop/typeArgumentPresent.kt
@@ -2,5 +2,5 @@
fun foo() {
val x = 1..4
- x.forEach({ it })
+ x.forEach({ it })
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertToForEachFunctionCall/iterativeElementTypeSpecified.kt.after b/idea/testData/intentions/convertToForEachFunctionCall/iterativeElementTypeSpecified.kt.after
index 1183a23711b..e800c27fe50 100644
--- a/idea/testData/intentions/convertToForEachFunctionCall/iterativeElementTypeSpecified.kt.after
+++ b/idea/testData/intentions/convertToForEachFunctionCall/iterativeElementTypeSpecified.kt.after
@@ -2,5 +2,5 @@
fun main() {
val list = 1..4
- list.forEach {(x: Int) -> x }
+ list.forEach { x: Int -> x }
}
\ No newline at end of file
diff --git a/idea/testData/intentions/convertToForEachFunctionCall/typeAnnotatedWithNonBlockBody.kt.after b/idea/testData/intentions/convertToForEachFunctionCall/typeAnnotatedWithNonBlockBody.kt.after
index b3babbdc94a..5f8d6656adf 100644
--- a/idea/testData/intentions/convertToForEachFunctionCall/typeAnnotatedWithNonBlockBody.kt.after
+++ b/idea/testData/intentions/convertToForEachFunctionCall/typeAnnotatedWithNonBlockBody.kt.after
@@ -2,5 +2,5 @@
fun main() {
val list = 1..4
- list.forEach {(x: Int) -> 11 }
+ list.forEach { x: Int -> 11 }
}
\ No newline at end of file