diff --git a/idea/resources/inspectionDescriptions/MapGetWithNotNullAssertionOperator.html b/idea/resources/inspectionDescriptions/MapGetWithNotNullAssertionOperator.html
index a5884cc186a..81f6877429b 100644
--- a/idea/resources/inspectionDescriptions/MapGetWithNotNullAssertionOperator.html
+++ b/idea/resources/inspectionDescriptions/MapGetWithNotNullAssertionOperator.html
@@ -1,5 +1,5 @@
-This inspection reports map.get()!! that can be replaced with map.getValue().
+This inspection reports map.get()!! that can be replaced with map.getValue(), map.getOrElse(), etc.
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/MapGetWithNotNullAssertionOperatorInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/MapGetWithNotNullAssertionOperatorInspection.kt
index 06fd623191a..96d7d20d465 100644
--- a/idea/src/org/jetbrains/kotlin/idea/inspections/MapGetWithNotNullAssertionOperatorInspection.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/MapGetWithNotNullAssertionOperatorInspection.kt
@@ -10,6 +10,7 @@ import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiDocumentManager
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.intentions.callExpression
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
class MapGetWithNotNullAssertionOperatorInspection : AbstractKotlinInspection() {
@@ -29,7 +31,9 @@ class MapGetWithNotNullAssertionOperatorInspection : AbstractKotlinInspection()
expression.operationReference,
"map.get() with not-null assertion operator (!!)",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
- ReplaceWithGetValueCallFix()
+ ReplaceWithGetValueCallFix(),
+ ReplaceWithGetOrElseFix(),
+ ReplaceWithElvisErrorFix()
)
})
@@ -43,6 +47,37 @@ class MapGetWithNotNullAssertionOperatorInspection : AbstractKotlinInspection()
replaced.findExistingEditor()?.caretModel?.moveToOffset(replaced.endOffset)
}
}
+
+ private class ReplaceWithGetOrElseFix : LocalQuickFix {
+ override fun getName() = "Replace with 'getOrElse' call"
+ override fun getFamilyName() = name
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val expression = descriptor.psiElement.parent as? KtPostfixExpression ?: return
+ val (reference, index) = expression.getReplacementData() ?: return
+ val replaced = expression.replaced(KtPsiFactory(expression).createExpressionByPattern("$0.getOrElse($1){}", reference, index))
+
+ val editor = replaced.findExistingEditor() ?: return
+ val offset = (replaced as KtQualifiedExpression).callExpression?.lambdaArguments?.firstOrNull()?.startOffset ?: return
+ val document = editor.document
+ PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document)
+ document.insertString(offset + 1, " ")
+ editor.caretModel.moveToOffset(offset + 2)
+ }
+ }
+
+ private class ReplaceWithElvisErrorFix : LocalQuickFix {
+ override fun getName() = "Replace with '?: error(\"\")'"
+ override fun getFamilyName() = name
+ override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
+ val expression = descriptor.psiElement.parent as? KtPostfixExpression ?: return
+ val (reference, index) = expression.getReplacementData() ?: return
+ val replaced = expression.replace(KtPsiFactory(expression).createExpressionByPattern("$0[$1] ?: error(\"\")", reference, index))
+
+ val editor = replaced.findExistingEditor() ?: return
+ val offset = (replaced as? KtBinaryExpression)?.right?.endOffset ?: return
+ editor.caretModel.moveToOffset(offset - 2)
+ }
+ }
}
private fun KtPostfixExpression.getReplacementData(): Pair? {
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt
index 26e1fe89a2b..19b06741146 100644
--- a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt
@@ -1,3 +1,4 @@
+// FIX: Replace with 'getValue' call
// WITH_RUNTIME
fun test(map: Map) {
val s = map.get(1)!!
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt.after b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt.after
index 43f6104cd3c..6b558d2b016 100644
--- a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt.after
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/get.kt.after
@@ -1,3 +1,4 @@
+// FIX: Replace with 'getValue' call
// WITH_RUNTIME
fun test(map: Map) {
val s = map.getValue(1)
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt
index 1aaa64a7e05..576c2e93190 100644
--- a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt
@@ -1,3 +1,4 @@
+// FIX: Replace with 'getValue' call
// WITH_RUNTIME
fun test(map: Map) {
val s = map[1]!!
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt.after b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt.after
index 43f6104cd3c..6b558d2b016 100644
--- a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt.after
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/indexedAccess.kt.after
@@ -1,3 +1,4 @@
+// FIX: Replace with 'getValue' call
// WITH_RUNTIME
fun test(map: Map) {
val s = map.getValue(1)
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt
new file mode 100644
index 00000000000..4302535abcc
--- /dev/null
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt
@@ -0,0 +1,5 @@
+// FIX: Replace with '?: error("")'
+// WITH_RUNTIME
+fun test(map: Map) {
+ val s = map[1]!!
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt.after b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt.after
new file mode 100644
index 00000000000..f1a93dabc10
--- /dev/null
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt.after
@@ -0,0 +1,5 @@
+// FIX: Replace with '?: error("")'
+// WITH_RUNTIME
+fun test(map: Map) {
+ val s = map[1] ?: error("")
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt
new file mode 100644
index 00000000000..dcc744fa7de
--- /dev/null
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt
@@ -0,0 +1,6 @@
+// FIX: Replace with 'getOrElse' call
+// DISABLE-ERRORS
+// WITH_RUNTIME
+fun test(map: Map) {
+ val s = map[1]!!
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt.after b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt.after
new file mode 100644
index 00000000000..c6a4c2241a8
--- /dev/null
+++ b/idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt.after
@@ -0,0 +1,6 @@
+// FIX: Replace with 'getOrElse' call
+// DISABLE-ERRORS
+// WITH_RUNTIME
+fun test(map: Map) {
+ val s = map.getOrElse(1) { }
+}
\ 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 37a3bbc22e2..e70ba38eca1 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -3840,6 +3840,16 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
public void testNoNotNullAssersion() throws Exception {
runTest("idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/noNotNullAssersion.kt");
}
+
+ @TestMetadata("replaceWithElvisError.kt")
+ public void testReplaceWithElvisError() throws Exception {
+ runTest("idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithElvisError.kt");
+ }
+
+ @TestMetadata("replaceWithGetOrElse.kt")
+ public void testReplaceWithGetOrElse() throws Exception {
+ runTest("idea/testData/inspectionsLocal/mapGetWithNotNullAssertionOperator/replaceWithGetOrElse.kt");
+ }
}
@TestMetadata("idea/testData/inspectionsLocal/mayBeConstant")