diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml
index 503b5dbda6c..6a05a337bab 100644
--- a/idea/resources/META-INF/plugin-common.xml
+++ b/idea/resources/META-INF/plugin-common.xml
@@ -3164,6 +3164,15 @@
language="kotlin"
/>
+
+
diff --git a/idea/resources/inspectionDescriptions/BooleanLiteralArgument.html b/idea/resources/inspectionDescriptions/BooleanLiteralArgument.html
new file mode 100644
index 00000000000..67fe55548ce
--- /dev/null
+++ b/idea/resources/inspectionDescriptions/BooleanLiteralArgument.html
@@ -0,0 +1,5 @@
+
+
+This inspection reports boolean literal arguments should be named.
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/BooleanLiteralArgumentInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/BooleanLiteralArgumentInspection.kt
new file mode 100644
index 00000000000..b526d1b97f7
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/BooleanLiteralArgumentInspection.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.codeInspection.IntentionWrapper
+import com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING
+import com.intellij.codeInspection.ProblemsHolder
+import com.intellij.openapi.util.TextRange
+import org.jetbrains.kotlin.KtNodeTypes
+import org.jetbrains.kotlin.diagnostics.Severity
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
+import org.jetbrains.kotlin.idea.intentions.AddNameToArgumentIntention
+import org.jetbrains.kotlin.idea.intentions.AddNamesToCallArgumentsIntention
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+
+class BooleanLiteralArgumentInspection : AbstractKotlinInspection() {
+ override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) =
+ valueArgumentVisitor(fun(argument: KtValueArgument) {
+ if (argument.getArgumentName() != null) return
+ val argumentExpression = argument.getArgumentExpression() as? KtConstantExpression ?: return
+ if (argumentExpression.node.elementType != KtNodeTypes.BOOLEAN_CONSTANT) return
+ if (argumentExpression.analyze().diagnostics.forElement(argumentExpression).any { it.severity == Severity.ERROR }) return
+ val call = argument.getStrictParentOfType() ?: return
+ if (call.resolveToCall()?.resultingDescriptor?.hasStableParameterNames() != true) return
+
+ when {
+ call.valueArguments.takeLastWhile { it != argument }.none { !it.isNamed() } ->
+ holder.registerProblem(
+ argument,
+ "Boolean literal argument without parameter name",
+ GENERIC_ERROR_OR_WARNING,
+ IntentionWrapper(AddNameToArgumentIntention(), argument.containingKtFile)
+ )
+ AddNamesToCallArgumentsIntention.canAddNamesToCallArguments(call) ->
+ holder.registerProblem(
+ holder.manager.createProblemDescriptor(
+ call,
+ argument.textRange.shiftRight(-call.startOffset),
+ description,
+ highlightType,
+ isOnTheFly,
+ IntentionWrapper(AddNamesIntention(), file)
+ )
+ )
+ }
+ })
+
+ private class AddNamesIntention : AddNamesToCallArgumentsIntention() {
+ override fun applicabilityRange(element: KtCallElement): TextRange? = element.textRange
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/AddNamesToCallArgumentsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/AddNamesToCallArgumentsIntention.kt
index 828a516ae89..cb700a06e19 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/AddNamesToCallArgumentsIntention.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/AddNamesToCallArgumentsIntention.kt
@@ -23,26 +23,12 @@ import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
-class AddNamesToCallArgumentsIntention : SelfTargetingRangeIntention(
+open class AddNamesToCallArgumentsIntention : SelfTargetingRangeIntention(
KtCallElement::class.java,
"Add names to call arguments"
) {
- override fun applicabilityRange(element: KtCallElement): TextRange? {
- val arguments = element.valueArguments
- if (arguments.all { it.isNamed() || it is LambdaArgument }) return null
-
- val resolvedCall = element.resolveToCall() ?: return null
- if (!resolvedCall.resultingDescriptor.hasStableParameterNames()) return null
-
- if (arguments.all {
- AddNameToArgumentIntention.argumentMatchedAndCouldBeNamedInCall(it, resolvedCall, element.languageVersionSettings)
- }
- ) {
- return element.calleeExpression?.textRange
- }
-
- return null
- }
+ override fun applicabilityRange(element: KtCallElement): TextRange? =
+ element.calleeExpression?.textRange?.takeIf { canAddNamesToCallArguments(element) }
override fun applyTo(element: KtCallElement, editor: Editor?) {
val arguments = element.valueArguments
@@ -59,4 +45,19 @@ class AddNamesToCallArgumentsIntention : SelfTargetingRangeIntention)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt
new file mode 100644
index 00000000000..d1e3dfc7cdb
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add 'c =' to argument
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, true, true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt.after b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt.after
new file mode 100644
index 00000000000..6485f9ac346
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt.after
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add 'c =' to argument
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt
new file mode 100644
index 00000000000..ce6191b4ddf
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add names to call arguments
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, true, true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt.after b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt.after
new file mode 100644
index 00000000000..99251ab678b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt.after
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add names to call arguments
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(a = true, b = true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt
new file mode 100644
index 00000000000..e22e79a68c4
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add 'b =' to argument
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt.after b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt.after
new file mode 100644
index 00000000000..551e42c5a90
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt.after
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add 'b =' to argument
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, b = true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt
new file mode 100644
index 00000000000..bc9033ae4a2
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add names to call arguments
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt.after b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt.after
new file mode 100644
index 00000000000..99251ab678b
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt.after
@@ -0,0 +1,7 @@
+// HIGHLIGHT: GENERIC_ERROR_OR_WARNING
+// FIX: Add names to call arguments
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(a = true, b = true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/hasError.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/hasError.kt
new file mode 100644
index 00000000000..bc298b5b5f0
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/hasError.kt
@@ -0,0 +1,7 @@
+// PROBLEM: none
+// DISABLE-ERRORS
+fun foo(vararg a: Int, b: Boolean) {}
+
+fun test() {
+ foo(1, 2, 3, true)
+}
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/hasName.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/hasName.kt
new file mode 100644
index 00000000000..16c030d92f5
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/hasName.kt
@@ -0,0 +1,6 @@
+// PROBLEM: none
+fun foo(a: Boolean, b: Boolean, c: Boolean) {}
+
+fun test() {
+ foo(true, true, c = true)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/hasVararg.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/hasVararg.kt
new file mode 100644
index 00000000000..08eb6009ae1
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/hasVararg.kt
@@ -0,0 +1,7 @@
+// PROBLEM: none
+fun foo(a: Boolean, vararg b: Int) {}
+
+fun test() {
+ foo(true, 1, 2, 3)
+}
+
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/intLiteral.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/intLiteral.kt
new file mode 100644
index 00000000000..2da8505ade0
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/intLiteral.kt
@@ -0,0 +1,6 @@
+// PROBLEM: none
+fun foo(a: Boolean, b: Boolean, c: Int) {}
+
+fun test(b: Boolean) {
+ foo(true, true, 1)
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.1.java b/idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.1.java
new file mode 100644
index 00000000000..639262590c8
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.1.java
@@ -0,0 +1,3 @@
+public class JavaClass {
+ void foo(boolean b) {}
+}
\ No newline at end of file
diff --git a/idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.kt b/idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.kt
new file mode 100644
index 00000000000..355f5529c21
--- /dev/null
+++ b/idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.kt
@@ -0,0 +1,4 @@
+// PROBLEM: none
+fun test() {
+ JavaClass().foo(false)
+}
\ 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 c4c6ed0b55c..159d21963a7 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java
@@ -47,6 +47,69 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
}
}
+ @TestMetadata("idea/testData/inspectionsLocal/booleanLiteralArgument")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class BooleanLiteralArgument extends AbstractLocalInspectionTest {
+ private void runTest(String testDataFilePath) throws Exception {
+ KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
+ }
+
+ public void testAllFilesPresentInBooleanLiteralArgument() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/inspectionsLocal/booleanLiteralArgument"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
+ }
+
+ @TestMetadata("boolean.kt")
+ public void testBoolean() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/boolean.kt");
+ }
+
+ @TestMetadata("booleanLiteral.kt")
+ public void testBooleanLiteral() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral.kt");
+ }
+
+ @TestMetadata("booleanLiteral2.kt")
+ public void testBooleanLiteral2() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral2.kt");
+ }
+
+ @TestMetadata("booleanLiteral3.kt")
+ public void testBooleanLiteral3() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral3.kt");
+ }
+
+ @TestMetadata("booleanLiteral4.kt")
+ public void testBooleanLiteral4() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/booleanLiteral4.kt");
+ }
+
+ @TestMetadata("hasError.kt")
+ public void testHasError() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/hasError.kt");
+ }
+
+ @TestMetadata("hasName.kt")
+ public void testHasName() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/hasName.kt");
+ }
+
+ @TestMetadata("hasVararg.kt")
+ public void testHasVararg() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/hasVararg.kt");
+ }
+
+ @TestMetadata("intLiteral.kt")
+ public void testIntLiteral() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/intLiteral.kt");
+ }
+
+ @TestMetadata("javaMethod.kt")
+ public void testJavaMethod() throws Exception {
+ runTest("idea/testData/inspectionsLocal/booleanLiteralArgument/javaMethod.kt");
+ }
+ }
+
@TestMetadata("idea/testData/inspectionsLocal/branched")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)