Minor: fix warnings & refactoring

This commit is contained in:
Dmitry Gridin
2019-03-11 19:05:20 +07:00
parent ba61695a45
commit 3d66147685
11 changed files with 170 additions and 158 deletions
@@ -17,17 +17,15 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import com.intellij.psi.*
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.nextStatement
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.previousStatement
import org.jetbrains.kotlin.idea.refactoring.getLineCount
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.idea.refactoring.getLineNumber
import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.j2k.isInSingleLine
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.calls.CallExpressionElement
class AddBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class.java, "Add braces") {
override fun isApplicableTo(element: KtElement, caretOffset: Int): Boolean {
@@ -37,7 +35,7 @@ class AddBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class.ja
val parent = expression.parent
return when (parent) {
is KtContainerNode -> {
val description = parent.description()!!
val description = parent.description() ?: return false
text = "Add braces to '$description' statement"
true
}
@@ -53,7 +51,7 @@ class AddBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class.ja
override fun applyTo(element: KtElement, editor: Editor?) {
if (editor == null) throw IllegalArgumentException("This intention requires an editor")
val expression = element.getTargetExpression(editor.caretModel.offset)!!
val expression = element.getTargetExpression(editor.caretModel.offset) ?: return
var isCommentBeneath = false
var isCommentInside = false
val psiFactory = KtPsiFactory(element)
@@ -76,9 +74,9 @@ class AddBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class.ja
// Check if \n before first received comment sibling
// if false, the normal procedure of adding braces occurs.
isCommentBeneath =
sibling.prevSibling is PsiWhiteSpace &&
sibling.prevSibling.textContains('\n') &&
(sibling.prevSibling.prevSibling is PsiComment || sibling.prevSibling.prevSibling is PsiElement)
sibling.prevSibling is PsiWhiteSpace &&
sibling.prevSibling.textContains('\n') &&
(sibling.prevSibling.prevSibling is PsiComment || sibling.prevSibling.prevSibling is PsiElement)
}
}
@@ -117,7 +115,7 @@ class AddBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class.ja
when (element) {
is KtDoWhileExpression ->
// remove new line between '}' and while
(element.body!!.parent.nextSibling as? PsiWhiteSpace)?.delete()
(element.body?.parent?.nextSibling as? PsiWhiteSpace)?.delete()
is KtIfExpression ->
(result?.parent?.nextSibling as? PsiWhiteSpace)?.delete()
}
@@ -131,7 +129,7 @@ class AddBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class.ja
is KtIfExpression -> {
val thenExpr = then ?: return null
val elseExpr = `else`
if (elseExpr != null && caretLocation >= elseKeyword!!.startOffset) {
if (elseExpr != null && caretLocation >= elseKeyword?.startOffset ?: return null) {
elseExpr
} else {
thenExpr
@@ -48,8 +48,7 @@ abstract class AbstractChopListIntention<TList : KtElement, TElement : KtElement
val elements = element.elements()
if (!hasLineBreakAfter(elements.last())) {
val rpar = element.allChildren.lastOrNull { it.node.elementType == KtTokens.RPAR }
rpar?.startOffset?.let { document.insertString(it, "\n") }
element.allChildren.lastOrNull { it.node.elementType == KtTokens.RPAR }?.startOffset?.let { document.insertString(it, "\n") }
}
for (e in elements.asReversed()) {
@@ -60,8 +59,8 @@ abstract class AbstractChopListIntention<TList : KtElement, TElement : KtElement
val documentManager = PsiDocumentManager.getInstance(project)
documentManager.commitDocument(document)
val psiFile = documentManager.getPsiFile(document)!!
val newList = PsiTreeUtil.getParentOfType(psiFile.findElementAt(startOffset)!!, listClass)!!
val psiFile = documentManager.getPsiFile(document) ?: return
val newList = PsiTreeUtil.getParentOfType(psiFile.findElementAt(startOffset) ?: return, listClass) ?: return
CodeStyleManager.getInstance(project).adjustLineIndent(psiFile, newList.textRange)
}
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.CodeInsightBundle
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileSystemItem
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.util.PsiTreeUtil
@@ -34,18 +33,18 @@ import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
class IntroduceVariableIntention : SelfTargetingRangeIntention<PsiElement>(
PsiElement::class.java, CodeInsightBundle.message("intention.introduce.variable.text")
PsiElement::class.java, CodeInsightBundle.message("intention.introduce.variable.text")
) {
private fun getExpressionToProcess(element: PsiElement): KtExpression? {
if (element is PsiFileSystemItem) return null
val startElement = PsiTreeUtil.skipSiblingsBackward(element, PsiWhiteSpace::class.java) ?: element
return startElement.parentsWithSelf
.filterIsInstance<KtExpression>()
.takeWhile { it !is KtDeclarationWithBody }
.firstOrNull {
val parent = it.parent
parent is KtBlockExpression || parent is KtDeclarationWithBody && !parent.hasBlockBody() && parent.bodyExpression == it
}
.filterIsInstance<KtExpression>()
.takeWhile { it !is KtDeclarationWithBody }
.firstOrNull {
val parent = it.parent
parent is KtBlockExpression || parent is KtDeclarationWithBody && !parent.hasBlockBody() && parent.bodyExpression == it
}
}
override fun applicabilityRange(element: PsiElement): TextRange? {
@@ -58,7 +57,7 @@ class IntroduceVariableIntention : SelfTargetingRangeIntention<PsiElement>(
override fun applyTo(element: PsiElement, editor: Editor?) {
val expression = getExpressionToProcess(element) ?: return
KotlinIntroduceVariableHandler.doRefactoring(
element.project, editor, expression, isVar = false, occurrencesToReplace = null, onNonInteractiveFinish = null
element.project, editor, expression, isVar = false, occurrencesToReplace = null, onNonInteractiveFinish = null
)
}
}
@@ -35,8 +35,7 @@ class RemoveBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class
override fun isApplicableTo(element: KtElement, caretOffset: Int): Boolean {
val block = element.findChildBlock() ?: return false
val singleStatement = block.statements.singleOrNull() ?: return false
val container = block.parent
when (container) {
when (val container = block.parent) {
is KtContainerNode -> {
if (singleStatement is KtIfExpression) {
val elseExpression = (container.parent as? KtIfExpression)?.`else`
@@ -74,7 +73,8 @@ class RemoveBracesIntention : SelfTargetingIntention<KtElement>(KtElement::class
if (construct is KtIfExpression &&
container.node.elementType == KtNodeTypes.ELSE &&
construct.parent is KtExpression &&
construct.parent !is KtStatementExpression) {
construct.parent !is KtStatementExpression
) {
construct.replace(factory.createExpressionByPattern("($0)", construct))
}
}
@@ -46,25 +46,23 @@ class ReplaceExplicitFunctionLiteralParamWithItIntention : PsiElementBaseIntenti
if (parameter.destructuringDeclaration != null) return false
if (functionLiteral.anyDescendantOfType<KtFunctionLiteral> { literal ->
literal.usesName(element.text) &&
(!literal.hasParameterSpecification() || literal.usesName("it"))
} ) return false
literal.usesName(element.text) && (!literal.hasParameterSpecification() || literal.usesName("it"))
}) return false
text = "Replace explicit parameter '${parameter.name}' with 'it'"
return true
}
private fun KtFunctionLiteral.usesName(name: String): Boolean =
anyDescendantOfType<KtSimpleNameExpression> {
nameExpr -> nameExpr.getReferencedName() == name
}
private fun KtFunctionLiteral.usesName(name: String): Boolean = anyDescendantOfType<KtSimpleNameExpression> { nameExpr ->
nameExpr.getReferencedName() == name
}
override fun startInWriteAction(): Boolean = false
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
val caretOffset = editor.caretModel.offset
val functionLiteral = targetFunctionLiteral(element, editor.caretModel.offset)!!
val cursorInParameterList = functionLiteral.valueParameterList!!.textRange.containsOffset(caretOffset)
val functionLiteral = targetFunctionLiteral(element, editor.caretModel.offset) ?: return
val cursorInParameterList = functionLiteral.valueParameterList?.textRange?.containsOffset(caretOffset) ?: return
ParamRenamingProcessor(editor, functionLiteral, cursorInParameterList).run()
}
@@ -83,22 +81,23 @@ class ReplaceExplicitFunctionLiteralParamWithItIntention : PsiElementBaseIntenti
}
private class ParamRenamingProcessor(
val editor: Editor,
val functionLiteral: KtFunctionLiteral,
val cursorWasInParameterList: Boolean
) : RenameProcessor(editor.project,
functionLiteral.valueParameters.single(),
"it",
false,
false
val editor: Editor,
val functionLiteral: KtFunctionLiteral,
val cursorWasInParameterList: Boolean
) : RenameProcessor(
editor.project,
functionLiteral.valueParameters.single(),
"it",
false,
false
) {
override fun performRefactoring(usages: Array<out UsageInfo>) {
super.performRefactoring(usages)
functionLiteral.deleteChildRange(functionLiteral.valueParameterList, functionLiteral.arrow!!)
functionLiteral.deleteChildRange(functionLiteral.valueParameterList, functionLiteral.arrow ?: return)
if (cursorWasInParameterList) {
editor.caretModel.moveToOffset(functionLiteral.bodyExpression!!.textOffset)
editor.caretModel.moveToOffset(functionLiteral.bodyExpression?.textOffset ?: return)
}
val project = functionLiteral.project
@@ -28,23 +28,23 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
class ReplaceItWithExplicitFunctionLiteralParamIntention : SelfTargetingOffsetIndependentIntention<KtNameReferenceExpression> (
KtNameReferenceExpression::class.java, "Replace 'it' with explicit parameter"
class ReplaceItWithExplicitFunctionLiteralParamIntention : SelfTargetingOffsetIndependentIntention<KtNameReferenceExpression>(
KtNameReferenceExpression::class.java, "Replace 'it' with explicit parameter"
), LowPriorityAction {
override fun isApplicableTo(element: KtNameReferenceExpression)
= isAutoCreatedItUsage(element)
override fun isApplicableTo(element: KtNameReferenceExpression) = isAutoCreatedItUsage(element)
override fun applyTo(element: KtNameReferenceExpression, editor: Editor?) {
if (editor == null) throw IllegalArgumentException("This intention requires an editor")
val target = element.mainReference.resolveToDescriptors(element.analyze()).single()
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.containingDeclaration!!) as KtFunctionLiteral
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.containingDeclaration ?: return) as KtFunctionLiteral
val newExpr = KtPsiFactory(element).createExpression("{ it -> }") as KtLambdaExpression
functionLiteral.addRangeAfter(
newExpr.functionLiteral.valueParameterList,
newExpr.functionLiteral.arrow!!,
functionLiteral.lBrace)
newExpr.functionLiteral.valueParameterList,
newExpr.functionLiteral.arrow ?: return,
functionLiteral.lBrace
)
PsiDocumentManager.getInstance(element.project).doPostponedOperationsAndUnblockDocument(editor.document)
val paramToRename = functionLiteral.valueParameters.single()
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.hint.HintManager
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.codeInsight.template.*
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
@@ -47,7 +46,7 @@ import org.jetbrains.kotlin.utils.ifEmpty
class SpecifyTypeExplicitlyIntention : SelfTargetingRangeIntention<KtCallableDeclaration>(
KtCallableDeclaration::class.java,
"Specify type explicitly"
), LowPriorityAction {
) {
override fun applicabilityRange(element: KtCallableDeclaration): TextRange? {
if (element.containingFile is KtCodeFragment) return null
@@ -156,11 +156,7 @@ open class AddModifierFix(
object MakeClassOpenFactory : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val typeReference = diagnostic.psiElement as KtTypeReference
val bindingContext = typeReference.analyze(BodyResolveMode.PARTIAL)
val type = bindingContext[BindingContext.TYPE, typeReference] ?: return null
val classDescriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) as? KtClass ?: return null
if (!declaration.canRefactor()) return null
val declaration = typeReference.classForRefactor() ?: return null
if (declaration.isEnum() || declaration.isData()) return null
return AddModifierFix(declaration, KtTokens.OPEN_KEYWORD)
}
@@ -181,3 +177,12 @@ open class AddModifierFix(
}
}
}
fun KtTypeReference.classForRefactor(): KtClass? {
val bindingContext = analyze(BodyResolveMode.PARTIAL)
val type = bindingContext[BindingContext.TYPE, this] ?: return null
val classDescriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) as? KtClass ?: return null
if (!declaration.canRefactor()) return null
return declaration
}
@@ -117,8 +117,7 @@ class AddExclExclCallFix(psiElement: PsiElement, val checkImplicitReceivers: Boo
return when (psiElement) {
is KtArrayAccessExpression -> psiElement.expressionForCall()
is KtOperationReferenceExpression -> {
val parent = psiElement.parent
when (parent) {
when (val parent = psiElement.parent) {
is KtUnaryExpression -> parent.baseExpression.expressionForCall()
is KtBinaryExpression -> {
val receiver = if (KtPsiUtil.isInOrNotInOperation(parent)) parent.right else parent.left
@@ -31,7 +31,6 @@ import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiModifier
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
@@ -52,11 +51,12 @@ import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.idea.util.ReceiverType
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.idea.util.receiverTypesWithIndex
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@@ -81,8 +81,8 @@ import java.util.*
* Check possibility and perform fix for unresolved references.
*/
internal abstract class ImportFixBase<T : KtExpression> protected constructor(
expression: T,
private val factory: Factory
expression: T,
private val factory: Factory
) : KotlinQuickFixAction<T>(expression), HighPriorityAction, HintAction {
private val project = expression.project
@@ -115,8 +115,7 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
override fun getFamilyName() = KotlinBundle.message("import.fix")
override fun isAvailable(project: Project, editor: Editor?, file: KtFile)
= element != null && suggestions.isNotEmpty()
override fun isAvailable(project: Project, editor: Editor?, file: KtFile) = element != null && suggestions.isNotEmpty()
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
@@ -197,21 +196,22 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
private fun checkErrorStillPresent(bindingContext: BindingContext): Boolean {
return elementsToCheckDiagnostics()
.flatMap { bindingContext.diagnostics.forElement(it) }
.any { diagnostic -> diagnostic.factory in getSupportedErrors() }
.flatMap { bindingContext.diagnostics.forElement(it) }
.any { diagnostic -> diagnostic.factory in getSupportedErrors() }
}
protected open fun elementsToCheckDiagnostics(): Collection<PsiElement> = listOfNotNull(element)
abstract fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor>
private fun reduceCandidatesBasedOnDependencyRuleViolation(
candidates: Collection<DeclarationDescriptor>, file: PsiFile): Collection<DeclarationDescriptor> {
candidates: Collection<DeclarationDescriptor>, file: PsiFile
): Collection<DeclarationDescriptor> {
val project = file.project
val validationManager = DependencyValidationManager.getInstance(project)
return candidates.filter {
@@ -229,11 +229,11 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
open fun createImportActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<ImportFixBase<*>> = emptyList()
override final fun createAction(diagnostic: Diagnostic): IntentionAction? {
final override fun createAction(diagnostic: Diagnostic): IntentionAction? {
return createImportAction(diagnostic)?.apply { computeSuggestions() }
}
override final fun doCreateActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> {
final override fun doCreateActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<IntentionAction> {
return createImportActionsForAllProblems(sameTypeDiagnostics).onEach { it.computeSuggestions() }
}
}
@@ -242,10 +242,10 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T, factory: Factory) : ImportFixBase<T>(expression, factory) {
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val expression = element ?: return emptyList()
@@ -284,13 +284,14 @@ internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFix
return emptyList()
}
override val importNames: Collection<Name> = ((element?.mainReference?.resolvesByNames ?: emptyList()) + importNamesForMembers()).distinct()
override val importNames: Collection<Name> =
((element?.mainReference?.resolvesByNames ?: emptyList()) + importNamesForMembers()).distinct()
private fun collectMemberCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val element = element ?: return emptyList()
@@ -314,78 +315,92 @@ internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFix
val explicitReceiverTypes = actualReceiverTypes.filterNot { it.implicit }
val checkDispatchReceiver = when(callTypeAndReceiver) {
val checkDispatchReceiver = when (callTypeAndReceiver) {
is CallTypeAndReceiver.OPERATOR, is CallTypeAndReceiver.INFIX -> true
else -> false
}
val processor = { descriptor: CallableDescriptor ->
if (descriptor.canBeReferencedViaImport() && filterByCallType(descriptor)
&& descriptor.isValidByReceiversFor(explicitReceiverTypes, actualReceiverTypes, checkDispatchReceiver)) {
&& descriptor.isValidByReceiversFor(explicitReceiverTypes, actualReceiverTypes, checkDispatchReceiver)
) {
result.add(descriptor)
}
}
indicesHelper.processKotlinCallablesByName(
name,
filter = { declaration -> (declaration.parent as? KtClassBody)?.parent is KtObjectDeclaration },
processor = processor
name,
filter = { declaration -> (declaration.parent as? KtClassBody)?.parent is KtObjectDeclaration },
processor = processor
)
if (TargetPlatformDetector.getPlatform(element.containingKtFile) == JvmPlatform) {
indicesHelper.processJvmCallablesByName(
name,
filter = { it.hasModifierProperty(PsiModifier.STATIC) },
processor = processor
name,
filter = { it.hasModifierProperty(PsiModifier.STATIC) },
processor = processor
)
}
return result
}
private fun CallableDescriptor.isValidByReceiversFor(explicitReceiverTypes: Collection<ReceiverType>,
allReceiverTypes: Collection<ReceiverType>,
checkDispatchReceiver: Boolean): Boolean {
private fun CallableDescriptor.isValidByReceiversFor(
explicitReceiverTypes: Collection<ReceiverType>,
allReceiverTypes: Collection<ReceiverType>,
checkDispatchReceiver: Boolean
): Boolean {
val bothReceivers = listOfNotNull(extensionReceiverParameter, dispatchReceiverParameter.takeIf { checkDispatchReceiver })
val receiverTypesPerReceiver = generateSequence(explicitReceiverTypes.ifEmpty { allReceiverTypes }) { allReceiverTypes }
return bothReceivers
.zip(receiverTypesPerReceiver.asIterable())
.all { (receiver, possibleTypes) -> possibleTypes.any { it.type.isSubtypeOf(receiver.type) } }
.zip(receiverTypesPerReceiver.asIterable())
.all { (receiver, possibleTypes) -> possibleTypes.any { it.type.isSubtypeOf(receiver.type) } }
}
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
return super.fillCandidates(name, callTypeAndReceiver, bindingContext, indicesHelper) + collectMemberCandidates(name, callTypeAndReceiver, bindingContext, indicesHelper)
return super.fillCandidates(name, callTypeAndReceiver, bindingContext, indicesHelper) + collectMemberCandidates(
name,
callTypeAndReceiver,
bindingContext,
indicesHelper
)
}
companion object MyFactory : Factory() {
override fun createImportAction(diagnostic: Diagnostic) =
(diagnostic.psiElement as? KtSimpleNameExpression)?.let(::ImportFix)
(diagnostic.psiElement as? KtSimpleNameExpression)?.let(::ImportFix)
}
}
internal class ImportConstructorReferenceFix(expression: KtSimpleNameExpression) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
internal class ImportConstructorReferenceFix(expression: KtSimpleNameExpression) :
ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
override fun getCallTypeAndReceiver() = element?.let {
CallTypeAndReceiver.detect(it) as? CallTypeAndReceiver.CALLABLE_REFERENCE
}
override fun fillCandidates(name: String, callTypeAndReceiver: CallTypeAndReceiver<*, *>, bindingContext: BindingContext, indicesHelper: KotlinIndicesHelper): List<DeclarationDescriptor> {
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val expression = element ?: return emptyList()
val filterByCallType = callTypeAndReceiver.toFilter()
// TODO Type-aliases
return indicesHelper.getClassesByName(expression, name)
.asSequence()
.map { it.constructors }.flatten()
.filter { it.importableFqName != null }
.filter(filterByCallType)
.toList()
.asSequence()
.map { it.constructors }.flatten()
.filter { it.importableFqName != null }
.filter(filterByCallType)
.toList()
}
override fun createAction(project: Project, editor: Editor, element: KtExpression): KotlinAddImportAction {
@@ -396,7 +411,7 @@ internal class ImportConstructorReferenceFix(expression: KtSimpleNameExpression)
companion object MyFactory : Factory() {
override fun createImportAction(diagnostic: Diagnostic) =
(diagnostic.psiElement as? KtSimpleNameExpression)?.let(::ImportConstructorReferenceFix)
(diagnostic.psiElement as? KtSimpleNameExpression)?.let(::ImportConstructorReferenceFix)
}
}
@@ -407,14 +422,14 @@ internal class InvokeImportFix(expression: KtExpression) : OrdinaryImportFixBase
companion object MyFactory : Factory() {
override fun createImportAction(diagnostic: Diagnostic) =
(diagnostic.psiElement as? KtExpression)?.let(::InvokeImportFix)
(diagnostic.psiElement as? KtExpression)?.let(::InvokeImportFix)
}
}
internal open class ArrayAccessorImportFix(
element: KtArrayAccessExpression,
override val importNames: Collection<Name>,
private val showHint: Boolean
element: KtArrayAccessExpression,
override val importNames: Collection<Name>,
private val showHint: Boolean
) : OrdinaryImportFixBase<KtArrayAccessExpression>(element, MyFactory) {
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.OPERATOR(it.arrayExpression!!) }
@@ -445,9 +460,9 @@ internal open class ArrayAccessorImportFix(
}
internal class DelegateAccessorsImportFix(
element: KtExpression,
override val importNames: Collection<Name>,
private val solveSeveralProblems: Boolean
element: KtExpression,
override val importNames: Collection<Name>,
private val solveSeveralProblems: Boolean
) : OrdinaryImportFixBase<KtExpression>(element, MyFactory) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.DELEGATE(element)
@@ -472,9 +487,9 @@ internal class DelegateAccessorsImportFix(
}
override fun createImportAction(diagnostic: Diagnostic) =
(diagnostic.psiElement as? KtExpression)?.let {
DelegateAccessorsImportFix(it, importNames(listOf(diagnostic)), false)
}
(diagnostic.psiElement as? KtExpression)?.let {
DelegateAccessorsImportFix(it, importNames(listOf(diagnostic)), false)
}
override fun createImportActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<DelegateAccessorsImportFix> {
@@ -486,9 +501,9 @@ internal class DelegateAccessorsImportFix(
}
internal class ComponentsImportFix(
element: KtExpression,
override val importNames: Collection<Name>,
private val solveSeveralProblems: Boolean
element: KtExpression,
override val importNames: Collection<Name>,
private val solveSeveralProblems: Boolean
) : OrdinaryImportFixBase<KtExpression>(element, MyFactory) {
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.OPERATOR(it) }
@@ -503,12 +518,12 @@ internal class ComponentsImportFix(
companion object MyFactory : Factory() {
private fun importNames(diagnostics: Collection<Diagnostic>) =
diagnostics.map { Name.identifier(Errors.COMPONENT_FUNCTION_MISSING.cast(it).a.identifier) }
diagnostics.map { Name.identifier(Errors.COMPONENT_FUNCTION_MISSING.cast(it).a.identifier) }
override fun createImportAction(diagnostic: Diagnostic) =
(diagnostic.psiElement as? KtExpression)?.let {
ComponentsImportFix(it, importNames(listOf(diagnostic)), false)
}
(diagnostic.psiElement as? KtExpression)?.let {
ComponentsImportFix(it, importNames(listOf(diagnostic)), false)
}
override fun createImportActionsForAllProblems(sameTypeDiagnostics: Collection<Diagnostic>): List<ComponentsImportFix> {
val element = sameTypeDiagnostics.first().psiElement
@@ -520,7 +535,7 @@ internal class ComponentsImportFix(
}
internal class ImportForMismatchingArgumentsFix(
expression: KtSimpleNameExpression
expression: KtSimpleNameExpression
) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) }
@@ -530,17 +545,19 @@ internal class ImportForMismatchingArgumentsFix(
val element = element ?: return emptyList()
val callExpression = element.parent as? KtCallExpression ?: return emptyList()
return callExpression.valueArguments +
callExpression.valueArguments.mapNotNull { it.getArgumentExpression() } +
callExpression.valueArguments.mapNotNull { it.getArgumentName()?.referenceExpression } +
listOfNotNull(callExpression.valueArgumentList,
callExpression.referenceExpression())
callExpression.valueArguments.mapNotNull { it.getArgumentExpression() } +
callExpression.valueArguments.mapNotNull { it.getArgumentName()?.referenceExpression } +
listOfNotNull(
callExpression.valueArgumentList,
callExpression.referenceExpression()
)
}
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val element = element ?: return emptyList()
@@ -567,9 +584,9 @@ internal class ImportForMismatchingArgumentsFix(
val resolutionScopeWithAddedImport = resolutionScope.addImportingScope(ExplicitImportsScope(listOf(descriptor)))
val dataFlowInfo = bindingContext.getDataFlowInfoBefore(elementToAnalyze)
val newBindingContext = elementToAnalyze.analyzeInContext(
resolutionScopeWithAddedImport,
dataFlowInfo = dataFlowInfo,
contextDependency = ContextDependency.DEPENDENT // to not check complete inference
resolutionScopeWithAddedImport,
dataFlowInfo = dataFlowInfo,
contextDependency = ContextDependency.DEPENDENT // to not check complete inference
)
return newBindingContext.diagnostics.none { it.severity == Severity.ERROR }
}
@@ -583,13 +600,13 @@ internal class ImportForMismatchingArgumentsFix(
}
indicesHelper
.getCallableTopLevelExtensions(callTypeAndReceiver, element, bindingContext) { it == name }
.forEach(::processDescriptor)
.getCallableTopLevelExtensions(callTypeAndReceiver, element, bindingContext) { it == name }
.forEach(::processDescriptor)
if (!isSelectorInQualified(element)) {
indicesHelper
.getTopLevelCallablesByName(name)
.forEach(::processDescriptor)
.getTopLevelCallablesByName(name)
.forEach(::processDescriptor)
}
return result
@@ -609,8 +626,7 @@ internal object ImportForMissingOperatorFactory : ImportFixBase.Factory() {
override fun createImportAction(diagnostic: Diagnostic): ImportFixBase<*>? {
val element = diagnostic.psiElement as? KtExpression ?: return null
val operatorDescriptor = Errors.OPERATOR_MODIFIER_REQUIRED.cast(diagnostic).a
val name = operatorDescriptor.name
when (name) {
when (val name = operatorDescriptor.name) {
OperatorNameConventions.GET, OperatorNameConventions.SET -> {
if (element is KtArrayAccessExpression) {
return object : ArrayAccessorImportFix(element, listOf(name), false) {
@@ -634,4 +650,6 @@ private fun KotlinIndicesHelper.getClassesByName(expressionForPlatform: KtExpres
kindFilter = { kind -> kind != ClassKind.ENUM_ENTRY })
}
private fun CallTypeAndReceiver<*, *>.toFilter() = { descriptor: DeclarationDescriptor -> this.callType.descriptorKindFilter.accepts(descriptor) }
private fun CallTypeAndReceiver<*, *>.toFilter() = { descriptor: DeclarationDescriptor ->
callType.descriptorKindFilter.accepts(descriptor)
}
@@ -45,11 +45,7 @@ class MakeClassAnAnnotationClassFix(annotationClass: KtClass) : KotlinQuickFixAc
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val typeReference = diagnostic.psiElement.getNonStrictParentOfType<KtAnnotationEntry>()?.typeReference ?: return null
val bindingContext = typeReference.analyze(BodyResolveMode.PARTIAL)
val type = bindingContext[BindingContext.TYPE, typeReference] ?: return null
val classDescriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
val klass = DescriptorToSourceUtils.descriptorToDeclaration(classDescriptor) as? KtClass ?: return null
if (!klass.canRefactor()) return null
val klass = typeReference.classForRefactor() ?: return null
return MakeClassAnAnnotationClassFix(klass)
}
}