Avoid mutating state and do not rely on side effects for proper function

So #KT-17740 Fixed
This commit is contained in:
fitermay
2017-06-01 03:35:50 -04:00
committed by Mikhail Glukhikh
parent 0dced8d29c
commit 289286c8cd
@@ -35,50 +35,58 @@ import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import java.util.*
private typealias DeclPtr = SmartPsiElementPointer<KtCallableDeclaration>
class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAction<KtDeclaration>(declaration) {
private val overriddenNonOverridableMembers = ArrayList<SmartPsiElementPointer<KtCallableDeclaration>>()
private val containingDeclarationsNames = ArrayList<String>()
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
private val myQuickFixInfo: QuickFixInfo by lazy {
computeState()
}
if (!super.isAvailable(project, editor, file) || file !is KtFile) {
return false
}
private val containingDeclarationsNames
get() = myQuickFixInfo.declNames
// When running single test 'isAvailable()' is invoked multiple times, so we need to clear lists.
overriddenNonOverridableMembers.clear()
containingDeclarationsNames.clear()
private val overriddenNonOverridableMembers
get() = myQuickFixInfo.declarations
val descriptor = element.resolveToDescriptorIfAny(BodyResolveMode.FULL) as? CallableMemberDescriptor ?: return false
private fun computeState(): QuickFixInfo {
val element = element ?: return QUICKFIX_UNAVAILABLE
val overriddenNonOverridableMembers = mutableListOf<DeclPtr>()
val containingDeclarationsNames = mutableListOf<String>()
val descriptor = element.resolveToDescriptorIfAny(BodyResolveMode.FULL) as? CallableMemberDescriptor ?: return QUICKFIX_UNAVAILABLE
for (overriddenDescriptor in getAllDeclaredNonOverridableOverriddenDescriptors(descriptor)) {
assert(overriddenDescriptor.kind == DECLARATION) { "Can only be applied to declarations." }
val overriddenMember = DescriptorToSourceUtils.descriptorToDeclaration(overriddenDescriptor)
if (overriddenMember == null || !overriddenMember.canRefactor() || overriddenMember !is KtCallableDeclaration ||
overriddenMember.modifierList?.hasModifier(OPEN_KEYWORD) == true) {
return false
return QUICKFIX_UNAVAILABLE
}
val containingDeclarationName = overriddenDescriptor.containingDeclaration.name.asString()
overriddenNonOverridableMembers.add(overriddenMember.createSmartPointer())
containingDeclarationsNames.add(containingDeclarationName)
}
return overriddenNonOverridableMembers.size > 0
return QuickFixInfo(overriddenNonOverridableMembers, containingDeclarationsNames)
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
if (!super.isAvailable(project, editor, file) || file !is KtFile) {
return false
}
return overriddenNonOverridableMembers.isNotEmpty()
}
override fun getText(): String {
val element = element ?: return ""
if (overriddenNonOverridableMembers.size == 1) {
val name = containingDeclarationsNames[0] + "." + element.name
return "Make $name $OPEN_KEYWORD"
}
Collections.sort(containingDeclarationsNames)
val declarations = containingDeclarationsNames.subList(0, containingDeclarationsNames.size - 1).joinToString(", ") + " and " +
containingDeclarationsNames.last()
val sortedDeclarationNames = containingDeclarationsNames.sorted()
val declarations = sortedDeclarationNames.subList(0, sortedDeclarationNames.size - 1).joinToString(", ") + " and " +
sortedDeclarationNames.last()
return "Make '${element.name}' in $declarations open"
}
@@ -91,6 +99,9 @@ class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAc
}
companion object : KotlinSingleIntentionActionFactory() {
private data class QuickFixInfo(val declarations: List<DeclPtr>, val declNames: List<String>)
private val QUICKFIX_UNAVAILABLE = QuickFixInfo(emptyList(), emptyList())
private fun getAllDeclaredNonOverridableOverriddenDescriptors(
callableMemberDescriptor: CallableMemberDescriptor): Collection<CallableMemberDescriptor> {
@@ -104,7 +115,8 @@ class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAc
FAKE_OVERRIDE, DELEGATION ->
result.addAll(getAllDeclaredNonOverridableOverriddenDescriptors(overriddenDescriptor))
SYNTHESIZED -> {} /* do nothing */
SYNTHESIZED -> {
} /* do nothing */
else -> throw UnsupportedOperationException("Unexpected callable kind ${overriddenDescriptor.kind}")
}