Smaller availability range for add argument name intention
This commit is contained in:
@@ -216,6 +216,8 @@ public fun PsiElement.getStartOffsetIn(ancestor: PsiElement): Int {
|
||||
return offset
|
||||
}
|
||||
|
||||
public fun TextRange.containsInside(offset: Int): Boolean = getStartOffset() < offset && offset < getEndOffset()
|
||||
|
||||
public val PsiChildRange.textRange: TextRange?
|
||||
get() {
|
||||
if (isEmpty) return null
|
||||
|
||||
+14
-15
@@ -25,14 +25,14 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
|
||||
public abstract class JetSelfTargetingIntention<TElement : JetElement>(
|
||||
public val elementType: Class<TElement>,
|
||||
private var text: String,
|
||||
private val familyName: String = text,
|
||||
private val firstElementOfTypeOnly: Boolean = false
|
||||
private val familyName: String = text
|
||||
) : IntentionAction {
|
||||
|
||||
protected val defaultText: String = text
|
||||
@@ -65,16 +65,17 @@ public abstract class JetSelfTargetingIntention<TElement : JetElement>(
|
||||
elementsToCheck += commonParent.parentsWithSelf
|
||||
}
|
||||
|
||||
val elementsOfType = elementsToCheck.filterIsInstance(elementType)
|
||||
if (firstElementOfTypeOnly) {
|
||||
val candidate = elementsOfType.firstOrNull() ?: return null
|
||||
return if (isApplicableTo(candidate, offset)) candidate else null
|
||||
}
|
||||
else {
|
||||
return elementsOfType.firstOrNull { isApplicableTo(it, offset) }
|
||||
for (element in elementsToCheck) {
|
||||
if (elementType.isInstance(element) && isApplicableTo(element as TElement, offset)) {
|
||||
return element as TElement
|
||||
}
|
||||
if (!allowCaretInsideElement(element) && element.getTextRange().containsInside(offset)) break
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
protected open fun allowCaretInsideElement(element: PsiElement): Boolean = true
|
||||
|
||||
final override fun isAvailable(project: Project, editor: Editor, file: PsiFile)
|
||||
= getTarget(editor, file) != null
|
||||
|
||||
@@ -91,9 +92,8 @@ public abstract class JetSelfTargetingIntention<TElement : JetElement>(
|
||||
public abstract class JetSelfTargetingRangeIntention<TElement : JetElement>(
|
||||
elementType: Class<TElement>,
|
||||
text: String,
|
||||
familyName: String = text,
|
||||
firstElementOfTypeOnly: Boolean = false
|
||||
) : JetSelfTargetingIntention<TElement>(elementType, text, familyName, firstElementOfTypeOnly) {
|
||||
familyName: String = text
|
||||
) : JetSelfTargetingIntention<TElement>(elementType, text, familyName) {
|
||||
|
||||
public abstract fun applicabilityRange(element: TElement): TextRange?
|
||||
|
||||
@@ -106,9 +106,8 @@ public abstract class JetSelfTargetingRangeIntention<TElement : JetElement>(
|
||||
public abstract class JetSelfTargetingOffsetIndependentIntention<TElement : JetElement>(
|
||||
elementType: Class<TElement>,
|
||||
text: String,
|
||||
familyName: String = text,
|
||||
firstElementOfTypeOnly: Boolean = false
|
||||
) : JetSelfTargetingRangeIntention<TElement>(elementType, text, familyName, firstElementOfTypeOnly) {
|
||||
familyName: String = text
|
||||
) : JetSelfTargetingRangeIntention<TElement>(elementType, text, familyName) {
|
||||
|
||||
public abstract fun isApplicableTo(element: TElement): Boolean
|
||||
|
||||
|
||||
@@ -18,11 +18,13 @@ package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.conversion.copy.end
|
||||
import org.jetbrains.kotlin.idea.conversion.copy.start
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus
|
||||
@@ -44,6 +46,9 @@ public class AddNameToArgumentIntention
|
||||
return true
|
||||
}
|
||||
|
||||
override fun allowCaretInsideElement(element: PsiElement)
|
||||
= element !is JetValueArgumentList && element !is JetContainerNode
|
||||
|
||||
override fun applyTo(element: JetValueArgument, editor: Editor) {
|
||||
val name = detectNameToAdd(element)!!
|
||||
val newArgument = JetPsiFactory(element).createArgument(element.getArgumentExpression()!!, name, element.getSpreadElement() != null)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
@@ -25,7 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
|
||||
public class ConvertToBlockBodyIntention : JetSelfTargetingIntention<JetDeclarationWithBody>(
|
||||
javaClass(), "Convert to block body", firstElementOfTypeOnly = true
|
||||
javaClass(), "Convert to block body"
|
||||
) {
|
||||
override fun isApplicableTo(element: JetDeclarationWithBody, caretOffset: Int): Boolean {
|
||||
if (element is JetFunctionLiteral || element.hasBlockBody() || !element.hasBody()) return false
|
||||
@@ -43,6 +44,8 @@ public class ConvertToBlockBodyIntention : JetSelfTargetingIntention<JetDeclarat
|
||||
}
|
||||
}
|
||||
|
||||
override fun allowCaretInsideElement(element: PsiElement) = element !is JetDeclaration
|
||||
|
||||
override fun applyTo(element: JetDeclarationWithBody, editor: Editor) {
|
||||
convert(element)
|
||||
}
|
||||
|
||||
@@ -33,13 +33,15 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
public class ConvertToExpressionBodyIntention : JetSelfTargetingOffsetIndependentIntention<JetDeclarationWithBody>(
|
||||
javaClass(), "Convert to expression body", firstElementOfTypeOnly = true
|
||||
javaClass(), "Convert to expression body"
|
||||
) {
|
||||
override fun isApplicableTo(element: JetDeclarationWithBody): Boolean {
|
||||
val value = calcValue(element)
|
||||
return value != null && !containsReturn(value)
|
||||
}
|
||||
|
||||
override fun allowCaretInsideElement(element: PsiElement) = element !is JetDeclaration
|
||||
|
||||
override fun applyTo(element: JetDeclarationWithBody, editor: Editor) {
|
||||
applyToInternal(element) {
|
||||
val typeRef = it.getTypeReference()!!
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.idea.core.moveInsideParentheses
|
||||
import org.jetbrains.kotlin.psi.JetFunctionLiteralArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
||||
|
||||
public class MoveLambdaInsideParenthesesIntention : JetSelfTargetingIntention<JetFunctionLiteralArgument>(javaClass(), "Move lambda argument into parentheses"), LowPriorityAction {
|
||||
override fun isApplicableTo(element: JetFunctionLiteralArgument, caretOffset: Int): Boolean {
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.intentions
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.psi.JetParenthesizedExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containsInside
|
||||
|
||||
public class RemoveUnnecessaryParenthesesIntention : JetSelfTargetingIntention<JetParenthesizedExpression>(javaClass(), "Remove unnecessary parentheses") {
|
||||
override fun isApplicableTo(element: JetParenthesizedExpression, caretOffset: Int): Boolean {
|
||||
|
||||
@@ -63,8 +63,6 @@ fun JetContainerNode.description(): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun TextRange.containsInside(offset: Int) = getStartOffset() < offset && offset < getEndOffset()
|
||||
|
||||
fun isAutoCreatedItUsage(expression: JetSimpleNameExpression): Boolean {
|
||||
if (expression.getReferencedName() != "it") return false
|
||||
val context = expression.analyze()
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun foo(p: Int){}
|
||||
|
||||
fun bar(list: List<Int>) {
|
||||
foo(list[<caret>1])
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun foo(p: Int){}
|
||||
|
||||
fun bar() {
|
||||
foo("".hashCode(<caret>))
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(p: Int){}
|
||||
|
||||
fun bar() {
|
||||
foo("".hashCode<caret>())
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun foo(p: Int){}
|
||||
|
||||
fun bar() {
|
||||
foo(p = "".hashCode<caret>())
|
||||
}
|
||||
@@ -130,6 +130,24 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notInsideIndices.kt")
|
||||
public void testNotInsideIndices() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/addNameToArgument/notInsideIndices.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notInsideNestedArgumentList.kt")
|
||||
public void testNotInsideNestedArgumentList() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/addNameToArgument/notInsideNestedArgumentList.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notInsideNestedArgumentList2.kt")
|
||||
public void testNotInsideNestedArgumentList2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/addNameToArgument/notInsideNestedArgumentList2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notLast.kt")
|
||||
public void testNotLast() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/addNameToArgument/notLast.kt");
|
||||
|
||||
Reference in New Issue
Block a user