Rename: Qualify references to members of enum companions in case of conflict with enum entries

#KT-10033 Fixed
(cherry picked from commit 3373d54)
This commit is contained in:
Alexey Sedunov
2016-05-27 18:58:33 +03:00
parent 35aa3f7646
commit 5296b61ce9
10 changed files with 93 additions and 6 deletions
@@ -21,10 +21,7 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.PostprocessReformattingAspect
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.core.ShortenReferences.Options
@@ -46,6 +43,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
import org.jetbrains.kotlin.resolve.scopes.utils.findPackage
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import java.util.*
@@ -469,6 +467,11 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
val selectorsSelectorTarget = selectorsSelector.singleTarget(bindingContext) ?: return false
if (selectorsSelectorTarget is ClassDescriptor) return false
// TODO: More generic solution may be possible
if (selectorsSelectorTarget is PropertyDescriptor) {
val source = selectorsSelectorTarget.source.getPsi() as? KtProperty
if (source != null && isEnumCompanionPropertyWithEntryConflict(source, source.name ?: "")) return false
}
addElementToShorten(qualifiedExpression)
return true
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.core
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.analysis.computeTypeInContext
import org.jetbrains.kotlin.idea.caches.resolve.analyze
@@ -27,6 +28,7 @@ import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstanceToExpression
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.BindingContext
@@ -159,4 +161,16 @@ fun KtCallableDeclaration.canOmitDeclaredType(initializerOrBodyExpression: KtExp
return canChangeTypeToSubtype && expressionType.isSubtypeOf(declaredType)
}
fun String.quoteIfNeeded(): String = if (KotlinNameSuggester.isIdentifier(this)) this else "`$this`"
fun String.quoteIfNeeded(): String = if (KotlinNameSuggester.isIdentifier(this)) this else "`$this`"
fun isEnumCompanionPropertyWithEntryConflict(element: PsiElement, expectedName: String): Boolean {
if (element !is KtProperty) return false
val propertyClass = element.containingClassOrObject as? KtObjectDeclaration ?: return false
if (!propertyClass.isCompanion()) return false
val outerClass = propertyClass.containingClassOrObject as? KtClass ?: return false
if (!outerClass.isEnum()) return false
return outerClass.declarations.any { it is KtEnumEntry && it.name == expectedName }
}