Create TrailingCommaIntention

#KT-34744
This commit is contained in:
Dmitry Gridin
2020-02-04 16:43:57 +07:00
parent 195d9020a6
commit 6c439ae85a
65 changed files with 123 additions and 0 deletions
@@ -1340,6 +1340,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.TrailingCommaIntention</className>
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.ToOrdinaryStringLiteralIntention</className>
<category>Kotlin</category>
@@ -0,0 +1,4 @@
fun a(
i: Int,
b: Int<spot>,</spot>
) = Unit
@@ -0,0 +1,4 @@
fun a(
i: Int,
b: Int
) = Unit
@@ -0,0 +1,5 @@
<html>
<body>
This intention changes the setting <b>Editor -> Code Style -> Kotlin -> Wrapping and Braces -> Use trailing comma</b>.
</body>
</html>
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.intentions
import com.intellij.application.options.CodeStyle
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings
import org.jetbrains.kotlin.idea.util.addTrailingCommaIsAllowedForThis
import org.jetbrains.kotlin.psi.KtElement
class TrailingCommaIntention : SelfTargetingIntention<KtElement>(KtElement::class.java, "Enable/disable a trailing comma in the formatter"),
LowPriorityAction {
override fun applyTo(element: KtElement, editor: Editor?) {
val kotlinCustomSettings = CodeStyle.getSettings(element.project).kotlinCustomSettings
kotlinCustomSettings.ALLOW_TRAILING_COMMA = !kotlinCustomSettings.ALLOW_TRAILING_COMMA
}
override fun isApplicableTo(element: KtElement, caretOffset: Int): Boolean {
return element.addTrailingCommaIsAllowedForThis().also {
val action = if (CodeStyle.getSettings(element.project).kotlinCustomSettings.ALLOW_TRAILING_COMMA) "Disable" else "Enable"
text = "$action a trailing comma by default in the formatter"
}
}
}
+1
View File
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.intentions.TrailingCommaIntention
@@ -0,0 +1 @@
fun a(i: Int<caret>) = Unit
@@ -0,0 +1 @@
fun a(i: Int<caret>) = Unit
@@ -4,6 +4,7 @@
// ACTION: Create enum 'Foo'
// ACTION: Create interface 'Foo'
// ACTION: Create type parameter 'Foo' in function 'use'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: Foo
package bar
@@ -4,6 +4,7 @@
// ACTION: Create enum 'Foo'
// ACTION: Create interface 'Foo'
// ACTION: Create type parameter 'Foo' in function 'use'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: Foo
package bar
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Cannot create an instance of an abstract class
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Test.Foo.component2'
// ACTION: Create member function 'Test.Foo.component1'
// ACTION: Create member function 'Test.Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Destructuring declaration initializer of type Test.Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Test.Foo must have a 'component2()' function
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Foo must have a 'component2()' function
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Foo must have a 'component2()' function
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Foo must have a 'component2()' function
class Foo()
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Foo must have a 'component2()' function
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Foo must have a 'component2()' function
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Cannot access '<init>': it is private in 'Foo'
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
+1
View File
@@ -3,6 +3,7 @@
// ACTION: Create extension function 'Foo.component2'
// ACTION: Create member function 'Foo.component1'
// ACTION: Create member function 'Foo.component2'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put arguments on separate lines
// ERROR: Destructuring declaration initializer of type Foo must have a 'component1()' function
// ERROR: Destructuring declaration initializer of type Foo must have a 'component2()' function
+1
View File
@@ -1,4 +1,5 @@
// "Add 'inline' to function 'foo'" "false"
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Modifier 'crossinline' is allowed only for function parameters of an inline function
fun bar() {
@@ -1,3 +1,4 @@
// "Add 'out' variance" "false"
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Implement interface
interface Empty<<caret>T>
@@ -3,6 +3,7 @@
// ERROR: Destructuring declaration initializer of type Some must have a 'component1()' function
// ACTION: Create extension function 'Some.component1'
// ACTION: Create member function 'Some.component1'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Introduce import alias
@@ -1,4 +1,5 @@
// "Remove parameter 'value'" "false"
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify type explicitly
class Abacaba {
var foo: String
@@ -3,5 +3,6 @@
// ACTION: Create interface 'NotExistent'
// ACTION: Create type parameter 'NotExistent' in class 'TPB'
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: NotExistent
class TPB<X : <caret>NotExistent>
@@ -3,5 +3,6 @@
// ACTION: Create interface 'NotExistent'
// ACTION: Create type parameter 'NotExistent' in class 'TPB'
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: NotExistent
class TPB<X : <caret>NotExistent>
@@ -3,5 +3,6 @@
// ACTION: Create interface 'NotExistent'
// ACTION: Create type parameter 'NotExistent' in class 'TPB'
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: NotExistent
class TPB<X : <caret>NotExistent>
@@ -3,6 +3,7 @@
// ACTION: Create class 'X'
// ACTION: Create enum 'X'
// ACTION: Create interface 'X'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: X
class A
@@ -3,6 +3,7 @@
// ACTION: Create enum 'X'
// ACTION: Create interface 'X'
// ACTION: Create object 'X'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: X
class A
@@ -1,6 +1,7 @@
// "Create type parameter 'X'" "false"
// ACTION: Create class 'X'
// ACTION: Create interface 'X'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: X
class A
@@ -1,4 +1,5 @@
// "Create type parameter in class 'X'" "false"
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Introduce import alias
// ERROR: 2 type arguments expected for class X<T, U>
class X<T, U>
@@ -1,4 +1,5 @@
// "Create type parameter in class 'X'" "false"
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Introduce import alias
// ERROR: No type arguments expected for class X
@@ -1,6 +1,7 @@
// "Create local variable 'defaultPreferencesName'" "false"
// ACTION: Create parameter 'defaultPreferencesName'
// ACTION: Create property 'defaultPreferencesName'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Rename reference
// ERROR: Unresolved reference: defaultPreferencesName
// ERROR: Default value of annotation parameter must be a compile-time constant
@@ -1,5 +1,6 @@
// "Create property 'address2' as constructor parameter" "false"
// ACTION: Create property 'address' as constructor parameter
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Introduce import alias
// ACTION: Make 'Person' data class
// ERROR: Destructuring declaration initializer of type Person must have a 'component3()' function
@@ -1,5 +1,6 @@
// "Make 'foo' private" "false"
// ACTION: Convert parameter to receiver
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Make 'Nested' internal
// ACTION: Make 'Nested' public
// ACTION: Remove parameter 'arg'
@@ -1,5 +1,6 @@
// "Make '<init>' internal" "false"
// DISABLE-ERRORS
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Introduce import alias
// ACTION: Make 'My' public
+1
View File
@@ -5,6 +5,7 @@
// ACTION: Add '@OptIn(MyExperimentalAPI::class)' annotation to 'foo'
// ACTION: Add '@OptIn(MyExperimentalAPI::class)' annotation to containing class 'Derived'
// ACTION: Add '-Xopt-in=MyExperimentalAPI' to module light_idea_test_case compiler arguments
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: This declaration overrides experimental member of supertype 'Base' and must be annotated with '@MyExperimentalAPI'
@RequiresOptIn
@@ -2,6 +2,7 @@
// TOOL: org.jetbrains.kotlin.idea.inspections.FunctionWithLambdaExpressionBodyInspection
// ACTION: Convert to block body
// ACTION: Convert to run { ... }
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify return type explicitly
@@ -3,6 +3,7 @@
// ACTION: Convert to block body
// ACTION: Convert to run { ... }
// ACTION: Specify explicit lambda signature
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify return type explicitly
fun test(a: Int, b: Int) = <caret>{
@@ -3,6 +3,7 @@
// ACTION: Convert to block body
// ACTION: Convert to multi-line lambda
// ACTION: Convert to run { ... }
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify return type explicitly
@@ -2,6 +2,7 @@
// TOOL: org.jetbrains.kotlin.idea.inspections.FunctionWithLambdaExpressionBodyInspection
// ACTION: Convert to block body
// ACTION: Convert to multi-line lambda
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify return type explicitly
@@ -3,6 +3,7 @@
// ACTION: Convert property getter to initializer
// ACTION: Convert to block body
// ACTION: Convert to run { ... }
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify type explicitly
@@ -3,6 +3,7 @@
// ACTION: Convert property getter to initializer
// ACTION: Convert to block body
// ACTION: Convert to run { ... }
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify type explicitly
@@ -4,6 +4,7 @@
// ACTION: Convert to block body
// ACTION: Convert to multi-line lambda
// ACTION: Convert to run { ... }
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify type explicitly
@@ -3,6 +3,7 @@
// ACTION: Convert property getter to initializer
// ACTION: Convert to block body
// ACTION: Convert to multi-line lambda
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify type explicitly
@@ -2,6 +2,7 @@
// TOOL: org.jetbrains.kotlin.idea.inspections.FunctionWithLambdaExpressionBodyInspection
// ACTION: Convert to block body
// ACTION: Convert to multi-line lambda
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify return type explicitly
@@ -3,6 +3,7 @@
// ACTION: Convert property getter to initializer
// ACTION: Convert to block body
// ACTION: Convert to multi-line lambda
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify explicit lambda signature
// ACTION: Specify explicit lambda signature
// ACTION: Specify type explicitly
@@ -2,6 +2,7 @@
// DISABLE-ERRORS
// ACTION: Convert to secondary constructor
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Make private
// ACTION: Make protected
// ACTION: Make public
@@ -1,6 +1,7 @@
// "Add 'private' modifier" "false"
// ACTION: Convert to secondary constructor
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Move to class body
class My(val <caret>parameter: Int) {
@@ -1,5 +1,6 @@
// "class org.jetbrains.kotlin.idea.quickfix.AddModifierFix" "false"
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Inline type parameter
// ACTION: Introduce import alias
// ACTION: Remove final upper bound
@@ -1,6 +1,7 @@
// "Replace with safe (?.) call" "false"
// ACTION: Add non-null asserted (!!) call
// ACTION: Flip '<='
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Replace overloaded operator with function call
// ERROR: Operator call corresponds to a dot-qualified call 'w?.x.compareTo(42)' which is not allowed on a nullable receiver 'w?.x'.
@@ -2,6 +2,7 @@
// ACTION: Convert function to property
// ACTION: Convert to block body
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Specify return type explicitly
fun foo<caret>() = arrayOf(java.lang.String.valueOf(1))
@@ -5,6 +5,7 @@
// ACTION: Specify type explicitly
// ACTION: Convert to anonymous function
// ACTION: Convert to multi-line lambda
// ACTION: Enable a trailing comma by default in the formatter
// RUNTIME_WITH_FULL_JDK
fun main() {
@@ -4,6 +4,7 @@
// ACTION: Convert to also
// ACTION: Convert to apply
// ACTION: Convert to multi-line lambda
// ACTION: Enable a trailing comma by default in the formatter
fun test() {
val f = { <caret>i: Int -> foo() }
bar(f)
@@ -3,6 +3,7 @@
// ACTION: Convert parameter to receiver
// ACTION: Rename to _
// ACTION: Specify return type explicitly
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put parameters on separate lines
fun foo(block: (String, Int) -> Unit) {
@@ -1,4 +1,5 @@
// "Remove parameter 'x'" "false"
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Move lambda argument into parentheses
// ACTION: Remove explicit lambda parameter types (may break code)
// ACTION: Rename to _
@@ -1,5 +1,6 @@
// "Rename to _" "false"
// ACTION: Convert parameter to receiver
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Remove parameter 'x'
fun foo(x<caret>: Int) {
@@ -3,6 +3,7 @@
// ACTION: Create class 'X'
// ACTION: Create enum 'X'
// ACTION: Create interface 'X'
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Unresolved reference: X
// ERROR: Unresolved reference: X
class A {
@@ -7,6 +7,7 @@
// ACTION: Specify explicit lambda signature
// ACTION: Add return@let
// ACTION: Convert to single-line lambda
// ACTION: Enable a trailing comma by default in the formatter
// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
fun String?.foo(a: String?) {
@@ -2,6 +2,7 @@
// ACTION: Create test
// ACTION: Make primary constructor internal
// ACTION: Make primary constructor private
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Extract 'C' from current file
// ACTION: Rename file to C.kt
@@ -4,6 +4,7 @@
// ACTION: Create class 'NoSuchType'
// ACTION: Create enum 'NoSuchType'
// ACTION: Create interface 'NoSuchType'
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Remove explicit lambda parameter types (may break code)
// ACTION: Create type parameter 'NoSuchType' in function 'foo'
// ERROR: Type mismatch: inferred type is ([ERROR : NoSuchType]) -> Int but Int was expected
+1
View File
@@ -1,6 +1,7 @@
// "Replace array of boxed with array of primitive" "false"
// ERROR: Invalid type of annotation member
// ACTION: Introduce import alias
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Put parameters on one line
annotation class SuperAnnotation(
val foo: <caret>Array<*>,
@@ -1,6 +1,7 @@
// "Replace array of boxed with array of primitive" "false"
// ACTION: Put parameters on one line
// ACTION: Introduce import alias
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Convert to vararg parameter (may break code)
annotation class SuperAnnotation(
val str: <caret>Array<String>
@@ -1,4 +1,5 @@
// "Suppress unused warning if annotated by 'kotlin.Deprecated'" "false"
// ACTION: Create test
// ACTION: Enable a trailing comma by default in the formatter
@Deprecated("")
fun foo<caret>(){}
@@ -4,6 +4,7 @@
// ACTION: Make protected
// ACTION: Create test
// ACTION: Convert to secondary constructor
// ACTION: Enable a trailing comma by default in the formatter
// ACTION: Move to class body
class C(<caret>val x: String) {
}
@@ -16059,6 +16059,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
@TestMetadata("idea/testData/intentions/trailingComma")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class TrailingComma extends AbstractIntentionTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInTrailingComma() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/intentions/trailingComma"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("valueParameterList.kt")
public void testValueParameterList() throws Exception {
runTest("idea/testData/intentions/trailingComma/valueParameterList.kt");
}
}
@TestMetadata("idea/testData/intentions/underscoresInNumericLiteral")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)