Introduce subject to when: don't perform analysis in if transformation

Otherwise we get an exception about non-analysable file
Related to KT-18772
This commit is contained in:
Mikhail Glukhikh
2019-09-27 09:04:17 +03:00
parent fdf9acfb6a
commit d45e83b27d
2 changed files with 15 additions and 11 deletions
@@ -37,7 +37,7 @@ fun KtWhenCondition.toExpression(subject: KtExpression?): KtExpression {
}
}
fun KtWhenExpression.getSubjectToIntroduce(): KtExpression? {
fun KtWhenExpression.getSubjectToIntroduce(checkConstants: Boolean = true): KtExpression? {
if (subjectExpression != null) return null
var lastCandidate: KtExpression? = null
@@ -48,7 +48,7 @@ fun KtWhenExpression.getSubjectToIntroduce(): KtExpression? {
for (condition in conditions) {
if (condition !is KtWhenConditionWithExpression) return null
val candidate = condition.expression?.getWhenConditionSubjectCandidate() ?: return null
val candidate = condition.expression?.getWhenConditionSubjectCandidate(checkConstants) ?: return null
if (candidate !is KtNameReferenceExpression
&& (candidate as? KtQualifiedExpression)?.selectorExpression !is KtNameReferenceExpression
&& candidate !is KtThisExpression
@@ -65,7 +65,7 @@ fun KtWhenExpression.getSubjectToIntroduce(): KtExpression? {
return lastCandidate
}
private fun KtExpression?.getWhenConditionSubjectCandidate(): KtExpression? = when (this) {
private fun KtExpression?.getWhenConditionSubjectCandidate(checkConstants: Boolean): KtExpression? = when (this) {
is KtIsExpression -> leftHandSide
is KtBinaryExpression -> {
@@ -74,10 +74,11 @@ private fun KtExpression?.getWhenConditionSubjectCandidate(): KtExpression? = wh
when (operationToken) {
KtTokens.IN_KEYWORD, KtTokens.NOT_IN -> lhs
KtTokens.EQEQ ->
lhs?.takeIf { it.hasCandidateNameReferenceExpression() } ?: rhs?.takeIf { it.hasCandidateNameReferenceExpression() }
lhs?.takeIf { it.hasCandidateNameReferenceExpression(checkConstants) }
?: rhs?.takeIf { it.hasCandidateNameReferenceExpression(checkConstants) }
KtTokens.OROR -> {
val leftCandidate = lhs.getWhenConditionSubjectCandidate()
val rightCandidate = rhs.getWhenConditionSubjectCandidate()
val leftCandidate = lhs.getWhenConditionSubjectCandidate(checkConstants)
val rightCandidate = rhs.getWhenConditionSubjectCandidate(checkConstants)
if (leftCandidate.matches(rightCandidate)) leftCandidate else null
}
else -> null
@@ -88,17 +89,20 @@ private fun KtExpression?.getWhenConditionSubjectCandidate(): KtExpression? = wh
else -> null
}
private fun KtExpression.hasCandidateNameReferenceExpression(): Boolean {
private fun KtExpression.hasCandidateNameReferenceExpression(checkConstants: Boolean): Boolean {
val nameReferenceExpression = this as? KtNameReferenceExpression
?: (this as? KtQualifiedExpression)?.selectorExpression as? KtNameReferenceExpression
?: return false
if (!checkConstants) {
return true
}
val resolved = nameReferenceExpression.mainReference.resolve()
if (resolved is KtObjectDeclaration || (resolved as? KtProperty)?.hasModifier(KtTokens.CONST_KEYWORD) == true) return false
return true
}
fun KtWhenExpression.introduceSubject(): KtWhenExpression? {
val subject = getSubjectToIntroduce() ?: return null
fun KtWhenExpression.introduceSubject(checkConstants: Boolean = true): KtWhenExpression? {
val subject = getSubjectToIntroduce(checkConstants) ?: return null
val commentSaver = CommentSaver(this, saveLineBreaks = true)
@@ -191,8 +191,8 @@ class IfToWhenIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpres
} as KtWhenExpression
if (whenExpression.getSubjectToIntroduce() != null) {
whenExpression = whenExpression.introduceSubject() ?: return
if (whenExpression.getSubjectToIntroduce(checkConstants = false) != null) {
whenExpression = whenExpression.introduceSubject(checkConstants = false) ?: return
}
val result = ifExpression.replaced(whenExpression)