Intention based intentions: added ability to highlight partial range, used it in new inspection based on IntroduceWhenSubjectIntention + added missing description
This commit is contained in:
+18
-16
@@ -23,15 +23,14 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingOffsetIndependentIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import java.util.*
|
||||
|
||||
public abstract class IntentionBasedInspection<T: JetElement>(
|
||||
protected val intentions: List<JetSelfTargetingOffsetIndependentIntention<T>>,
|
||||
protected val intentions: List<JetSelfTargetingRangeIntention<T>>,
|
||||
protected val elementType: Class<T>
|
||||
) : AbstractKotlinInspection() {
|
||||
constructor(intention: JetSelfTargetingOffsetIndependentIntention<T>): this(listOf(intention), intention.elementType)
|
||||
constructor(intention: JetSelfTargetingRangeIntention<T>): this(listOf(intention), intention.elementType)
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||
return object: PsiElementVisitor() {
|
||||
@@ -42,7 +41,10 @@ public abstract class IntentionBasedInspection<T: JetElement>(
|
||||
val targetElement = element as T
|
||||
|
||||
for (intention in intentions) {
|
||||
if (!intention.isApplicableTo(targetElement)) continue
|
||||
val range = intention.applicabilityRange(targetElement) ?: continue
|
||||
val elementRange = targetElement.getTextRange()
|
||||
assert(range in elementRange, "Wrong applicabilityRange() result for $intention - should be within element's range")
|
||||
val rangeInElement = range.shiftRight(-elementRange.getStartOffset())
|
||||
|
||||
val fix = object: LocalQuickFix {
|
||||
private val text = intention.getText()
|
||||
@@ -59,7 +61,7 @@ public abstract class IntentionBasedInspection<T: JetElement>(
|
||||
}
|
||||
}
|
||||
|
||||
holder.registerProblem(targetElement, intention.getText(), problemHighlightType, fix)
|
||||
holder.registerProblem(targetElement, intention.getText(), problemHighlightType, rangeInElement, fix)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,14 +69,14 @@ public abstract class IntentionBasedInspection<T: JetElement>(
|
||||
|
||||
protected open val problemHighlightType: ProblemHighlightType
|
||||
get() = ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
}
|
||||
|
||||
private fun PsiElement.getOrCreateEditor(): Editor? {
|
||||
val file = getContainingFile()?.getVirtualFile() ?: return null
|
||||
val document = FileDocumentManager.getInstance().getDocument(file) ?: return null
|
||||
|
||||
val editorFactory = EditorFactory.getInstance()!!
|
||||
|
||||
val editors = editorFactory.getEditors(document)
|
||||
return if (editors.isEmpty()) editorFactory.createEditor(document) else editors[0]
|
||||
|
||||
private fun PsiElement.getOrCreateEditor(): Editor? {
|
||||
val file = getContainingFile()?.getVirtualFile() ?: return null
|
||||
val document = FileDocumentManager.getInstance().getDocument(file) ?: return null
|
||||
|
||||
val editorFactory = EditorFactory.getInstance()
|
||||
|
||||
val editors = editorFactory.getEditors(document)
|
||||
return if (editors.isEmpty()) editorFactory.createEditor(document) else editors[0]
|
||||
}
|
||||
}
|
||||
|
||||
+24
-3
@@ -19,12 +19,12 @@ package org.jetbrains.kotlin.idea.intentions
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
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.getParentOfTypesAndPredicate
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
|
||||
public abstract class JetSelfTargetingIntention<TElement : JetElement>(
|
||||
@@ -88,7 +88,7 @@ public abstract class JetSelfTargetingIntention<TElement : JetElement>(
|
||||
override fun toString(): String = getText()
|
||||
}
|
||||
|
||||
public abstract class JetSelfTargetingOffsetIndependentIntention<TElement : JetElement>(
|
||||
public abstract class JetSelfTargetingRangeIntention<TElement : JetElement>(
|
||||
elementType: Class<TElement>,
|
||||
text: String,
|
||||
familyName: String = text,
|
||||
@@ -99,7 +99,28 @@ public abstract class JetSelfTargetingOffsetIndependentIntention<TElement : JetE
|
||||
public constructor(key: String, elementType: Class<TElement>) : this(elementType, JetBundle.message(key), JetBundle.message(key + ".family")) {
|
||||
}
|
||||
|
||||
public abstract fun applicabilityRange(element: TElement): TextRange?
|
||||
|
||||
override final fun isApplicableTo(element: TElement, caretOffset: Int): Boolean {
|
||||
val range = applicabilityRange(element) ?: return false
|
||||
return range.containsOffset(caretOffset)
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class JetSelfTargetingOffsetIndependentIntention<TElement : JetElement>(
|
||||
elementType: Class<TElement>,
|
||||
text: String,
|
||||
familyName: String = text,
|
||||
firstElementOfTypeOnly: Boolean = false
|
||||
) : JetSelfTargetingRangeIntention<TElement>(elementType, text, familyName, firstElementOfTypeOnly) {
|
||||
|
||||
deprecated("Use primary constructor, no need to use i18n")
|
||||
public constructor(key: String, elementType: Class<TElement>) : this(elementType, JetBundle.message(key), JetBundle.message(key + ".family")) {
|
||||
}
|
||||
|
||||
public abstract fun isApplicableTo(element: TElement): Boolean
|
||||
|
||||
override final fun isApplicableTo(element: TElement, caretOffset: Int): Boolean = isApplicableTo(element)
|
||||
override final fun applicabilityRange(element: TElement): TextRange? {
|
||||
return if (isApplicableTo(element)) element.getTextRange() else null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user