Change API in AbstractApplicabilityBasedInspection
Replace all inspectionTarget with inspectionHighlightRangeInElement & change type of element in applyTo from PsiElement to TElement
This commit is contained in:
+4
-6
@@ -20,7 +20,6 @@ import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||
|
||||
@@ -44,7 +43,7 @@ abstract class AbstractApplicabilityBasedInspection<TElement : KtElement>(
|
||||
if (!isApplicable(element)) return
|
||||
|
||||
holder.registerProblemWithoutOfflineInformation(
|
||||
inspectionTarget(element),
|
||||
element,
|
||||
inspectionText(element),
|
||||
isOnTheFly,
|
||||
inspectionHighlightType(element),
|
||||
@@ -55,8 +54,6 @@ abstract class AbstractApplicabilityBasedInspection<TElement : KtElement>(
|
||||
|
||||
open fun inspectionHighlightRangeInElement(element: TElement): TextRange? = null
|
||||
|
||||
open fun inspectionTarget(element: TElement): PsiElement = element
|
||||
|
||||
open fun inspectionHighlightType(element: TElement): ProblemHighlightType = ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
|
||||
abstract fun inspectionText(element: TElement): String
|
||||
@@ -67,7 +64,7 @@ abstract class AbstractApplicabilityBasedInspection<TElement : KtElement>(
|
||||
|
||||
abstract fun isApplicable(element: TElement): Boolean
|
||||
|
||||
abstract fun applyTo(element: PsiElement, project: Project = element.project, editor: Editor? = null)
|
||||
abstract fun applyTo(element: TElement, project: Project = element.project, editor: Editor? = null)
|
||||
|
||||
open val startFixInWriteAction = true
|
||||
|
||||
@@ -75,7 +72,8 @@ abstract class AbstractApplicabilityBasedInspection<TElement : KtElement>(
|
||||
override fun startInWriteAction() = startFixInWriteAction
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val element = descriptor.psiElement
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val element = descriptor.psiElement as TElement
|
||||
applyTo(element, project, element.findExistingEditor())
|
||||
}
|
||||
|
||||
|
||||
@@ -7,17 +7,15 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
|
||||
import org.jetbrains.kotlin.idea.util.nameIdentifierTextRangeInThis
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.util.OperatorChecks
|
||||
|
||||
class AddOperatorModifierInspection : AbstractApplicabilityBasedInspection<KtNamedFunction>(KtNamedFunction::class.java) {
|
||||
override fun inspectionHighlightRangeInElement(element: KtNamedFunction) =
|
||||
element.nameIdentifier?.textRange?.shiftLeft(element.startOffset)
|
||||
override fun inspectionHighlightRangeInElement(element: KtNamedFunction) = element.nameIdentifierTextRangeInThis()
|
||||
|
||||
override fun inspectionText(element: KtNamedFunction) = "Function should have 'operator' modifier"
|
||||
|
||||
@@ -29,8 +27,8 @@ class AddOperatorModifierInspection : AbstractApplicabilityBasedInspection<KtNam
|
||||
return !functionDescriptor.isOperator && OperatorChecks.check(functionDescriptor).isSuccess
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
for (declaration in (element as KtNamedFunction).withExpectedActuals()) {
|
||||
override fun applyTo(element: KtNamedFunction, project: Project, editor: Editor?) {
|
||||
for (declaration in element.withExpectedActuals()) {
|
||||
declaration.addModifier(KtTokens.OPERATOR_KEYWORD)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-15
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
@@ -22,8 +21,8 @@ import org.jetbrains.kotlin.idea.core.moveCaret
|
||||
import org.jetbrains.kotlin.idea.core.unblockDocument
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.textRangeIn
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -38,14 +37,13 @@ import java.util.*
|
||||
class DeprecatedCallableAddReplaceWithInspection : AbstractApplicabilityBasedInspection<KtCallableDeclaration>(
|
||||
KtCallableDeclaration::class.java
|
||||
) {
|
||||
override fun inspectionText(element: KtCallableDeclaration) =
|
||||
"@Deprecated annotation without 'replaceWith' argument"
|
||||
override fun inspectionText(element: KtCallableDeclaration) = "@Deprecated annotation without 'replaceWith' argument"
|
||||
|
||||
override fun inspectionTarget(element: KtCallableDeclaration): KtAnnotationEntry =
|
||||
element.annotationEntries.first { it.shortName == DEPRECATED_NAME }
|
||||
override fun inspectionHighlightRangeInElement(element: KtCallableDeclaration) = element.annotationEntries.first {
|
||||
it.shortName == DEPRECATED_NAME
|
||||
}.textRangeIn(element)
|
||||
|
||||
override val defaultFixText =
|
||||
"Add 'replaceWith' argument to specify replacement pattern"
|
||||
override val defaultFixText = "Add 'replaceWith' argument to specify replacement pattern"
|
||||
|
||||
private class ReplaceWith(val expression: String, vararg val imports: String)
|
||||
|
||||
@@ -54,14 +52,13 @@ class DeprecatedCallableAddReplaceWithInspection : AbstractApplicabilityBasedIns
|
||||
return element.suggestReplaceWith() != null
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val declaration = element.getParentOfType<KtCallableDeclaration>(strict = true) ?: return
|
||||
val replaceWith = declaration.suggestReplaceWith()!!
|
||||
override fun applyTo(element: KtCallableDeclaration, project: Project, editor: Editor?) {
|
||||
val replaceWith = element.suggestReplaceWith()!!
|
||||
|
||||
assert('\n' !in replaceWith.expression && '\r' !in replaceWith.expression) { "Formatted expression text should not contain \\n or \\r" }
|
||||
|
||||
val annotationEntry = declaration.deprecatedAnnotationWithNoReplaceWith()!!
|
||||
val psiFactory = KtPsiFactory(declaration)
|
||||
val annotationEntry = element.deprecatedAnnotationWithNoReplaceWith()!!
|
||||
val psiFactory = KtPsiFactory(element)
|
||||
|
||||
var escapedText = replaceWith.expression.replace("\\", "\\\\").replace("\"", "\\\"")
|
||||
|
||||
@@ -212,8 +209,8 @@ class DeprecatedCallableAddReplaceWithInspection : AbstractApplicabilityBasedIns
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
val bindingContext = expression.analyze()
|
||||
val target = bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, expression]
|
||||
?: bindingContext[BindingContext.REFERENCE_TARGET, expression]
|
||||
?: return
|
||||
?: bindingContext[BindingContext.REFERENCE_TARGET, expression]
|
||||
?: return
|
||||
if (target.isExtension || expression.getReceiverExpression() == null) {
|
||||
val fqName = target.importableFqName ?: return
|
||||
if (!importHelper.isImportedWithDefault(ImportPath(fqName, false), file)
|
||||
|
||||
+5
-7
@@ -22,14 +22,13 @@ import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.core.setType
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.elvisPattern
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.expressionComparedToNull
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.fromIfKeywordToRightParenthesisTextRangeInThis
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.shouldBeTransformed
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.textRange
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
@@ -43,16 +42,15 @@ class FoldInitializerAndIfToElvisInspection : AbstractApplicabilityBasedInspecti
|
||||
|
||||
override val defaultFixText: String = "Replace 'if' with elvis operator"
|
||||
|
||||
override fun inspectionHighlightRangeInElement(element: KtIfExpression): TextRange? = element.textRange().shiftLeft(element.startOffset)
|
||||
override fun inspectionHighlightRangeInElement(element: KtIfExpression) = element.fromIfKeywordToRightParenthesisTextRangeInThis()
|
||||
|
||||
override fun inspectionHighlightType(element: KtIfExpression): ProblemHighlightType =
|
||||
if (element.shouldBeTransformed()) ProblemHighlightType.GENERIC_ERROR_OR_WARNING else ProblemHighlightType.INFORMATION
|
||||
|
||||
override fun isApplicable(element: KtIfExpression): Boolean = Companion.isApplicable(element)
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val newElvis = Companion.applyTo(element as KtIfExpression)
|
||||
editor?.caretModel?.moveToOffset(newElvis.right!!.textOffset)
|
||||
override fun applyTo(element: KtIfExpression, project: Project, editor: Editor?) {
|
||||
Companion.applyTo(element).right?.textOffset?.let { editor?.caretModel?.moveToOffset(it) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -62,7 +60,7 @@ class FoldInitializerAndIfToElvisInspection : AbstractApplicabilityBasedInspecti
|
||||
val type = data.ifNullExpression.analyze().getType(data.ifNullExpression) ?: return null
|
||||
if (!type.isNothing()) return null
|
||||
|
||||
return element.textRange()
|
||||
return element.fromIfKeywordToRightParenthesisTextRangeInThis()
|
||||
}
|
||||
|
||||
fun isApplicable(element: KtIfExpression): Boolean = applicabilityRange(element) != null
|
||||
|
||||
@@ -5,20 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.getLastLambdaExpression
|
||||
import org.jetbrains.kotlin.idea.inspections.collections.isMap
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.util.calleeTextRangeInThis
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
@@ -41,16 +40,14 @@ class JavaMapForEachInspection : AbstractApplicabilityBasedInspection<KtDotQuali
|
||||
return resolvedCall.isResolvedWithSamConversions()
|
||||
}
|
||||
|
||||
override fun inspectionTarget(element: KtDotQualifiedExpression) = element.callExpression?.calleeExpression ?: element
|
||||
override fun inspectionHighlightRangeInElement(element: KtDotQualifiedExpression): TextRange? = element.calleeTextRangeInThis()
|
||||
|
||||
override fun inspectionText(element: KtDotQualifiedExpression) = "Java Map.forEach method call should be replaced with Kotlin's forEach"
|
||||
|
||||
override fun inspectionHighlightType(element: KtDotQualifiedExpression) = ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
|
||||
override val defaultFixText = "Replace with Kotlin's forEach"
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val call = element.getStrictParentOfType<KtCallExpression>() ?: return
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val call = element.callExpression ?: return
|
||||
val lambda = call.lambda() ?: return
|
||||
val valueParameters = lambda.valueParameters
|
||||
lambda.functionLiteral.valueParameterList?.replace(
|
||||
|
||||
+7
-11
@@ -8,14 +8,12 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses
|
||||
import org.jetbrains.kotlin.idea.core.getLastLambdaExpression
|
||||
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
|
||||
import org.jetbrains.kotlin.idea.util.textRangeIn
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.unpackFunctionLiteral
|
||||
|
||||
@@ -36,19 +34,17 @@ class MoveLambdaOutsideParenthesesInspection : AbstractApplicabilityBasedInspect
|
||||
|
||||
override fun isApplicable(element: KtCallExpression) = element.canMoveLambdaOutsideParentheses()
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element.getParentOfType<KtCallExpression>(strict = false) ?: return
|
||||
|
||||
if (expression.canMoveLambdaOutsideParentheses()) {
|
||||
expression.moveFunctionLiteralOutsideParentheses()
|
||||
override fun applyTo(element: KtCallExpression, project: Project, editor: Editor?) {
|
||||
if (element.canMoveLambdaOutsideParentheses()) {
|
||||
element.moveFunctionLiteralOutsideParentheses()
|
||||
}
|
||||
}
|
||||
|
||||
override fun inspectionText(element: KtCallExpression) = "Lambda argument ${element.verb} be moved out of parentheses"
|
||||
|
||||
override fun inspectionTarget(element: KtCallExpression): KtElement {
|
||||
return element.getLastLambdaExpression()?.getStrictParentOfType<KtValueArgument>()?.asElement() ?: element
|
||||
}
|
||||
override fun inspectionHighlightRangeInElement(element: KtCallExpression) = element.getLastLambdaExpression()
|
||||
?.getStrictParentOfType<KtValueArgument>()?.asElement()
|
||||
?.textRangeIn(element)
|
||||
|
||||
override val defaultFixText = "Move lambda argument out of parentheses"
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class NullableBooleanElvisInspection : AbstractKotlinInspection(), CleanupLocalI
|
||||
val prefixExpression = equalityCheckExpression.getParentOfType<KtPrefixExpression>(strict = true) ?: return
|
||||
val simplifier = SimplifyNegatedBinaryExpressionInspection()
|
||||
if (simplifier.isApplicable(prefixExpression)) {
|
||||
simplifier.applyTo(prefixExpression.operationReference)
|
||||
simplifier.applyTo(prefixExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.core.canDropBraces
|
||||
import org.jetbrains.kotlin.idea.core.dropBraces
|
||||
import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry
|
||||
@@ -20,7 +19,7 @@ class RemoveCurlyBracesFromTemplateInspection :
|
||||
|
||||
override fun isApplicable(element: KtBlockStringTemplateEntry): Boolean = element.canDropBraces()
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
(element as KtBlockStringTemplateEntry).dropBraces()
|
||||
override fun applyTo(element: KtBlockStringTemplateEntry, project: Project, editor: Editor?) {
|
||||
element.dropBraces()
|
||||
}
|
||||
}
|
||||
|
||||
+9
-11
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.intentions.resolvedToArrayType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -28,24 +27,23 @@ import org.jetbrains.kotlin.psi.createExpressionByPattern
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
|
||||
class ReplaceArrayEqualityOpWithArraysEqualsInspection : AbstractApplicabilityBasedInspection<KtBinaryExpression>(
|
||||
KtBinaryExpression::class.java
|
||||
KtBinaryExpression::class.java
|
||||
) {
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element as? KtBinaryExpression ?: return
|
||||
val right = expression.right ?: return
|
||||
val left = expression.left ?: return
|
||||
override fun applyTo(element: KtBinaryExpression, project: Project, editor: Editor?) {
|
||||
val right = element.right ?: return
|
||||
val left = element.left ?: return
|
||||
val factory = KtPsiFactory(project)
|
||||
val template = buildString {
|
||||
if (expression.operationToken == KtTokens.EXCLEQ) append("!")
|
||||
if (element.operationToken == KtTokens.EXCLEQ) append("!")
|
||||
append("$0.contentEquals($1)")
|
||||
}
|
||||
expression.replace(factory.createExpressionByPattern(template, left, right))
|
||||
element.replace(factory.createExpressionByPattern(template, left, right))
|
||||
}
|
||||
|
||||
override fun isApplicable(element: KtBinaryExpression): Boolean {
|
||||
val operationToken = element.operationToken
|
||||
when (operationToken) {
|
||||
KtTokens.EQEQ, KtTokens.EXCLEQ -> {}
|
||||
when (element.operationToken) {
|
||||
KtTokens.EQEQ, KtTokens.EXCLEQ -> {
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
val right = element.right
|
||||
|
||||
+8
-10
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
import com.intellij.codeInsight.actions.OptimizeImportsProcessor
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
@@ -39,21 +38,20 @@ class ReplaceAssertBooleanWithAssertEqualityInspection : AbstractApplicabilityBa
|
||||
return (element.replaceableAssertion() != null)
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element as? KtCallExpression ?: return
|
||||
val valueArguments = expression.valueArguments
|
||||
override fun applyTo(element: KtCallExpression, project: Project, editor: Editor?) {
|
||||
val valueArguments = element.valueArguments
|
||||
val condition = valueArguments.firstOrNull()?.getArgumentExpression() as? KtBinaryExpression ?: return
|
||||
val left = condition.left ?: return
|
||||
val right = condition.right ?: return
|
||||
val assertion = expression.replaceableAssertion() ?: return
|
||||
val assertion = element.replaceableAssertion() ?: return
|
||||
|
||||
val file = expression.containingKtFile
|
||||
val file = element.containingKtFile
|
||||
val factory = KtPsiFactory(project)
|
||||
val replaced = if (valueArguments.size == 2) {
|
||||
val message = valueArguments[1].getArgumentExpression() ?: return
|
||||
expression.replaced(factory.createExpressionByPattern("$assertion($0, $1, $2)", left, right, message))
|
||||
element.replaced(factory.createExpressionByPattern("$assertion($0, $1, $2)", left, right, message))
|
||||
} else {
|
||||
expression.replaced(factory.createExpressionByPattern("$assertion($0, $1)", left, right))
|
||||
element.replaced(factory.createExpressionByPattern("$assertion($0, $1)", left, right))
|
||||
}
|
||||
ShortenReferences.DEFAULT.process(replaced)
|
||||
OptimizeImportsProcessor(project, file).run()
|
||||
@@ -79,11 +77,11 @@ class ReplaceAssertBooleanWithAssertEqualityInspection : AbstractApplicabilityBa
|
||||
|
||||
return assertionMap[Pair(referencedName, operationToken)]
|
||||
}
|
||||
|
||||
|
||||
private fun KtExpression.descriptor(context: BindingContext): CallableDescriptor? {
|
||||
return getResolvedCall(context)?.resultingDescriptor
|
||||
}
|
||||
|
||||
|
||||
private fun KtExpression.type(context: BindingContext): KotlinType? {
|
||||
return descriptor(context)?.returnType
|
||||
}
|
||||
|
||||
+7
-9
@@ -18,15 +18,14 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.util.calleeTextRangeInThis
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
@@ -63,26 +62,25 @@ class ReplacePutWithAssignmentInspection : AbstractApplicabilityBasedInspection<
|
||||
return receiverClass.isSubclassOf(DefaultBuiltIns.Instance.mutableMap)
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element.getParentOfType<KtDotQualifiedExpression>(strict = false) ?: return
|
||||
val valueArguments = expression.callExpression?.valueArguments ?: return
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val valueArguments = element.callExpression?.valueArguments ?: return
|
||||
val firstArg = valueArguments[0]?.getArgumentExpression() ?: return
|
||||
val secondArg = valueArguments[1]?.getArgumentExpression() ?: return
|
||||
val label = if (secondArg is KtLambdaExpression) {
|
||||
val returnLabel = secondArg.findDescendantOfType<KtReturnExpression>()?.getLabelName()
|
||||
compatibleNames.firstOrNull { it == returnLabel }?.plus("@") ?: ""
|
||||
} else ""
|
||||
expression.replace(
|
||||
KtPsiFactory(expression).createExpressionByPattern(
|
||||
element.replace(
|
||||
KtPsiFactory(element).createExpressionByPattern(
|
||||
"$0[$1] = $label$2",
|
||||
expression.receiverExpression,
|
||||
element.receiverExpression,
|
||||
firstArg,
|
||||
secondArg
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun inspectionTarget(element: KtDotQualifiedExpression) = element.callExpression?.calleeExpression ?: element
|
||||
override fun inspectionHighlightRangeInElement(element: KtDotQualifiedExpression) = element.calleeTextRangeInThis()
|
||||
|
||||
override fun inspectionText(element: KtDotQualifiedExpression): String = "map.put() should be converted to assignment"
|
||||
|
||||
|
||||
+2
-7
@@ -7,13 +7,11 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.intentions.isToString
|
||||
import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
|
||||
class ReplaceToStringWithStringTemplateInspection : AbstractApplicabilityBasedInspection<KtDotQualifiedExpression>(
|
||||
KtDotQualifiedExpression::class.java
|
||||
@@ -24,15 +22,12 @@ class ReplaceToStringWithStringTemplateInspection : AbstractApplicabilityBasedIn
|
||||
return element.isToString()
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element.getParentOfType<KtDotQualifiedExpression>(strict = false) ?: return
|
||||
val variable = expression.receiverExpression.text
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val variable = element.receiverExpression.text
|
||||
element.replace(KtPsiFactory(element).createExpression("\"$$variable\""))
|
||||
}
|
||||
|
||||
override fun inspectionText(element: KtDotQualifiedExpression) = "Call of 'toString' could be replaced with string template"
|
||||
|
||||
override fun inspectionTarget(element: KtDotQualifiedExpression) = element
|
||||
|
||||
override val defaultFixText = "Replace 'toString' with string template"
|
||||
}
|
||||
+2
-3
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -115,8 +114,8 @@ class ReplaceWithOperatorAssignmentInspection : AbstractApplicabilityBasedInspec
|
||||
operationToken == KtTokens.DIV ||
|
||||
operationToken == KtTokens.PERC
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
(element as? KtBinaryExpression)?.replace(buildOperatorAssignment(element))
|
||||
override fun applyTo(element: KtBinaryExpression, project: Project, editor: Editor?) {
|
||||
element.replace(buildOperatorAssignment(element))
|
||||
}
|
||||
|
||||
private fun buildOperatorAssignment(element: KtBinaryExpression): KtBinaryExpression {
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
import com.intellij.codeInsight.CodeInsightUtilCore
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
@@ -69,35 +68,34 @@ class SimplifyAssertNotNullInspection : AbstractApplicabilityBasedInspection<KtC
|
||||
override fun fixText(element: KtCallExpression): String {
|
||||
return if (element.valueArguments.size == 1) {
|
||||
"Replace with '!!' operator"
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
"Replace with '?: error(...)'"
|
||||
}
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element as? KtCallExpression ?: return
|
||||
val declaration = findVariableDeclaration(expression)!!
|
||||
val initializer = declaration.initializer!!
|
||||
val message = extractMessage(expression)
|
||||
override fun applyTo(element: KtCallExpression, project: Project, editor: Editor?) {
|
||||
val declaration = findVariableDeclaration(element) ?: return
|
||||
val initializer = declaration.initializer ?: return
|
||||
val message = extractMessage(element)
|
||||
|
||||
val commentSaver = CommentSaver(expression)
|
||||
val commentSaver = CommentSaver(element)
|
||||
|
||||
if (message == null) {
|
||||
val newInitializer = KtPsiFactory(expression).createExpressionByPattern("$0!!", initializer)
|
||||
val newInitializer = KtPsiFactory(element).createExpressionByPattern("$0!!", initializer)
|
||||
initializer.replace(newInitializer)
|
||||
}
|
||||
else {
|
||||
val newInitializer = KtPsiFactory(expression).createExpressionByPattern("$0 ?: kotlin.error($1)", initializer, message)
|
||||
} else {
|
||||
val newInitializer = KtPsiFactory(element).createExpressionByPattern("$0 ?: kotlin.error($1)", initializer, message)
|
||||
val result = initializer.replace(newInitializer)
|
||||
|
||||
val qualifiedExpression = (result as KtBinaryExpression).right as KtDotQualifiedExpression
|
||||
ShortenReferences.DEFAULT.process(expression.containingKtFile,
|
||||
qualifiedExpression.startOffset,
|
||||
(qualifiedExpression.selectorExpression as KtCallExpression).calleeExpression!!.endOffset)
|
||||
ShortenReferences.DEFAULT.process(
|
||||
element.containingKtFile,
|
||||
qualifiedExpression.startOffset,
|
||||
(qualifiedExpression.selectorExpression as KtCallExpression).calleeExpression!!.endOffset
|
||||
)
|
||||
}
|
||||
|
||||
expression.delete()
|
||||
element.delete()
|
||||
|
||||
commentSaver.restore(declaration)
|
||||
|
||||
@@ -120,8 +118,8 @@ class SimplifyAssertNotNullInspection : AbstractApplicabilityBasedInspection<KtC
|
||||
val arguments = element.valueArguments
|
||||
if (arguments.size != 2) return null
|
||||
return (arguments[1].getArgumentExpression() as? KtLambdaExpression)
|
||||
?.bodyExpression
|
||||
?.statements
|
||||
?.singleOrNull()
|
||||
?.bodyExpression
|
||||
?.statements
|
||||
?.singleOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -18,15 +18,13 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.idea.util.textRangeIn
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInspection<KtPrefixExpression>(
|
||||
KtPrefixExpression::class.java
|
||||
) {
|
||||
class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInspection<KtPrefixExpression>(KtPrefixExpression::class.java) {
|
||||
|
||||
private fun IElementType.negate(): KtSingleValueToken? = when (this) {
|
||||
KtTokens.IN_KEYWORD -> KtTokens.NOT_IN
|
||||
@@ -47,7 +45,7 @@ class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInsp
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun inspectionTarget(element: KtPrefixExpression) = element.operationReference
|
||||
override fun inspectionHighlightRangeInElement(element: KtPrefixExpression) = element.operationReference.textRangeIn(element)
|
||||
|
||||
override fun inspectionText(element: KtPrefixExpression) = "Negated operation should be simplified"
|
||||
|
||||
@@ -73,9 +71,8 @@ class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInsp
|
||||
return (expression.operationReference.getReferencedNameElementType() as? KtSingleValueToken)?.negate() != null
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val prefixExpression = element.parent as? KtPrefixExpression ?: return
|
||||
val expression = KtPsiUtil.deparenthesize(prefixExpression.baseExpression) ?: return
|
||||
override fun applyTo(element: KtPrefixExpression, project: Project, editor: Editor?) {
|
||||
val expression = KtPsiUtil.deparenthesize(element.baseExpression) ?: return
|
||||
val operation = (expression as KtOperationExpression).operationReference.getReferencedNameElementType().negate()?.value ?: return
|
||||
|
||||
val psiFactory = KtPsiFactory(expression)
|
||||
@@ -87,6 +84,6 @@ class SimplifyNegatedBinaryExpressionInspection : AbstractApplicabilityBasedInsp
|
||||
else ->
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
prefixExpression.replace(newExpression)
|
||||
element.replace(newExpression)
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -27,9 +26,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
|
||||
import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler
|
||||
import org.jetbrains.kotlin.idea.util.nameIdentifierTextRangeInThis
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET
|
||||
@@ -40,7 +39,7 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection<KtPro
|
||||
|
||||
override fun isApplicable(element: KtProperty) = statusFor(element) != null
|
||||
|
||||
override fun inspectionTarget(element: KtProperty) = element.nameIdentifier ?: element
|
||||
override fun inspectionHighlightRangeInElement(element: KtProperty) = element.nameIdentifierTextRangeInThis()
|
||||
|
||||
override fun inspectionText(element: KtProperty) = when (statusFor(element)) {
|
||||
Status.RETURN_ONLY ->
|
||||
@@ -54,9 +53,8 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection<KtPro
|
||||
|
||||
override val startFixInWriteAction = false
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val property = element.getParentOfType<KtProperty>(strict = false) ?: return
|
||||
KotlinInlineValHandler(withPrompt = false).inlineElement(project, editor, property)
|
||||
override fun applyTo(element: KtProperty, project: Project, editor: Editor?) {
|
||||
KotlinInlineValHandler(withPrompt = false).inlineElement(project, editor, element)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -72,7 +70,7 @@ class UnnecessaryVariableInspection : AbstractApplicabilityBasedInspection<KtPro
|
||||
fun isExactCopy(): Boolean {
|
||||
if (!property.isVar && initializer is KtNameReferenceExpression && property.typeReference == null) {
|
||||
val initializerDescriptor = initializer.resolveToCall(BodyResolveMode.FULL)?.resultingDescriptor as? VariableDescriptor
|
||||
?: return false
|
||||
?: return false
|
||||
if (initializerDescriptor.isVar) return false
|
||||
if (initializerDescriptor.containingDeclaration !is FunctionDescriptor) return false
|
||||
|
||||
|
||||
+3
-9
@@ -10,8 +10,6 @@ import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
@@ -21,7 +19,6 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.*
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
@@ -42,14 +39,11 @@ class IfThenToElvisInspection(
|
||||
else
|
||||
ProblemHighlightType.INFORMATION
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
convert(
|
||||
element as KtIfExpression,
|
||||
editor
|
||||
)
|
||||
override fun applyTo(element: KtIfExpression, project: Project, editor: Editor?) {
|
||||
convert(element, editor)
|
||||
}
|
||||
|
||||
override fun inspectionHighlightRangeInElement(element: KtIfExpression): TextRange? = element.textRange().shiftLeft(element.startOffset)
|
||||
override fun inspectionHighlightRangeInElement(element: KtIfExpression) = element.fromIfKeywordToRightParenthesisTextRangeInThis()
|
||||
|
||||
override fun createOptionsPanel(): JComponent? = MultipleCheckboxOptionsPanel(this).also {
|
||||
it.addCheckbox("Report also on statement", "highlightStatement")
|
||||
|
||||
+3
-5
@@ -19,9 +19,7 @@ package org.jetbrains.kotlin.idea.inspections.branchedTransformations
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.core.replaced
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspection
|
||||
@@ -40,7 +38,7 @@ class IfThenToSafeAccessInspection : AbstractApplicabilityBasedInspection<KtIfEx
|
||||
|
||||
override fun isApplicable(element: KtIfExpression): Boolean = isApplicableTo(element, expressionShouldBeStable = true)
|
||||
|
||||
override fun inspectionHighlightRangeInElement(element: KtIfExpression): TextRange? = element.textRange().shiftLeft(element.startOffset)
|
||||
override fun inspectionHighlightRangeInElement(element: KtIfExpression) = element.fromIfKeywordToRightParenthesisTextRangeInThis()
|
||||
|
||||
override fun inspectionText(element: KtIfExpression) = "Foldable if-then"
|
||||
|
||||
@@ -53,8 +51,8 @@ class IfThenToSafeAccessInspection : AbstractApplicabilityBasedInspection<KtIfEx
|
||||
|
||||
override val startFixInWriteAction = false
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
convert(element as KtIfExpression, editor)
|
||||
override fun applyTo(element: KtIfExpression, project: Project, editor: Editor?) {
|
||||
convert(element, editor)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+4
-5
@@ -18,18 +18,17 @@ package org.jetbrains.kotlin.idea.inspections.branchedTransformations
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspection
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.getSubjectToIntroduce
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.introduceSubject
|
||||
import org.jetbrains.kotlin.idea.util.textRangeIn
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
|
||||
class IntroduceWhenSubjectInspection : AbstractApplicabilityBasedInspection<KtWhenExpression>(KtWhenExpression::class.java) {
|
||||
|
||||
override fun isApplicable(element: KtWhenExpression) = element.getSubjectToIntroduce() != null
|
||||
|
||||
override fun inspectionTarget(element: KtWhenExpression) = element.whenKeyword
|
||||
override fun inspectionHighlightRangeInElement(element: KtWhenExpression) = element.whenKeyword.textRangeIn(element)
|
||||
|
||||
override fun inspectionText(element: KtWhenExpression) = "'when' with subject should be used"
|
||||
|
||||
@@ -40,7 +39,7 @@ class IntroduceWhenSubjectInspection : AbstractApplicabilityBasedInspection<KtWh
|
||||
return "Introduce '${subject.text}' as subject of 'when'"
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
element.getParentOfType<KtWhenExpression>(strict = true)?.introduceSubject()
|
||||
override fun applyTo(element: KtWhenExpression, project: Project, editor: Editor?) {
|
||||
element.introduceSubject()
|
||||
}
|
||||
}
|
||||
|
||||
+10
-11
@@ -35,11 +35,12 @@ import org.jetbrains.kotlin.idea.intentions.isReceiverExpressionWithValue
|
||||
import org.jetbrains.kotlin.idea.intentions.toResolvedCall
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.project.platform
|
||||
import org.jetbrains.kotlin.idea.util.calleeTextRangeInThis
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.platform.js.isJs
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getFirstArgumentExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
@@ -47,7 +48,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.getKotlinTypeWithPossibleSmartCastToFP
|
||||
import org.jetbrains.kotlin.platform.js.isJs
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
@@ -82,7 +82,7 @@ class ReplaceCallWithBinaryOperatorInspection : AbstractApplicabilityBasedInspec
|
||||
return element.isReceiverExpressionWithValue()
|
||||
}
|
||||
|
||||
override fun inspectionTarget(element: KtDotQualifiedExpression) = element.callExpression?.calleeExpression ?: element
|
||||
override fun inspectionHighlightRangeInElement(element: KtDotQualifiedExpression) = element.calleeTextRangeInThis()
|
||||
|
||||
override fun inspectionHighlightType(element: KtDotQualifiedExpression): ProblemHighlightType {
|
||||
val calleeExpression = element.callExpression?.calleeExpression as? KtSimpleNameExpression
|
||||
@@ -118,28 +118,27 @@ class ReplaceCallWithBinaryOperatorInspection : AbstractApplicabilityBasedInspec
|
||||
return "Replace with '${operation.value}'"
|
||||
}
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val qualifiedExpression = element.getParentOfType<KtDotQualifiedExpression>(strict = false) ?: return
|
||||
val callExpression = qualifiedExpression.callExpression ?: return
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val callExpression = element.callExpression ?: return
|
||||
val operation = operation(callExpression.calleeExpression as? KtSimpleNameExpression ?: return) ?: return
|
||||
val argument = callExpression.valueArguments.single().getArgumentExpression() ?: return
|
||||
val receiver = qualifiedExpression.receiverExpression
|
||||
val receiver = element.receiverExpression
|
||||
|
||||
val factory = KtPsiFactory(qualifiedExpression)
|
||||
val factory = KtPsiFactory(element)
|
||||
when (operation) {
|
||||
KtTokens.EXCLEQ -> {
|
||||
val prefixExpression = qualifiedExpression.getWrappingPrefixExpressionIfAny() ?: return
|
||||
val prefixExpression = element.getWrappingPrefixExpressionIfAny() ?: return
|
||||
val newExpression = factory.createExpressionByPattern("$0 != $1", receiver, argument)
|
||||
prefixExpression.replace(newExpression)
|
||||
}
|
||||
in OperatorConventions.COMPARISON_OPERATIONS -> {
|
||||
val binaryParent = qualifiedExpression.parent as? KtBinaryExpression ?: return
|
||||
val binaryParent = element.parent as? KtBinaryExpression ?: return
|
||||
val newExpression = factory.createExpressionByPattern("$0 ${operation.value} $1", receiver, argument)
|
||||
binaryParent.replace(newExpression)
|
||||
}
|
||||
else -> {
|
||||
val newExpression = factory.createExpressionByPattern("$0 ${operation.value} $1", receiver, argument)
|
||||
qualifiedExpression.replace(newExpression)
|
||||
element.replace(newExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-18
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspectio
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.isReceiverExpressionWithValue
|
||||
import org.jetbrains.kotlin.idea.intentions.toResolvedCall
|
||||
import org.jetbrains.kotlin.idea.util.calleeTextRangeInThis
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
@@ -39,7 +40,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.util.isValidOperator
|
||||
|
||||
class ReplaceGetOrSetInspection : AbstractApplicabilityBasedInspection<KtDotQualifiedExpression>(
|
||||
KtDotQualifiedExpression::class.java
|
||||
KtDotQualifiedExpression::class.java
|
||||
) {
|
||||
private fun FunctionDescriptor.isExplicitOperator(): Boolean {
|
||||
return if (overriddenDescriptors.isEmpty())
|
||||
@@ -75,10 +76,9 @@ class ReplaceGetOrSetInspection : AbstractApplicabilityBasedInspection<KtDotQual
|
||||
override fun inspectionText(element: KtDotQualifiedExpression) = "Should be replaced with indexing"
|
||||
|
||||
override fun inspectionHighlightType(element: KtDotQualifiedExpression): ProblemHighlightType {
|
||||
return if ((element.toResolvedCall(BodyResolveMode.PARTIAL)!!.resultingDescriptor as FunctionDescriptor).isExplicitOperator()) {
|
||||
return if ((element.toResolvedCall(BodyResolveMode.PARTIAL)?.resultingDescriptor as? FunctionDescriptor)?.isExplicitOperator() == true) {
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ProblemHighlightType.INFORMATION
|
||||
}
|
||||
}
|
||||
@@ -92,16 +92,15 @@ class ReplaceGetOrSetInspection : AbstractApplicabilityBasedInspection<KtDotQual
|
||||
return "Replace '${resolvedCall.resultingDescriptor.name.asString()}' call with indexing operator"
|
||||
}
|
||||
|
||||
override fun inspectionTarget(element: KtDotQualifiedExpression) = element.callExpression?.calleeExpression ?: element
|
||||
override fun inspectionHighlightRangeInElement(element: KtDotQualifiedExpression) = element.calleeTextRangeInThis()
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
val expression = element as? KtDotQualifiedExpression ?: element.parent.parent as? KtDotQualifiedExpression ?: return
|
||||
val isSet = expression.toResolvedCall(BodyResolveMode.PARTIAL)!!.resultingDescriptor.name == OperatorNameConventions.SET
|
||||
val allArguments = expression.callExpression!!.valueArguments
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val isSet = element.toResolvedCall(BodyResolveMode.PARTIAL)?.resultingDescriptor?.name == OperatorNameConventions.SET
|
||||
val allArguments = element.callExpression!!.valueArguments
|
||||
assert(allArguments.isNotEmpty())
|
||||
|
||||
val newExpression = KtPsiFactory(expression).buildExpression {
|
||||
appendExpression(expression.receiverExpression)
|
||||
val newExpression = KtPsiFactory(element).buildExpression {
|
||||
appendExpression(element.receiverExpression)
|
||||
|
||||
appendFixedText("[")
|
||||
|
||||
@@ -116,7 +115,7 @@ class ReplaceGetOrSetInspection : AbstractApplicabilityBasedInspection<KtDotQual
|
||||
}
|
||||
}
|
||||
|
||||
val newElement = expression.replace(newExpression)
|
||||
val newElement = element.replace(newExpression)
|
||||
|
||||
if (editor != null) {
|
||||
moveCaret(editor, isSet, newElement)
|
||||
@@ -125,12 +124,11 @@ class ReplaceGetOrSetInspection : AbstractApplicabilityBasedInspection<KtDotQual
|
||||
|
||||
private fun moveCaret(editor: Editor, isSet: Boolean, newElement: PsiElement) {
|
||||
val arrayAccessExpression = if (isSet) {
|
||||
newElement.getChildOfType<KtArrayAccessExpression>()!!
|
||||
}
|
||||
else {
|
||||
newElement as KtArrayAccessExpression
|
||||
}
|
||||
newElement.getChildOfType()
|
||||
} else {
|
||||
newElement as? KtArrayAccessExpression
|
||||
} ?: return
|
||||
|
||||
editor.caretModel.moveToOffset(arrayAccessExpression.leftBracket!!.startOffset)
|
||||
arrayAccessExpression.leftBracket?.startOffset?.let { editor.caretModel.moveToOffset(it) }
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -5,22 +5,22 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections.substring
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractApplicabilityBasedInspection
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isStableSimpleExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.idea.intentions.toResolvedCall
|
||||
import org.jetbrains.kotlin.idea.util.calleeTextRangeInThis
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
abstract class ReplaceSubstringInspection :
|
||||
AbstractApplicabilityBasedInspection<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java) {
|
||||
abstract class ReplaceSubstringInspection : AbstractApplicabilityBasedInspection<KtDotQualifiedExpression>(
|
||||
KtDotQualifiedExpression::class.java
|
||||
) {
|
||||
protected abstract fun isApplicableInner(element: KtDotQualifiedExpression): Boolean
|
||||
protected open val isAlwaysStable: Boolean = false
|
||||
|
||||
@@ -30,8 +30,7 @@ abstract class ReplaceSubstringInspection :
|
||||
} else
|
||||
false
|
||||
|
||||
override fun inspectionHighlightRangeInElement(element: KtDotQualifiedExpression): TextRange? =
|
||||
element.callExpression?.calleeExpression?.textRange?.shiftLeft(element.startOffset)
|
||||
override fun inspectionHighlightRangeInElement(element: KtDotQualifiedExpression) = element.calleeTextRangeInThis()
|
||||
|
||||
protected fun isIndexOfCall(expression: KtExpression?, expectedReceiver: KtExpression): Boolean {
|
||||
return expression is KtDotQualifiedExpression
|
||||
|
||||
+3
-5
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.inspections.substring
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.evaluatesTo
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -20,10 +19,9 @@ class ReplaceSubstringWithDropLastInspection : ReplaceSubstringInspection() {
|
||||
override fun inspectionText(element: KtDotQualifiedExpression): String = "Replace 'substring' call with 'dropLast' call"
|
||||
override val defaultFixText: String = "Replace 'substring' call with 'dropLast' call"
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
if (element !is KtDotQualifiedExpression) return
|
||||
val argument = element.callExpression!!.valueArguments[1].getArgumentExpression()!!
|
||||
val rightExpression = (argument as KtBinaryExpression).right!!
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val argument = element.callExpression?.valueArguments?.elementAtOrNull(1)?.getArgumentExpression() ?: return
|
||||
val rightExpression = (argument as? KtBinaryExpression)?.right ?: return
|
||||
|
||||
element.replaceWith("$0.dropLast($1)", rightExpression)
|
||||
}
|
||||
|
||||
+2
-5
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.inspections.substring
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.psi.KtConstantExpression
|
||||
@@ -15,14 +14,12 @@ import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
|
||||
class ReplaceSubstringWithIndexingOperationInspection :
|
||||
ReplaceSubstringInspection() {
|
||||
class ReplaceSubstringWithIndexingOperationInspection : ReplaceSubstringInspection() {
|
||||
override fun inspectionText(element: KtDotQualifiedExpression): String = "Replace 'substring' call with indexing operation call"
|
||||
override val defaultFixText: String = "Replace 'substring' call with indexing operation call"
|
||||
override val isAlwaysStable: Boolean = true
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
if (element !is KtDotQualifiedExpression) return
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val expression = element.callExpression?.valueArguments?.firstOrNull()?.getArgumentExpression() ?: return
|
||||
element.replaceWith("$0[$1]", expression)
|
||||
}
|
||||
|
||||
+2
-5
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.inspections.substring
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
@@ -17,8 +16,7 @@ class ReplaceSubstringWithSubstringAfterInspection : ReplaceSubstringInspection(
|
||||
|
||||
override val defaultFixText: String = "Replace 'substring' call with 'substringAfter' call"
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
if (element !is KtDotQualifiedExpression) return
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
element.replaceWith(
|
||||
"$0.substringAfter($1)",
|
||||
(element.getArgumentExpression(0) as KtDotQualifiedExpression).getArgumentExpression(0)
|
||||
@@ -36,8 +34,7 @@ class ReplaceSubstringWithSubstringBeforeInspection : ReplaceSubstringInspection
|
||||
|
||||
override val defaultFixText: String = "Replace 'substring' call with 'substringBefore' call"
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
if (element !is KtDotQualifiedExpression) return
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
element.replaceWith(
|
||||
"$0.substringBefore($1)",
|
||||
(element.getArgumentExpression(1) as KtDotQualifiedExpression).getArgumentExpression(0)
|
||||
|
||||
+2
-4
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.inspections.substring
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
|
||||
@@ -16,9 +15,8 @@ class ReplaceSubstringWithTakeInspection : ReplaceSubstringInspection() {
|
||||
|
||||
override val defaultFixText: String = "Replace 'substring' call with 'take' call"
|
||||
|
||||
override fun applyTo(element: PsiElement, project: Project, editor: Editor?) {
|
||||
if (element !is KtDotQualifiedExpression) return
|
||||
val argument = element.callExpression!!.valueArguments[1].getArgumentExpression()!!
|
||||
override fun applyTo(element: KtDotQualifiedExpression, project: Project, editor: Editor?) {
|
||||
val argument = element.callExpression?.valueArguments?.elementAtOrNull(1)?.getArgumentExpression() ?: return
|
||||
element.replaceWith("$0.take($1)", argument)
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinI
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.textRangeIn
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -317,9 +318,9 @@ internal fun KtIfExpression.shouldBeTransformed(): Boolean = when (val condition
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun KtIfExpression.textRange(): TextRange {
|
||||
val rightOffset = rightParenthesis?.endOffset ?: return ifKeyword.textRange
|
||||
return TextRange(ifKeyword.startOffset, rightOffset)
|
||||
fun KtIfExpression.fromIfKeywordToRightParenthesisTextRangeInThis(): TextRange {
|
||||
val rightOffset = rightParenthesis?.endOffset ?: return ifKeyword.textRangeIn(this)
|
||||
return TextRange(ifKeyword.startOffset, rightOffset).shiftLeft(startOffset)
|
||||
}
|
||||
|
||||
private fun KtExpression.checkedExpression() = when (this) {
|
||||
|
||||
@@ -198,7 +198,7 @@ object J2KPostProcessingRegistrarImpl : J2KPostProcessingRegistrar {
|
||||
if (!isApplicable(tElement)) return null
|
||||
return {
|
||||
if (isApplicable(tElement)) { // check availability of the inspection again because something could change
|
||||
inspection.applyTo(inspection.inspectionTarget(tElement))
|
||||
inspection.applyTo(tElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.util
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.intentions.callExpression
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
@@ -32,4 +36,10 @@ fun KtExpression.hasNoSideEffects(): Boolean = when (this) {
|
||||
is KtStringTemplateExpression -> !hasInterpolation()
|
||||
is KtConstantExpression -> true
|
||||
else -> ConstantExpressionEvaluator.getConstant(this, analyze(BodyResolveMode.PARTIAL)) != null
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiElement.textRangeIn(other: PsiElement): TextRange = textRange.shiftLeft(other.startOffset)
|
||||
|
||||
fun KtDotQualifiedExpression.calleeTextRangeInThis(): TextRange? = callExpression?.calleeExpression?.textRangeIn(this)
|
||||
|
||||
fun KtNamedDeclaration.nameIdentifierTextRangeInThis(): TextRange? = nameIdentifier?.textRangeIn(this)
|
||||
+1
-1
@@ -287,7 +287,7 @@ inline fun <reified TElement : PsiElement, TInspection : AbstractApplicabilityBa
|
||||
if (!isApplicable(tElement)) return null
|
||||
return {
|
||||
if (isApplicable(tElement)) { // isApplicableTo availability of the inspection again because something could change
|
||||
inspection.applyTo(inspection.inspectionTarget(tElement))
|
||||
inspection.applyTo(tElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user