diff --git a/idea/resources/inspectionDescriptions/ReplaceAssertBooleanWithAssertEquality.html b/idea/resources/inspectionDescriptions/ReplaceAssertBooleanWithAssertEquality.html
new file mode 100644
index 00000000000..dfa5ccbbf46
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/ReplaceAssertBooleanWithAssertEquality.html
@@ -0,0 +1,6 @@
+
+
+This inspection reports assert boolean function calls replaceable with assert equality function.
+Example: assertTrue(a == b) can be replaced by assertEquals(a, b).
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 4adf664e6d6..94a9dab6b3b 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -2997,6 +2997,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.173 b/idea/src/META-INF/plugin.xml.173
index ab6f00e4bf7..ccbe8172e47 100644
--- a/idea/src/META-INF/plugin.xml.173
+++ b/idea/src/META-INF/plugin.xml.173
@@ -2996,6 +2996,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.181 b/idea/src/META-INF/plugin.xml.181
index 734cbab93cb..f84120de957 100644
--- a/idea/src/META-INF/plugin.xml.181
+++ b/idea/src/META-INF/plugin.xml.181
@@ -2996,6 +2996,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.183 b/idea/src/META-INF/plugin.xml.183
index 07a7a44ac0b..735a9cd0a0b 100644
--- a/idea/src/META-INF/plugin.xml.183
+++ b/idea/src/META-INF/plugin.xml.183
@@ -2997,6 +2997,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.as31 b/idea/src/META-INF/plugin.xml.as31
index 93b4115f0a7..95698548183 100644
--- a/idea/src/META-INF/plugin.xml.as31
+++ b/idea/src/META-INF/plugin.xml.as31
@@ -2996,6 +2996,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.as32 b/idea/src/META-INF/plugin.xml.as32
index 92bd0cb3b71..5e97bc35f06 100644
--- a/idea/src/META-INF/plugin.xml.as32
+++ b/idea/src/META-INF/plugin.xml.as32
@@ -2996,6 +2996,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/META-INF/plugin.xml.as33 b/idea/src/META-INF/plugin.xml.as33
index 3e6fc2aa78a..268ec4eee51 100644
--- a/idea/src/META-INF/plugin.xml.as33
+++ b/idea/src/META-INF/plugin.xml.as33
@@ -2998,6 +2998,15 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
language="kotlin"
/>
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceAssertBooleanWithAssertEqualityInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceAssertBooleanWithAssertEqualityInspection.kt
new file mode 100644
index 00000000000..9f830c62f0d
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ReplaceAssertBooleanWithAssertEqualityInspection.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010-2018 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 com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
+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 ReplaceAssertBooleanWithAssertEqualityInspection : AbstractApplicabilityBasedInspection(KtCallExpression::class.java) {
+
+ override fun inspectionText(element: KtCallExpression) = "Replace assert boolean with assert equality"
+
+ override val defaultFixText = "Replace assert boolean with assert equality"
+
+ override fun fixText(element: KtCallExpression): String {
+ val assertion = element.replaceableAssertion() ?: return defaultFixText
+ return "Replace with '$assertion'"
+ }
+
+ override fun isApplicable(element: KtCallExpression): Boolean {
+ return (element.replaceableAssertion() != null)
+ }
+
+ override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
+ val expression = element as? KtCallExpression ?: return
+ val condition = expression.valueArguments.first().getArgumentExpression() as? KtBinaryExpression ?: return
+ val left = condition.left ?: return
+ val right = condition.right ?: return
+ val assertion = expression.replaceableAssertion() ?: return
+ val factory = KtPsiFactory(project)
+
+ if (expression.valueArguments.size == 1) {
+ expression.replace(factory.createExpressionByPattern("$assertion($0, $1)", left, right))
+ } else if (expression.valueArguments.size == 2) {
+ val message = expression.valueArguments[1].getArgumentExpression() ?: return
+ expression.replace(factory.createExpressionByPattern("$assertion($0, $1, $2)", left, right, message))
+ }
+ }
+
+ private fun KtCallExpression.replaceableAssertion(): String? {
+ val referencedName = (calleeExpression as? KtNameReferenceExpression)?.getReferencedName() ?: return null
+ if (referencedName !in assertions) {
+ return null
+ }
+
+ if (getCallableDescriptor()?.containingDeclaration?.fqNameSafe != FqName("kotlin.test")) {
+ return null
+ }
+
+ if (valueArguments.size != 1 && valueArguments.size != 2) return null
+ val binaryExpression = valueArguments.first().getArgumentExpression() as? KtBinaryExpression ?: return null
+ val operationToken = binaryExpression.operationToken
+
+ return assertionMap[Pair(referencedName, operationToken)]
+ }
+
+ companion object {
+ private val assertions = setOf("assertTrue", "assertFalse")
+
+ private val assertionMap = mapOf(
+ Pair("assertTrue", KtTokens.EQEQ) to "assertEquals",
+ Pair("assertTrue", KtTokens.EQEQEQ) to "assertSame",
+ Pair("assertFalse", KtTokens.EQEQ) to "assertNotEquals",
+ Pair("assertFalse", KtTokens.EQEQEQ) to "assertNotSame"
+ )
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/.inspection b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/.inspection
new file mode 100644
index 00000000000..23cef0b237f
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/.inspection
@@ -0,0 +1 @@
+org.jetbrains.kotlin.idea.inspections.ReplaceAssertBooleanWithAssertEqualityInspection
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalse.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalse.kt
new file mode 100644
index 00000000000..c34f4bae5bc
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalse.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+// PROBLEM: none
+
+import kotlin.test.*
+
+fun foo() {
+ val isA = false
+ assertFalse(isA)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt
new file mode 100644
index 00000000000..9daeb97d9d3
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "b"
+ assertFalse(a == b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt.after b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt.after
new file mode 100644
index 00000000000..41fefb75779
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt.after
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "b"
+ assertNotEquals(a, b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt
new file mode 100644
index 00000000000..836d6313869
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "b"
+ assertFalse(a === b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt.after b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt.after
new file mode 100644
index 00000000000..c6f42a57c99
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt.after
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "b"
+ assertNotSame(a, b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt
new file mode 100644
index 00000000000..2e2a1c3caa7
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "b"
+ assertFalse(a == b, "message")
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt.after b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt.after
new file mode 100644
index 00000000000..dc5380969bd
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt.after
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "b"
+ assertNotEquals(a, b, "message")
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrue.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrue.kt
new file mode 100644
index 00000000000..007eb2f1f4f
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrue.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+// PROBLEM: none
+
+import kotlin.test.*
+
+fun foo() {
+ val isA = true
+ assertTrue(isA)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt
new file mode 100644
index 00000000000..a9384a0d47b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "a"
+ assertTrue(a == b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt.after b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt.after
new file mode 100644
index 00000000000..92086e37e9b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt.after
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "a"
+ assertEquals(a, b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt
new file mode 100644
index 00000000000..c1622231e5f
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "a"
+ assertTrue(a === b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt.after b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt.after
new file mode 100644
index 00000000000..0233b2c3c7a
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt.after
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "a"
+ assertSame(a, b)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt
new file mode 100644
index 00000000000..30264bcaff4
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "a"
+ assertTrue(a == b, "message")
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt.after b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt.after
new file mode 100644
index 00000000000..de36b31fc72
--- /dev/null
+++ b/idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt.after
@@ -0,0 +1,9 @@
+// RUNTIME_WITH_KOTLIN_TEST
+
+import kotlin.test.*
+
+fun foo() {
+ val a = "a"
+ val b = "a"
+ assertEquals(a, b, "message")
+}
\ 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 c8c575bf313..e6109eace40 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -4649,6 +4649,59 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class ReplaceAssertBooleanWithAssertEquality extends AbstractLocalInspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInReplaceAssertBooleanWithAssertEquality() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("assertFalse.kt")
+ public void testAssertFalse() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalse.kt");
+ }
+
+ @TestMetadata("assertFalseEQEQ.kt")
+ public void testAssertFalseEQEQ() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQ.kt");
+ }
+
+ @TestMetadata("assertFalseEQEQEQ.kt")
+ public void testAssertFalseEQEQEQ() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseEQEQEQ.kt");
+ }
+
+ @TestMetadata("assertFalseWithMessage.kt")
+ public void testAssertFalseWithMessage() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertFalseWithMessage.kt");
+ }
+
+ @TestMetadata("assertTrue.kt")
+ public void testAssertTrue() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrue.kt");
+ }
+
+ @TestMetadata("assertTrueEQEQ.kt")
+ public void testAssertTrueEQEQ() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQ.kt");
+ }
+
+ @TestMetadata("assertTrueEQEQEQ.kt")
+ public void testAssertTrueEQEQEQ() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueEQEQEQ.kt");
+ }
+
+ @TestMetadata("assertTrueWithMessage.kt")
+ public void testAssertTrueWithMessage() throws Exception {
+ runTest("idea/testData/inspectionsLocal/replaceAssertBooleanWithAssertEquality/assertTrueWithMessage.kt");
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/replacePutWithAssignment")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)