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:
Valentin Kipyatkov
2015-05-06 13:06:37 +03:00
parent 45c5454e39
commit 07a89b38e1
7 changed files with 69 additions and 25 deletions
@@ -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]
}
}
@@ -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
}
}
@@ -0,0 +1,5 @@
<html>
<body>
This inspection reports an if expression checking variable being null right after initializing it that can be converted into an elvis operator in the initializer
</body>
</html>
@@ -0,0 +1,5 @@
<html>
<body>
This inspection reports any 'when' expression that can be simplified by introducing subject argument
</body>
</html>
+7
View File
@@ -924,6 +924,13 @@
level="WEAK WARNING"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.IntroduceWhenSubjectInspection"
displayName="Introduce argument to 'when'"
groupName="Kotlin"
enabledByDefault="true"
level="WEAK WARNING"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection"
displayName="Unused Symbol"
groupName="Kotlin"
@@ -17,16 +17,17 @@
package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingOffsetIndependentIntention
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.getSubjectToIntroduce
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.introduceSubject
import org.jetbrains.kotlin.psi.JetWhenExpression
public class IntroduceWhenSubjectIntention : JetSelfTargetingOffsetIndependentIntention<JetWhenExpression>(javaClass(), "Introduce argument to 'when'") {
override fun isApplicableTo(element: JetWhenExpression): Boolean {
val subject = element.getSubjectToIntroduce() ?: return false
setText("Introduce '$subject' as argument to 'when'")
return true
public class IntroduceWhenSubjectIntention : JetSelfTargetingRangeIntention<JetWhenExpression>(javaClass(), "Introduce argument to 'when'") {
override fun applicabilityRange(element: JetWhenExpression): TextRange? {
val subject = element.getSubjectToIntroduce() ?: return null
setText("Introduce '${subject.getText()}' as argument to 'when'")
return element.getWhenKeywordElement().getTextRange()
}
override fun applyTo(element: JetWhenExpression, editor: Editor) {
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.intentions.attributeCallReplacements.ReplaceGetIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToElvisIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfThenToSafeAccessIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IntroduceWhenSubjectIntention
import org.jetbrains.kotlin.psi.*
public class ExplicitGetInspection : IntentionBasedInspection<JetDotQualifiedExpression>(ReplaceGetIntention())
@@ -40,3 +41,5 @@ public class SimplifyBinaryNegationInspection : IntentionBasedInspection<JetPref
public class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection<JetBinaryExpression>(ReplaceWithOperatorAssignmentIntention())
public class IntroduceWhenSubjectInspection : IntentionBasedInspection<JetWhenExpression>(IntroduceWhenSubjectIntention())