diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/JoinDeclarationAndAssignmentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/JoinDeclarationAndAssignmentIntention.kt index 81910e6e710..6d35d5c1503 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/JoinDeclarationAndAssignmentIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/JoinDeclarationAndAssignmentIntention.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.ScrollType +import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.PsiReferenceService import com.intellij.psi.util.PsiTreeUtil @@ -36,13 +37,13 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils class JoinDeclarationAndAssignmentInspection : IntentionBasedInspection( - JoinDeclarationAndAssignmentIntention::class, - "Can be joined with assignment" + JoinDeclarationAndAssignmentIntention::class, + "Can be joined with assignment" ) -class JoinDeclarationAndAssignmentIntention : SelfTargetingOffsetIndependentIntention( - KtProperty::class.java, - "Join declaration and assignment" +class JoinDeclarationAndAssignmentIntention : SelfTargetingRangeIntention( + KtProperty::class.java, + "Join declaration and assignment" ) { private fun equalNullableTypes(type1: KotlinType?, type2: KotlinType?): Boolean { @@ -51,24 +52,25 @@ class JoinDeclarationAndAssignmentIntention : SelfTargetingOffsetIndependentInte return TypeUtils.equalTypes(type1, type2) } - override fun isApplicableTo(element: KtProperty): Boolean { + override fun applicabilityRange(element: KtProperty): TextRange? { if (element.hasDelegate() || element.hasInitializer() || element.setter != null || element.getter != null || element.receiverTypeReference != null || element.name == null) { - return false + return null } - val assignment = findAssignment(element) ?: return false - return assignment.right?.let { - hasNoLocalDependencies(it, element.parent) && - assignment.analyze().let { context -> - (element.isVar && !element.isLocal) || - equalNullableTypes(it.getType(context), context[BindingContext.TYPE, element.typeReference]) - } - } ?: false + val assignment = findAssignment(element) ?: return null + if (assignment.right?.let { + hasNoLocalDependencies(it, element.parent) && assignment.analyze().let { context -> + (element.isVar && !element.isLocal) || + equalNullableTypes(it.getType(context), context[BindingContext.TYPE, element.typeReference]) + } + } != true) return null + + return TextRange((element.modifierList ?: element.valOrVarKeyword).startOffset, (element.typeReference ?: element).endOffset) } override fun applyTo(element: KtProperty, editor: Editor?) { @@ -93,8 +95,7 @@ class JoinDeclarationAndAssignmentIntention : SelfTargetingOffsetIndependentInte val colon = element.colon!! selectionModel.setSelection(colon.startOffset, typeReference.endOffset) moveCaret(typeReference.endOffset, ScrollType.CENTER) - } - else { + } else { moveCaret(newInitializer.startOffset, ScrollType.CENTER) } } @@ -161,6 +162,6 @@ class JoinDeclarationAndAssignmentIntention : SelfTargetingOffsetIndependentInte private fun PsiElement.resolveAllReferences(): Sequence { return PsiReferenceService.getService().getReferences(this, PsiReferenceService.Hints.NO_HINTS) - .asSequence() - .map { it.resolve() } + .asSequence() + .map { it.resolve() } } diff --git a/idea/testData/intentions/joinDeclarationAndAssignment/caretOnHeadComment.kt b/idea/testData/intentions/joinDeclarationAndAssignment/caretOnHeadComment.kt new file mode 100644 index 00000000000..1ff6197eda4 --- /dev/null +++ b/idea/testData/intentions/joinDeclarationAndAssignment/caretOnHeadComment.kt @@ -0,0 +1,8 @@ +// IS_APPLICABLE: false +class Test { + /* foo */ // bar + private val x: Int /* baz */ // qux + init { + x = 1 + } +} \ No newline at end of file diff --git a/idea/testData/intentions/joinDeclarationAndAssignment/caretOnTailComment.kt b/idea/testData/intentions/joinDeclarationAndAssignment/caretOnTailComment.kt new file mode 100644 index 00000000000..a867af98580 --- /dev/null +++ b/idea/testData/intentions/joinDeclarationAndAssignment/caretOnTailComment.kt @@ -0,0 +1,8 @@ +// IS_APPLICABLE: false +class Test { + /* foo */ // bar + private val x: Int /* baz */ // qux + init { + x = 1 + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 9a3eb46d9d3..3559e0301dd 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -9351,6 +9351,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("caretOnHeadComment.kt") + public void testCaretOnHeadComment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinDeclarationAndAssignment/caretOnHeadComment.kt"); + doTest(fileName); + } + + @TestMetadata("caretOnTailComment.kt") + public void testCaretOnTailComment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinDeclarationAndAssignment/caretOnTailComment.kt"); + doTest(fileName); + } + @TestMetadata("comment.kt") public void testComment() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/joinDeclarationAndAssignment/comment.kt");