From 3b290ce3ddc034e3070bf1682015351fdf64f610 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Tue, 5 Jul 2016 12:13:14 +0200 Subject: [PATCH] Add quickfix for "Illegal usage of inline parameter" that adds `noinline` (#888) Fixes #KT-12838 --- .../kotlin/idea/quickfix/AddCrossinlineFix.kt | 26 ++++++++++++++----- .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 3 ++- idea/testData/quickfix/addNoinline/basic.kt | 3 +++ .../quickfix/addNoinline/basic.kt.after | 3 +++ .../idea/quickfix/QuickFixTestGenerated.java | 15 +++++++++++ 5 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 idea/testData/quickfix/addNoinline/basic.kt create mode 100644 idea/testData/quickfix/addNoinline/basic.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddCrossinlineFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddCrossinlineFix.kt index ef55ed961d9..376172dd805 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddCrossinlineFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddCrossinlineFix.kt @@ -21,18 +21,22 @@ import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -class AddCrossInlineFix(element: KtNameReferenceExpression) : KotlinQuickFixAction(element) { - override fun getText() = "Add 'crossinline' to parameter '${element.getReferencedName()}'" - override fun getFamilyName() = "Add 'crossinline' to parameter" +class AddInlineModifierFix( + element: KtNameReferenceExpression, + private val modifier: KtModifierKeywordToken +) : KotlinQuickFixAction(element) { + override fun getText() = "Add '${modifier.value}' to parameter '${element.getReferencedName()}'" + override fun getFamilyName() = "Add '${modifier.value}' to parameter" override fun invoke(project: Project, editor: Editor?, file: KtFile) { val parameter = element.findParameterWithName(element.getReferencedName()) ?: return - if (!parameter.hasModifier(KtTokens.CROSSINLINE_KEYWORD)) { - parameter.addModifier(KtTokens.CROSSINLINE_KEYWORD) + if (!parameter.hasModifier(modifier)) { + parameter.addModifier(modifier) } } @@ -41,11 +45,19 @@ class AddCrossInlineFix(element: KtNameReferenceExpression) : KotlinQuickFixActi return function.valueParameters.firstOrNull { it.name == name } ?: function.findParameterWithName(name) } - companion object Factory : KotlinIntentionActionsFactory() { + object CrossInlineFactory : KotlinIntentionActionsFactory() { override fun doCreateActions(diagnostic: Diagnostic): List { val casted = Errors.NON_LOCAL_RETURN_NOT_ALLOWED.cast(diagnostic) val reference = casted.a as? KtNameReferenceExpression ?: return emptyList() - return listOf(AddCrossInlineFix(reference)) + return listOf(AddInlineModifierFix(reference, KtTokens.CROSSINLINE_KEYWORD)) + } + } + + object NoInlineFactory : KotlinIntentionActionsFactory() { + override fun doCreateActions(diagnostic: Diagnostic): List { + val casted = Errors.USAGE_IS_NOT_INLINABLE.cast(diagnostic) + val reference = casted.a as? KtNameReferenceExpression ?: return emptyList() + return listOf(AddInlineModifierFix(reference, KtTokens.NOINLINE_KEYWORD)) } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 668ca51ec2e..b2cd30ee0c6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -390,7 +390,8 @@ class QuickFixRegistrar : QuickFixContributor { DATA_CLASS_NOT_PROPERTY_PARAMETER.registerFactory(AddValVarToConstructorParameterAction.QuickFixFactory) - NON_LOCAL_RETURN_NOT_ALLOWED.registerFactory(AddCrossInlineFix) + NON_LOCAL_RETURN_NOT_ALLOWED.registerFactory(AddInlineModifierFix.CrossInlineFactory) + USAGE_IS_NOT_INLINABLE.registerFactory(AddInlineModifierFix.NoInlineFactory) UNRESOLVED_REFERENCE.registerFactory(MakeConstructorParameterPropertyFix) diff --git a/idea/testData/quickfix/addNoinline/basic.kt b/idea/testData/quickfix/addNoinline/basic.kt new file mode 100644 index 00000000000..d220aba9a50 --- /dev/null +++ b/idea/testData/quickfix/addNoinline/basic.kt @@ -0,0 +1,3 @@ +// "Add 'noinline' to parameter 'block'" "true" + +inline fun foo(block: () -> Unit) = block diff --git a/idea/testData/quickfix/addNoinline/basic.kt.after b/idea/testData/quickfix/addNoinline/basic.kt.after new file mode 100644 index 00000000000..df221ec7c96 --- /dev/null +++ b/idea/testData/quickfix/addNoinline/basic.kt.after @@ -0,0 +1,3 @@ +// "Add 'noinline' to parameter 'block'" "true" + +inline fun foo(noinline block: () -> Unit) = block diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 6fba904f0bf..3e563fc6c3c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -383,6 +383,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/addNoinline") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AddNoinline extends AbstractQuickFixTest { + public void testAllFilesPresentInAddNoinline() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/addNoinline"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); + } + + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/addNoinline/basic.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/addRunBeforeLambda") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)