From a683c2b68d5b68824fa4365a5ee59e2be7534fe0 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Thu, 18 Aug 2016 15:42:55 +0300 Subject: [PATCH] IntentionBasedInspection: Removing synchronizing on intention instances Recreate intention instance in `buildVisitor` Lock caused contention for UpSource --- .../inspections/IntentionBasedInspection.kt | 51 +++--- .../idea/intentions/SelfTargetingIntention.kt | 11 +- .../inspections/HasPlatformTypeInspection.kt | 7 +- .../ConvertLambdaToReferenceIntention.kt | 68 +++---- .../ConvertToStringTemplateIntention.kt | 168 +++++++++--------- ...precatedCallableAddReplaceWithIntention.kt | 8 +- .../idea/intentions/IfNullToElvisIntention.kt | 2 +- .../ObjectLiteralToLambdaIntention.kt | 4 +- ...RemoveAtFromAnnotationArgumentIntention.kt | 2 +- .../RemoveCurlyBracesFromTemplateIntention.kt | 2 +- .../RemoveExplicitSuperQualifierIntention.kt | 4 +- .../RemoveExplicitTypeArgumentsIntention.kt | 4 +- .../intentions/RemoveExplicitTypeIntention.kt | 21 +-- .../RemoveForLoopIndicesIntention.kt | 4 +- ...SingleExpressionStringTemplateIntention.kt | 2 +- .../RemoveUnnecessaryLateinitIntention.kt | 7 +- .../ReplaceWithOperatorAssignmentIntention.kt | 2 +- .../SimplifyAssertNotNullIntention.kt | 6 +- .../SimplifyBooleanWithConstantsIntention.kt | 3 +- .../idea/intentions/SimplifyForIntention.kt | 3 +- ...implifyNegatedBinaryExpressionIntention.kt | 2 +- .../SpecifyTypeExplicitlyIntention.kt | 46 ++--- .../UsePropertyAccessSyntaxIntention.kt | 2 +- .../intentions/IfThenToElvisIntention.kt | 2 +- .../intentions/IfThenToSafeAccessIntention.kt | 2 +- .../IntroduceWhenSubjectIntention.kt | 2 +- .../ReplaceCallWithBinaryOperatorIntention.kt | 14 +- .../ReplaceGetOrSetIntention.kt | 2 +- .../LoopToCallChainIntention.kt | 6 +- .../loopToCallChain/UseWithIndexIntention.kt | 2 +- .../kotlin/idea/j2k/J2kPostProcessings.kt | 2 +- .../PackageDirectoryMismatchInspection.kt | 7 +- 32 files changed, 239 insertions(+), 229 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/IntentionBasedInspection.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/IntentionBasedInspection.kt index 0a312ec24f9..842870ae247 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/IntentionBasedInspection.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/inspections/IntentionBasedInspection.kt @@ -31,34 +31,34 @@ import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiFile import com.intellij.util.SmartList import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention +import kotlin.reflect.KClass abstract class IntentionBasedInspection( - val intentions: List>, - protected open val problemText: String?, - protected val elementType: Class + val intentionInfos: List>, + protected open val problemText: String? ) : AbstractKotlinInspection() { constructor( - intention: SelfTargetingRangeIntention, + intention: KClass>, problemText: String? = null - ) : this(listOf(IntentionData(intention)), problemText, intention.elementType) + ) : this(listOf(IntentionData(intention)), problemText) constructor( - intention: SelfTargetingRangeIntention, + intention: KClass>, additionalChecker: (TElement, IntentionBasedInspection) -> Boolean, problemText: String? = null - ) : this(listOf(IntentionData(intention, additionalChecker)), problemText, intention.elementType) + ) : this(listOf(IntentionData(intention, additionalChecker)), problemText) constructor( - intention: SelfTargetingRangeIntention, + intention: KClass>, additionalChecker: (TElement) -> Boolean, problemText: String? = null - ) : this(listOf(IntentionData(intention, { element, inspection -> additionalChecker(element) } )), problemText, intention.elementType) + ) : this(listOf(IntentionData(intention, { element, inspection -> additionalChecker(element) } )), problemText) data class IntentionData( - val intention: SelfTargetingRangeIntention, + val intention: KClass>, val additionalChecker: (TElement, IntentionBasedInspection) -> Boolean = { element, inspection -> true } ) @@ -67,6 +67,13 @@ abstract class IntentionBasedInspection( open fun inspectionRange(element: TElement): TextRange? = null override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { + + val intentionsAndCheckers = intentionInfos.map { + it.intention.constructors.single().call() to it.additionalChecker + } + val elementType = intentionsAndCheckers.map { it.first.elementType }.distinct().singleOrNull() + ?: error("$intentionInfos should have the same elementType") + return object : PsiElementVisitor() { override fun visitElement(element: PsiElement) { if (!elementType.isInstance(element) || element.textLength == 0) return @@ -77,21 +84,19 @@ abstract class IntentionBasedInspection( var problemRange: TextRange? = null var fixes: SmartList? = null - for ((intention, additionalChecker) in intentions) { - synchronized(intention) { - val range = intention.applicabilityRange(targetElement)?.let { range -> - val elementRange = targetElement.textRange - assert(range in elementRange) { "Wrong applicabilityRange() result for $intention - should be within element's range" } - range.shiftRight(-elementRange.startOffset) - } + for ((intention, additionalChecker) in intentionsAndCheckers) { + val range = intention.applicabilityRange(targetElement)?.let { range -> + val elementRange = targetElement.textRange + assert(range in elementRange) { "Wrong applicabilityRange() result for $intention - should be within element's range" } + range.shiftRight(-elementRange.startOffset) + } - if (range != null && additionalChecker(targetElement, this@IntentionBasedInspection)) { - problemRange = problemRange?.union(range) ?: range - if (fixes == null) { - fixes = SmartList() - } - fixes!!.add(createQuickFix(intention, additionalChecker, targetElement)) + if (range != null && additionalChecker(targetElement, this@IntentionBasedInspection)) { + problemRange = problemRange?.union(range) ?: range + if (fixes == null) { + fixes = SmartList() } + fixes!!.add(createQuickFix(intention, additionalChecker, targetElement)) } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt index 3bb3b3470a0..997f4d82548 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/intentions/SelfTargetingIntention.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.containsInside import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import java.util.* +import kotlin.reflect.KClass abstract class SelfTargetingIntention( val elementType: Class, @@ -88,14 +89,14 @@ abstract class SelfTargetingIntention( } protected fun isIntentionBaseInspectionEnabled(project: Project, target: TElement): Boolean { - val inspection = findInspection(javaClass) ?: return false + val inspection = findInspection(this.javaClass.kotlin) ?: return false val key = HighlightDisplayKey.find(inspection.shortName) if (!InspectionProjectProfileManager.getInstance(project).getInspectionProfile(target).isToolEnabled(key)) { return false } - return inspection.intentions.single { it.intention.javaClass == javaClass }.additionalChecker(target, inspection) + return inspection.intentionInfos.single { it.intention == this.javaClass.kotlin }.additionalChecker(target, inspection) } final override fun invoke(project: Project, editor: Editor, file: PsiFile): Unit { @@ -109,9 +110,9 @@ abstract class SelfTargetingIntention( override fun toString(): String = getText() companion object { - private val intentionBasedInspections = HashMap>, IntentionBasedInspection<*>?>() + private val intentionBasedInspections = HashMap>, IntentionBasedInspection<*>?>() - fun findInspection(intentionClass: Class>): IntentionBasedInspection? { + fun findInspection(intentionClass: KClass>): IntentionBasedInspection? { if (intentionBasedInspections.containsKey(intentionClass)) { @Suppress("UNCHECKED_CAST") return intentionBasedInspections[intentionClass] as IntentionBasedInspection? @@ -119,7 +120,7 @@ abstract class SelfTargetingIntention( for (extension in Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION)) { val inspection = extension.instance as? IntentionBasedInspection<*> ?: continue - if (inspection.intentions.any { it.intention.javaClass == intentionClass }) { + if (inspection.intentionInfos.any { it.intention == intentionClass }) { intentionBasedInspections[intentionClass] = inspection @Suppress("UNCHECKED_CAST") return inspection as IntentionBasedInspection diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/HasPlatformTypeInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/HasPlatformTypeInspection.kt index c1bc2291974..4da9f91d0b6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/HasPlatformTypeInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/HasPlatformTypeInspection.kt @@ -33,14 +33,13 @@ import org.jetbrains.kotlin.types.isNullabilityFlexible import javax.swing.JComponent class HasPlatformTypeInspection( - val intention: SpecifyTypeExplicitlyIntention = SpecifyTypeExplicitlyIntention(), @JvmField var publicAPIOnly: Boolean = true, @JvmField var reportPlatformArguments: Boolean = false ) : IntentionBasedInspection( - intention, + SpecifyTypeExplicitlyIntention::class, { element, inspection -> with(inspection as HasPlatformTypeInspection) { - intention.dangerousFlexibleTypeOrNull(element, this.publicAPIOnly, this.reportPlatformArguments) != null + SpecifyTypeExplicitlyIntention.dangerousFlexibleTypeOrNull(element, this.publicAPIOnly, this.reportPlatformArguments) != null } } ) { @@ -50,7 +49,7 @@ class HasPlatformTypeInspection( override val problemText = "Declaration has platform type. Make the type explicit to prevent subtle bugs." override fun additionalFixes(element: KtCallableDeclaration): List? { - val type = intention.dangerousFlexibleTypeOrNull(element, publicAPIOnly, reportPlatformArguments) ?: return null + val type = SpecifyTypeExplicitlyIntention.dangerousFlexibleTypeOrNull(element, publicAPIOnly, reportPlatformArguments) ?: return null if (type.isNullabilityFlexible()) { val expression = element.node.findChildByType(KtTokens.EQ)?.psi?.getNextSiblingIgnoringWhitespaceAndComments() diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt index 820799b139e..d9a73fa0cde 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertLambdaToReferenceIntention.kt @@ -32,11 +32,9 @@ import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isUnit -class ConvertLambdaToReferenceInspection( - val intention: ConvertLambdaToReferenceIntention = ConvertLambdaToReferenceIntention() -) : IntentionBasedInspection( - intention, - { it -> intention.shouldSuggestToConvert(it) } +class ConvertLambdaToReferenceInspection() : IntentionBasedInspection( + ConvertLambdaToReferenceIntention::class, + { it -> ConvertLambdaToReferenceIntention.shouldSuggestToConvert(it) } ) class ConvertLambdaToReferenceIntention : SelfTargetingOffsetIndependentIntention( @@ -79,7 +77,7 @@ class ConvertLambdaToReferenceIntention : SelfTargetingOffsetIndependentIntentio if (calleeDescriptor.typeParameters.isNotEmpty()) return false // No references to Java synthetic properties if (calleeDescriptor is SyntheticJavaPropertyDescriptor) return false - val descriptorHasReceiver = with (calleeDescriptor) { + val descriptorHasReceiver = with(calleeDescriptor) { // No references to both member / extension if (dispatchReceiverParameter != null && extensionReceiverParameter != null) return false dispatchReceiverParameter != null || extensionReceiverParameter != null @@ -144,34 +142,6 @@ class ConvertLambdaToReferenceIntention : SelfTargetingOffsetIndependentIntentio } } - internal fun shouldSuggestToConvert(element: KtLambdaExpression): Boolean { - val body = element.bodyExpression ?: return false - val referenceName = buildReferenceText(body.statements.singleOrNull() ?: return false) ?: return false - return referenceName.length < element.text.length - } - - private fun KtCallExpression.getCallReferencedName() = (calleeExpression as? KtNameReferenceExpression)?.getReferencedName() - - private fun buildReferenceText(expression: KtExpression): String? { - return when (expression) { - is KtCallExpression -> "::${expression.getCallReferencedName()}" - is KtDotQualifiedExpression -> { - val selector = expression.selectorExpression - val selectorReferenceName = when (selector) { - is KtCallExpression -> selector.getCallReferencedName() ?: return null - is KtNameReferenceExpression -> selector.getReferencedName() - else -> return null - } - val receiver = expression.receiverExpression as? KtNameReferenceExpression ?: return null - val context = receiver.analyze() - val receiverDescriptor = context[REFERENCE_TARGET, receiver] as? ParameterDescriptor ?: return null - val receiverType = receiverDescriptor.type - "$receiverType::$selectorReferenceName" - } - else -> null - } - } - override fun applyTo(element: KtLambdaExpression, editor: Editor?) { val body = element.bodyExpression ?: return val referenceName = buildReferenceText(body.statements.singleOrNull() ?: return) ?: return @@ -221,4 +191,34 @@ class ConvertLambdaToReferenceIntention : SelfTargetingOffsetIndependentIntentio } } } + + companion object { + internal fun shouldSuggestToConvert(element: KtLambdaExpression): Boolean { + val body = element.bodyExpression ?: return false + val referenceName = buildReferenceText(body.statements.singleOrNull() ?: return false) ?: return false + return referenceName.length < element.text.length + } + + private fun buildReferenceText(expression: KtExpression): String? { + return when (expression) { + is KtCallExpression -> "::${expression.getCallReferencedName()}" + is KtDotQualifiedExpression -> { + val selector = expression.selectorExpression + val selectorReferenceName = when (selector) { + is KtCallExpression -> selector.getCallReferencedName() ?: return null + is KtNameReferenceExpression -> selector.getReferencedName() + else -> return null + } + val receiver = expression.receiverExpression as? KtNameReferenceExpression ?: return null + val context = receiver.analyze() + val receiverDescriptor = context[REFERENCE_TARGET, receiver] as? ParameterDescriptor ?: return null + val receiverType = receiverDescriptor.type + "$receiverType::$selectorReferenceName" + } + else -> null + } + } + + private fun KtCallExpression.getCallReferencedName() = (calleeExpression as? KtNameReferenceExpression)?.getReferencedName() + } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToStringTemplateIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToStringTemplateIntention.kt index b92ca0410ba..ab77b68cee3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToStringTemplateIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertToStringTemplateIntention.kt @@ -29,8 +29,8 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class ConvertToStringTemplateInspection : IntentionBasedInspection( - ConvertToStringTemplateIntention(), - { it -> ConvertToStringTemplateIntention().shouldSuggestToConvert(it) } + ConvertToStringTemplateIntention::class, + { it -> ConvertToStringTemplateIntention.shouldSuggestToConvert(it) } ) class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, "Convert concatenation to template") { @@ -47,101 +47,103 @@ class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIntention element.replaced(buildReplacement(element)) } - fun shouldSuggestToConvert(expression: KtBinaryExpression): Boolean { - val entries = buildReplacement(expression).entries - return entries.none { it is KtBlockStringTemplateEntry } - && !entries.all { it is KtLiteralStringTemplateEntry || it is KtEscapeStringTemplateEntry } - && entries.count { it is KtLiteralStringTemplateEntry } > 1 - && !expression.textContains('\n') - } - - private fun isApplicableToNoParentCheck(expression: KtBinaryExpression): Boolean { - if (expression.operationToken != KtTokens.PLUS) return false - val expressionType = expression.analyze(BodyResolveMode.PARTIAL).getType(expression) - if (!KotlinBuiltIns.isString(expressionType)) return false - return isSuitable(expression) - } - - private fun isSuitable(expression: KtExpression): Boolean { - if (expression is KtBinaryExpression && expression.operationToken == KtTokens.PLUS) { - return isSuitable(expression.left ?: return false) && isSuitable(expression.right ?: return false) + companion object { + fun shouldSuggestToConvert(expression: KtBinaryExpression): Boolean { + val entries = buildReplacement(expression).entries + return entries.none { it is KtBlockStringTemplateEntry } + && !entries.all { it is KtLiteralStringTemplateEntry || it is KtEscapeStringTemplateEntry } + && entries.count { it is KtLiteralStringTemplateEntry } > 1 + && !expression.textContains('\n') } - if (PsiUtilCore.hasErrorElementChild(expression)) return false - if (expression.textContains('\n')) return false - return true - } - - private fun buildReplacement(expression: KtBinaryExpression): KtStringTemplateExpression { - val rightText = buildText(expression.right, false) - return fold(expression.left, rightText, KtPsiFactory(expression)) - } - - private fun fold(left: KtExpression?, right: String, factory: KtPsiFactory): KtStringTemplateExpression { - val forceBraces = !right.isEmpty() && right.first() != '$' && right.first().isJavaIdentifierPart() - - if (left is KtBinaryExpression && isApplicableToNoParentCheck(left)) { - val leftRight = buildText(left.right, forceBraces) - return fold(left.left, leftRight + right, factory) + private fun buildReplacement(expression: KtBinaryExpression): KtStringTemplateExpression { + val rightText = buildText(expression.right, false) + return fold(expression.left, rightText, KtPsiFactory(expression)) } - else { - val leftText = buildText(left, forceBraces) - return factory.createExpression("\"$leftText$right\"") as KtStringTemplateExpression - } - } - private fun buildText(expr: KtExpression?, forceBraces: Boolean): String { - if (expr == null) return "" - val expression = KtPsiUtil.safeDeparenthesize(expr) - val expressionText = expression.text - when (expression) { - is KtConstantExpression -> { - val bindingContext = expression.analyze(BodyResolveMode.PARTIAL) - val type = bindingContext.getType(expression)!! + private fun fold(left: KtExpression?, right: String, factory: KtPsiFactory): KtStringTemplateExpression { + val forceBraces = !right.isEmpty() && right.first() != '$' && right.first().isJavaIdentifierPart() - if (KotlinBuiltIns.isChar(type)) { - val value = expressionText.removePrefix("'").removeSuffix("'") - return when (value) { // escape double quote and unescape single one - "\"" -> "\\\"" - "\\'" -> "'" - else -> value - } - } - - val constant = ConstantExpressionEvaluator.getConstant(expression, bindingContext) - val stringValue = constant?.getValue(type).toString() - if (stringValue == expressionText) { - return StringUtil.escapeStringCharacters(stringValue) - } + if (left is KtBinaryExpression && isApplicableToNoParentCheck(left)) { + val leftRight = buildText(left.right, forceBraces) + return fold(left.left, leftRight + right, factory) } + else { + val leftText = buildText(left, forceBraces) + return factory.createExpression("\"$leftText$right\"") as KtStringTemplateExpression + } + } - is KtStringTemplateExpression -> { - val base = if (expressionText.startsWith("\"\"\"") && expressionText.endsWith("\"\"\"")) { - val unquoted = expressionText.substring(3, expressionText.length - 3) - StringUtil.escapeStringCharacters(unquoted) - } - else { - StringUtil.unquoteString(expressionText) - } + private fun buildText(expr: KtExpression?, forceBraces: Boolean): String { + if (expr == null) return "" + val expression = KtPsiUtil.safeDeparenthesize(expr) + val expressionText = expression.text + when (expression) { + is KtConstantExpression -> { + val bindingContext = expression.analyze(BodyResolveMode.PARTIAL) + val type = bindingContext.getType(expression)!! - if (forceBraces) { - if (base.endsWith('$')) { - return base.dropLast(1) + "\\$" - } - else { - val lastPart = expression.children.lastOrNull() - if (lastPart is KtSimpleNameStringTemplateEntry) { - return base.dropLast(lastPart.textLength) + "\${" + lastPart.text.drop(1) + "}" + if (KotlinBuiltIns.isChar(type)) { + val value = expressionText.removePrefix("'").removeSuffix("'") + return when (value) { // escape double quote and unescape single one + "\"" -> "\\\"" + "\\'" -> "'" + else -> value } } + + val constant = ConstantExpressionEvaluator.getConstant(expression, bindingContext) + val stringValue = constant?.getValue(type).toString() + if (stringValue == expressionText) { + return StringUtil.escapeStringCharacters(stringValue) + } } - return base + + is KtStringTemplateExpression -> { + val base = if (expressionText.startsWith("\"\"\"") && expressionText.endsWith("\"\"\"")) { + val unquoted = expressionText.substring(3, expressionText.length - 3) + StringUtil.escapeStringCharacters(unquoted) + } + else { + StringUtil.unquoteString(expressionText) + } + + if (forceBraces) { + if (base.endsWith('$')) { + return base.dropLast(1) + "\\$" + } + else { + val lastPart = expression.children.lastOrNull() + if (lastPart is KtSimpleNameStringTemplateEntry) { + return base.dropLast(lastPart.textLength) + "\${" + lastPart.text.drop(1) + "}" + } + } + } + return base + } + + is KtNameReferenceExpression -> + return "$" + (if (forceBraces) "{$expressionText}" else expressionText) } - is KtNameReferenceExpression -> - return "$" + (if (forceBraces) "{$expressionText}" else expressionText) + return "\${$expressionText}" } - return "\${$expressionText}" + private fun isApplicableToNoParentCheck(expression: KtBinaryExpression): Boolean { + if (expression.operationToken != KtTokens.PLUS) return false + val expressionType = expression.analyze(BodyResolveMode.PARTIAL).getType(expression) + if (!KotlinBuiltIns.isString(expressionType)) return false + return isSuitable(expression) + } + + private fun isSuitable(expression: KtExpression): Boolean { + if (expression is KtBinaryExpression && expression.operationToken == KtTokens.PLUS) { + return isSuitable(expression.left ?: return false) && isSuitable(expression.right ?: return false) + } + + if (PsiUtilCore.hasErrorElementChild(expression)) return false + if (expression.textContains('\n')) return false + return true + } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/DeprecatedCallableAddReplaceWithIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/DeprecatedCallableAddReplaceWithIntention.kt index 35d2c3b1822..fea2633481e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/DeprecatedCallableAddReplaceWithIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/DeprecatedCallableAddReplaceWithIntention.kt @@ -25,12 +25,12 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.imports.importableFqName -import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection +import org.jetbrains.kotlin.idea.core.ShortenReferences 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.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.util.ImportInsertHelper -import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression import org.jetbrains.kotlin.resolve.BindingContext @@ -42,7 +42,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.types.typeUtil.isUnit import java.util.* -class DeprecatedCallableAddReplaceWithInspection : IntentionBasedInspection(DeprecatedCallableAddReplaceWithIntention()) +class DeprecatedCallableAddReplaceWithInspection : IntentionBasedInspection(DeprecatedCallableAddReplaceWithIntention::class) class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeIntention( KtCallableDeclaration::class.java, "Add 'replaceWith' argument to specify replacement pattern", "Add 'replaceWith' argument to 'Deprecated' annotation" diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt index 57133dae32b..d10569c2b9c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/IfNullToElvisIntention.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -class IfNullToElvisInspection : IntentionBasedInspection(IfNullToElvisIntention()) +class IfNullToElvisInspection : IntentionBasedInspection(IfNullToElvisIntention::class) class IfNullToElvisIntention : SelfTargetingRangeIntention(KtIfExpression::class.java, "Replace 'if' with elvis operator"){ override fun applicabilityRange(element: KtIfExpression): TextRange? { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt index fa6eb8f1fda..b3a9ebaa3a5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ObjectLiteralToLambdaIntention.kt @@ -24,13 +24,13 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection import org.jetbrains.kotlin.idea.util.CommentSaver import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils import org.jetbrains.kotlin.psi.* @@ -43,7 +43,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.KotlinType -class ObjectLiteralToLambdaInspection : IntentionBasedInspection(ObjectLiteralToLambdaIntention()) +class ObjectLiteralToLambdaInspection : IntentionBasedInspection(ObjectLiteralToLambdaIntention::class) class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention( KtObjectLiteralExpression::class.java, diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt index 93c5ba458d7..77f476419e8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveAtFromAnnotationArgumentIntention.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.KtAnnotatedExpression import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtPsiFactory -class RemoveAtFromAnnotationArgumentInspection : IntentionBasedInspection(RemoveAtFromAnnotationArgumentIntention()) +class RemoveAtFromAnnotationArgumentInspection : IntentionBasedInspection(RemoveAtFromAnnotationArgumentIntention::class) class RemoveAtFromAnnotationArgumentIntention : SelfTargetingOffsetIndependentIntention( KtAnnotatedExpression::class.java, diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveCurlyBracesFromTemplateIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveCurlyBracesFromTemplateIntention.kt index 30cb13535f1..3aa644a4afa 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveCurlyBracesFromTemplateIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveCurlyBracesFromTemplateIntention.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtStringTemplateEntryWithExpression import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry -class RemoveCurlyBracesFromTemplateInspection : IntentionBasedInspection(RemoveCurlyBracesFromTemplateIntention()) +class RemoveCurlyBracesFromTemplateInspection : IntentionBasedInspection(RemoveCurlyBracesFromTemplateIntention::class) class RemoveCurlyBracesFromTemplateIntention : SelfTargetingOffsetIndependentIntention(KtBlockStringTemplateEntry::class.java, "Remove curly braces") { override fun isApplicableTo(element: KtBlockStringTemplateEntry): Boolean { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt index 26535226564..28aee1eb6d0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitSuperQualifierIntention.kt @@ -23,8 +23,8 @@ import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.idea.analysis.analyzeInContext import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection +import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.KtQualifiedExpression import org.jetbrains.kotlin.psi.KtSuperExpression @@ -39,7 +39,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.TypeUtils -class RemoveExplicitSuperQualifierInspection : IntentionBasedInspection(RemoveExplicitSuperQualifierIntention()), CleanupLocalInspectionTool { +class RemoveExplicitSuperQualifierInspection : IntentionBasedInspection(RemoveExplicitSuperQualifierIntention::class), CleanupLocalInspectionTool { override val problemHighlightType: ProblemHighlightType get() = ProblemHighlightType.LIKE_UNUSED_SYMBOL } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt index 1c5bdbac36a..82ca99bb252 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeArgumentsIntention.kt @@ -18,9 +18,9 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.codeInspection.ProblemHighlightType import com.intellij.openapi.editor.Editor -import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection +import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext @@ -34,7 +34,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.KotlinTypeChecker -class RemoveExplicitTypeArgumentsInspection : IntentionBasedInspection(RemoveExplicitTypeArgumentsIntention()) { +class RemoveExplicitTypeArgumentsInspection : IntentionBasedInspection(RemoveExplicitTypeArgumentsIntention::class) { override val problemHighlightType: ProblemHighlightType get() = ProblemHighlightType.LIKE_UNUSED_SYMBOL } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt index 38d0cae74dc..698853bee0f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveExplicitTypeIntention.kt @@ -25,11 +25,10 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.getStartOffsetIn import org.jetbrains.kotlin.psi.psiUtil.startOffset -class RemoveSetterParameterTypeInspection( - val intention: RemoveExplicitTypeIntention = RemoveExplicitTypeIntention() -) : IntentionBasedInspection( - intention, - { it -> intention.isSetterParameter(it) } +class RemoveSetterParameterTypeInspection() +: IntentionBasedInspection( + RemoveExplicitTypeIntention::class, + { it -> RemoveExplicitTypeIntention.isSetterParameter(it) } ) { override val problemHighlightType = ProblemHighlightType.LIKE_UNUSED_SYMBOL @@ -44,11 +43,6 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention( - RemoveForLoopIndicesIntention(), - problemText = "Index is not used in the loop body" + RemoveForLoopIndicesIntention::class, + "Index is not used in the loop body" ) { override val problemHighlightType: ProblemHighlightType get() = ProblemHighlightType.LIKE_UNUSED_SYMBOL diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveSingleExpressionStringTemplateIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveSingleExpressionStringTemplateIntention.kt index a491287e1c5..25942a04c28 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveSingleExpressionStringTemplateIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveSingleExpressionStringTemplateIntention.kt @@ -30,7 +30,7 @@ private fun KtStringTemplateExpression.singleExpressionOrNull() = children.singleOrNull()?.children?.firstOrNull() as? KtExpression class RemoveSingleExpressionStringTemplateInspection : IntentionBasedInspection( - RemoveSingleExpressionStringTemplateIntention(), + RemoveSingleExpressionStringTemplateIntention::class, additionalChecker = { templateExpression -> templateExpression.singleExpressionOrNull()?.let { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveUnnecessaryLateinitIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveUnnecessaryLateinitIntention.kt index a872e8d2de6..5adfc45f168 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveUnnecessaryLateinitIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveUnnecessaryLateinitIntention.kt @@ -23,12 +23,15 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully import org.jetbrains.kotlin.idea.conversion.copy.range import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -class RemoveUnnecessaryLateinitInspection : IntentionBasedInspection(RemoveUnnecessaryLateinitIntention()) { +class RemoveUnnecessaryLateinitInspection : IntentionBasedInspection(RemoveUnnecessaryLateinitIntention::class) { override val problemHighlightType = ProblemHighlightType.LIKE_UNUSED_SYMBOL override val problemText = "Unnecessary lateinit" diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt index 5dd667680b6..3e1383fba3b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceWithOperatorAssignmentIntention.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection(ReplaceWithOperatorAssignmentIntention()) +class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection(ReplaceWithOperatorAssignmentIntention::class) class ReplaceWithOperatorAssignmentIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, "Replace with operator-assignment") { override fun isApplicableTo(element: KtBinaryExpression): Boolean { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyAssertNotNullIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyAssertNotNullIntention.kt index c5b5e226e0f..19e15fbdb41 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyAssertNotNullIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyAssertNotNullIntention.kt @@ -20,12 +20,12 @@ import com.intellij.codeInsight.CodeInsightUtilCore import com.intellij.openapi.editor.Editor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.core.ShortenReferences +import org.jetbrains.kotlin.idea.core.moveCaret import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.intentions.branchedTransformations.expressionComparedToNull -import org.jetbrains.kotlin.idea.core.moveCaret import org.jetbrains.kotlin.idea.util.CommentSaver -import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset @@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -class SimplifyAssertNotNullInspection : IntentionBasedInspection(SimplifyAssertNotNullIntention()) +class SimplifyAssertNotNullInspection : IntentionBasedInspection(SimplifyAssertNotNullIntention::class) class SimplifyAssertNotNullIntention : SelfTargetingOffsetIndependentIntention( KtCallExpression::class.java, diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt index 92d19992dc7..f9d8d1f3157 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyBooleanWithConstantsIntention.kt @@ -26,9 +26,8 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils -import org.jetbrains.kotlin.resolve.DelegatingBindingTrace -class SimplifyBooleanWithConstantsInspection : IntentionBasedInspection(SimplifyBooleanWithConstantsIntention()) +class SimplifyBooleanWithConstantsInspection : IntentionBasedInspection(SimplifyBooleanWithConstantsIntention::class) class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentIntention(KtBinaryExpression::class.java, "Simplify boolean expression") { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt index e7936866790..7ca5530952a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyForIntention.kt @@ -37,9 +37,8 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import java.util.* -import kotlin.collections.forEach -class SimplifyForInspection : IntentionBasedInspection(SimplifyForIntention()) +class SimplifyForInspection : IntentionBasedInspection(SimplifyForIntention::class) class SimplifyForIntention : SelfTargetingRangeIntention( KtForExpression::class.java, diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyNegatedBinaryExpressionIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyNegatedBinaryExpressionIntention.kt index de9e8782594..b5c0fed3def 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyNegatedBinaryExpressionIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SimplifyNegatedBinaryExpressionIntention.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -class SimplifyNegatedBinaryExpressionInspection : IntentionBasedInspection(SimplifyNegatedBinaryExpressionIntention()) +class SimplifyNegatedBinaryExpressionInspection : IntentionBasedInspection(SimplifyNegatedBinaryExpressionIntention::class) class SimplifyNegatedBinaryExpressionIntention : SelfTargetingRangeIntention(KtPrefixExpression::class.java, "Simplify negated binary expression") { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt index 445c56c9474..2e4abf10a8e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt @@ -51,29 +51,6 @@ class SpecifyTypeExplicitlyIntention : SelfTargetingRangeIntention(KtCallableDeclaration::class.java, "Specify type explicitly"), LowPriorityAction { - fun dangerousFlexibleTypeOrNull( - declaration: KtCallableDeclaration, publicAPIOnly: Boolean, reportPlatformArguments: Boolean - ): KotlinType? { - when (declaration) { - is KtFunction -> if (declaration.isLocal || declaration.hasDeclaredReturnType()) return null - is KtProperty -> if (declaration.isLocal || declaration.typeReference != null) return null - else -> return null - } - - if (declaration.containingClassOrObject?.isLocal() ?: false) return null - - val callable = declaration.resolveToDescriptorIfAny() as? CallableDescriptor ?: return null - if (publicAPIOnly && !callable.visibility.isPublicAPI) return null - val type = callable.returnType ?: return null - if (reportPlatformArguments) { - if (!type.isFlexibleRecursive()) return null - } - else { - if (!type.isFlexible()) return null - } - return type - } - override fun applicabilityRange(element: KtCallableDeclaration): TextRange? { if (element.containingFile is KtCodeFragment) return null if (element is KtFunctionLiteral) return null // TODO: should KtFunctionLiteral be KtCallableDeclaration at all? @@ -108,6 +85,29 @@ class SpecifyTypeExplicitlyIntention : private val PropertyDescriptor.setterType: KotlinType? get() = setter?.valueParameters?.firstOrNull()?.type?.let { if (it.isError) null else it } + fun dangerousFlexibleTypeOrNull( + declaration: KtCallableDeclaration, publicAPIOnly: Boolean, reportPlatformArguments: Boolean + ): KotlinType? { + when (declaration) { + is KtFunction -> if (declaration.isLocal || declaration.hasDeclaredReturnType()) return null + is KtProperty -> if (declaration.isLocal || declaration.typeReference != null) return null + else -> return null + } + + if (declaration.containingClassOrObject?.isLocal() ?: false) return null + + val callable = declaration.resolveToDescriptorIfAny() as? CallableDescriptor ?: return null + if (publicAPIOnly && !callable.visibility.isPublicAPI) return null + val type = callable.returnType ?: return null + if (reportPlatformArguments) { + if (!type.isFlexibleRecursive()) return null + } + else { + if (!type.isFlexible()) return null + } + return type + } + fun getTypeForDeclaration(declaration: KtCallableDeclaration): KotlinType { val descriptor = declaration.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] val type = (descriptor as? CallableDescriptor)?.returnType diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt index 948e3d29327..f11ee11367d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/UsePropertyAccessSyntaxIntention.kt @@ -55,7 +55,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isUnit -class UsePropertyAccessSyntaxInspection : IntentionBasedInspection(UsePropertyAccessSyntaxIntention()), CleanupLocalInspectionTool +class UsePropertyAccessSyntaxInspection : IntentionBasedInspection(UsePropertyAccessSyntaxIntention::class), CleanupLocalInspectionTool class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention(KtCallExpression::class.java, "Use property access syntax") { override fun isApplicableTo(element: KtCallExpression): Boolean { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt index 6a9c7ae7f9f..09196cdef6a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToElvisIntention.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -class IfThenToElvisInspection : IntentionBasedInspection(IfThenToElvisIntention()) +class IfThenToElvisInspection : IntentionBasedInspection(IfThenToElvisIntention::class) class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention(KtIfExpression::class.java, "Replace 'if' expression with elvis expression") { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt index 7adb1e6fc41..95189b75f00 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IfThenToSafeAccessIntention.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -class IfThenToSafeAccessInspection : IntentionBasedInspection(IfThenToSafeAccessIntention()) +class IfThenToSafeAccessInspection : IntentionBasedInspection(IfThenToSafeAccessIntention::class) class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntention(KtIfExpression::class.java, "Replace 'if' expression with safe access expression") { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IntroduceWhenSubjectIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IntroduceWhenSubjectIntention.kt index 7baaa8c31a8..8a2f2af2013 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IntroduceWhenSubjectIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/intentions/IntroduceWhenSubjectIntention.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.getSubjectTo import org.jetbrains.kotlin.idea.intentions.branchedTransformations.introduceSubject import org.jetbrains.kotlin.psi.KtWhenExpression -class IntroduceWhenSubjectInspection : IntentionBasedInspection(IntroduceWhenSubjectIntention()) +class IntroduceWhenSubjectInspection : IntentionBasedInspection(IntroduceWhenSubjectIntention::class) class IntroduceWhenSubjectIntention : SelfTargetingRangeIntention(KtWhenExpression::class.java, "Introduce argument to 'when'") { override fun applicabilityRange(element: KtWhenExpression): TextRange? { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt index b0c5654e5c9..6ab00e7c2a1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceCallWithBinaryOperatorIntention.kt @@ -19,25 +19,25 @@ package org.jetbrains.kotlin.idea.intentions.conventionNameCalls import com.intellij.codeInsight.intention.HighPriorityAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement import com.intellij.psi.tree.IElementType import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.idea.intentions.* +import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention +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.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions -class ReplaceCallWithComparisonInspection( - val intention: ReplaceCallWithBinaryOperatorIntention = ReplaceCallWithBinaryOperatorIntention() -) : IntentionBasedInspection( - intention, +class ReplaceCallWithComparisonInspection() : IntentionBasedInspection( + ReplaceCallWithBinaryOperatorIntention::class, { qualifiedExpression -> val calleeExpression = qualifiedExpression.callExpression?.calleeExpression as? KtSimpleNameExpression val identifier = calleeExpression?.getReferencedNameAsName() diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceGetOrSetIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceGetOrSetIntention.kt index fd9cad5cada..7c474580b3d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceGetOrSetIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/conventionNameCalls/ReplaceGetOrSetIntention.kt @@ -42,7 +42,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.isValidOperator class ReplaceGetOrSetInspection : IntentionBasedInspection( - ReplaceGetOrSetIntention(), ReplaceGetOrSetInspection.additionalChecker + ReplaceGetOrSetIntention::class, ReplaceGetOrSetInspection.additionalChecker ) { companion object { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/LoopToCallChainIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/LoopToCallChainIntention.kt index 0c6502e441b..6c62ec66b5e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/LoopToCallChainIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/LoopToCallChainIntention.kt @@ -28,9 +28,9 @@ import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.psiUtil.startOffset class LoopToCallChainInspection : IntentionBasedInspection( - listOf(IntentionData(LoopToCallChainIntention()), IntentionData(LoopToLazyCallChainIntention())), - problemText = "Loop can be replaced with stdlib operations", - elementType = KtForExpression::class.java) + listOf(IntentionData(LoopToCallChainIntention::class), IntentionData(LoopToLazyCallChainIntention::class)), + problemText = "Loop can be replaced with stdlib operations" +) class LoopToCallChainIntention : AbstractLoopToCallChainIntention(lazy = false, text = "Replace with stdlib operations") diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/UseWithIndexIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/UseWithIndexIntention.kt index a20f5586c58..8aac2e1933f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/UseWithIndexIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/loopToCallChain/UseWithIndexIntention.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.createExpressionByPattern -class UseWithIndexInspection : IntentionBasedInspection(UseWithIndexIntention()) +class UseWithIndexInspection : IntentionBasedInspection(UseWithIndexIntention::class) class UseWithIndexIntention : SelfTargetingRangeIntention( KtForExpression::class.java, diff --git a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt index d0e026876a2..ab307fa28c0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt +++ b/idea/src/org/jetbrains/kotlin/idea/j2k/J2kPostProcessings.kt @@ -190,7 +190,7 @@ object J2KPostProcessingRegistrar { private val intention = ConvertToStringTemplateIntention() override fun createAction(element: KtElement, diagnostics: Diagnostics): (() -> Unit)? { - if (element is KtBinaryExpression && intention.isApplicableTo(element) && intention.shouldSuggestToConvert(element)) { + if (element is KtBinaryExpression && intention.isApplicableTo(element) && ConvertToStringTemplateIntention.shouldSuggestToConvert(element)) { return { intention.applyTo(element, null) } } else { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt index 6eecfbc639d..4ea4d23658f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt @@ -20,7 +20,8 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.psi.KtPackageDirective class PackageDirectoryMismatchInspection: IntentionBasedInspection( - listOf(IntentionBasedInspection.IntentionData(MoveFileToPackageMatchingDirectoryIntention()), IntentionBasedInspection.IntentionData(ChangePackageToMatchDirectoryIntention())), - "Package directive doesn't match file location", - KtPackageDirective::class.java + listOf( + IntentionBasedInspection.IntentionData(MoveFileToPackageMatchingDirectoryIntention::class), + IntentionBasedInspection.IntentionData(ChangePackageToMatchDirectoryIntention::class)), + "Package directive doesn't match file location" ) \ No newline at end of file