Don't use JetSimpleNameExpression too much

This commit is contained in:
Valentin Kipyatkov
2015-10-08 11:42:16 +03:00
parent 23e13d4043
commit a7577ac722
20 changed files with 66 additions and 69 deletions
@@ -109,7 +109,7 @@ public class ConvertToStringTemplateIntention : JetSelfTargetingOffsetIndependen
} }
} }
is JetSimpleNameExpression -> is JetNameReferenceExpression ->
"$" + (if (forceBraces) "{$expressionText}" else expressionText) "$" + (if (forceBraces) "{$expressionText}" else expressionText)
null -> "" null -> ""
@@ -22,17 +22,17 @@ import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiRecursiveElementVisitor import com.intellij.psi.PsiRecursiveElementVisitor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.expressionComparedToNull import org.jetbrains.kotlin.idea.intentions.branchedTransformations.expressionComparedToNull
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.psi.psiUtil.siblings import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.util.ArrayList import java.util.*
public class IfNullToElvisInspection : IntentionBasedInspection<JetIfExpression>(IfNullToElvisIntention()) public class IfNullToElvisInspection : IntentionBasedInspection<JetIfExpression>(IfNullToElvisIntention())
@@ -91,7 +91,7 @@ public class IfNullToElvisIntention : JetSelfTargetingRangeIntention<JetIfExpres
val binaryExpression = ifExpression.getCondition() as? JetBinaryExpression ?: return null val binaryExpression = ifExpression.getCondition() as? JetBinaryExpression ?: return null
if (binaryExpression.getOperationToken() != JetTokens.EQEQ) return null if (binaryExpression.getOperationToken() != JetTokens.EQEQ) return null
val value = binaryExpression.expressionComparedToNull() as? JetSimpleNameExpression ?: return null val value = binaryExpression.expressionComparedToNull() as? JetNameReferenceExpression ?: return null
if (ifExpression.getParent() !is JetBlockExpression) return null if (ifExpression.getParent() !is JetBlockExpression) return null
val prevStatement = ifExpression.siblings(forward = false, withItself = false) val prevStatement = ifExpression.siblings(forward = false, withItself = false)
@@ -63,7 +63,7 @@ public class MoveAssignmentToInitializerIntention :
} }
private fun findTargetProperty(expr: JetBinaryExpression): JetProperty? { private fun findTargetProperty(expr: JetBinaryExpression): JetProperty? {
val leftExpression = expr.left as? JetSimpleNameExpression ?: return null val leftExpression = expr.left as? JetNameReferenceExpression ?: return null
return leftExpression.resolveAllReferences().firstIsInstanceOrNull<JetProperty>() return leftExpression.resolveAllReferences().firstIsInstanceOrNull<JetProperty>()
} }
@@ -21,11 +21,12 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.containsInside import org.jetbrains.kotlin.psi.psiUtil.containsInside
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi.unpackFunctionLiteral
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class MoveLambdaOutsideParenthesesIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Move lambda argument out of parentheses") { public class MoveLambdaOutsideParenthesesIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Move lambda argument out of parentheses") {
@@ -36,7 +37,7 @@ public class MoveLambdaOutsideParenthesesIntention : JetSelfTargetingIntention<J
val functionLiteral = expression.unpackFunctionLiteral() ?: return false val functionLiteral = expression.unpackFunctionLiteral() ?: return false
val callee = element.getCalleeExpression() val callee = element.getCalleeExpression()
if (callee is JetSimpleNameExpression) { if (callee is JetNameReferenceExpression) {
val bindingContext = element.analyze(BodyResolveMode.PARTIAL) val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
val targets = bindingContext[BindingContext.REFERENCE_TARGET, callee]?.let { listOf(it) } val targets = bindingContext[BindingContext.REFERENCE_TARGET, callee]?.let { listOf(it) }
?: bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, callee] ?: bindingContext[BindingContext.AMBIGUOUS_REFERENCE_TARGET, callee]
@@ -20,8 +20,8 @@ import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.psi.JetBlockStringTemplateEntry import org.jetbrains.kotlin.psi.JetBlockStringTemplateEntry
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.JetStringTemplateEntryWithExpression import org.jetbrains.kotlin.psi.JetStringTemplateEntryWithExpression
import java.util.regex.Pattern import java.util.regex.Pattern
@@ -29,7 +29,7 @@ public class RemoveCurlyBracesFromTemplateInspection : IntentionBasedInspection<
public class RemoveCurlyBracesFromTemplateIntention : JetSelfTargetingOffsetIndependentIntention<JetBlockStringTemplateEntry>(javaClass(), "Remove curly braces") { public class RemoveCurlyBracesFromTemplateIntention : JetSelfTargetingOffsetIndependentIntention<JetBlockStringTemplateEntry>(javaClass(), "Remove curly braces") {
override fun isApplicableTo(element: JetBlockStringTemplateEntry): Boolean { override fun isApplicableTo(element: JetBlockStringTemplateEntry): Boolean {
if (element.getExpression() !is JetSimpleNameExpression) return false if (element.getExpression() !is JetNameReferenceExpression) return false
val nextSiblingText = element.getNextSibling()?.getText() val nextSiblingText = element.getNextSibling()?.getText()
return nextSiblingText == null || !pattern.matcher(nextSiblingText).matches() return nextSiblingText == null || !pattern.matcher(nextSiblingText).matches()
} }
@@ -39,7 +39,7 @@ public class RemoveCurlyBracesFromTemplateIntention : JetSelfTargetingOffsetInde
} }
public fun applyTo(element: JetBlockStringTemplateEntry): JetStringTemplateEntryWithExpression { public fun applyTo(element: JetBlockStringTemplateEntry): JetStringTemplateEntryWithExpression {
val name = (element.getExpression() as JetSimpleNameExpression).getReferencedName() val name = (element.getExpression() as JetNameReferenceExpression).getReferencedName()
val newEntry = JetPsiFactory(element).createSimpleNameStringTemplateEntry(name) val newEntry = JetPsiFactory(element).createSimpleNameStringTemplateEntry(name)
return element.replaced(newEntry) return element.replaced(newEntry)
} }
@@ -27,13 +27,13 @@ import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.JetFunctionLiteral import org.jetbrains.kotlin.psi.JetFunctionLiteral
import org.jetbrains.kotlin.psi.JetSimpleNameExpression import org.jetbrains.kotlin.psi.JetNameReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBaseIntentionAction() { public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBaseIntentionAction() {
override fun getFamilyName() = "Replace explicit lambda parameter with 'it'" override fun getFamilyName() = "Replace explicit lambda parameter with 'it'"
@@ -56,9 +56,9 @@ public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBa
} }
private fun targetFunctionLiteral(element: PsiElement, caretOffset: Int): JetFunctionLiteral? { private fun targetFunctionLiteral(element: PsiElement, caretOffset: Int): JetFunctionLiteral? {
val expression = element.getParentOfType<JetSimpleNameExpression>(true) val expression = element.getParentOfType<JetNameReferenceExpression>(true)
if (expression != null) { if (expression != null) {
val target = expression.mainReference.resolveToDescriptors(expression.analyze()) val target = expression.mainReference.resolveToDescriptors(expression.analyze(BodyResolveMode.PARTIAL))
.singleOrNull() as? ParameterDescriptor ?: return null .singleOrNull() as? ParameterDescriptor ?: return null
val functionDescriptor = target.getContainingDeclaration() as? AnonymousFunctionDescriptor ?: return null val functionDescriptor = target.getContainingDeclaration() as? AnonymousFunctionDescriptor ?: return null
return DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) as? JetFunctionLiteral return DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) as? JetFunctionLiteral
@@ -23,19 +23,16 @@ import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.JetReference import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.JetFunctionLiteral import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.JetFunctionLiteralExpression
import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
public class ReplaceItWithExplicitFunctionLiteralParamIntention() : JetSelfTargetingOffsetIndependentIntention<JetSimpleNameExpression> ( public class ReplaceItWithExplicitFunctionLiteralParamIntention() : JetSelfTargetingOffsetIndependentIntention<JetNameReferenceExpression> (
javaClass(), "Replace 'it' with explicit parameter" javaClass(), "Replace 'it' with explicit parameter"
), LowPriorityAction { ), LowPriorityAction {
override fun isApplicableTo(element: JetSimpleNameExpression) override fun isApplicableTo(element: JetNameReferenceExpression)
= isAutoCreatedItUsage(element) = isAutoCreatedItUsage(element)
override fun applyTo(element: JetSimpleNameExpression, editor: Editor) { override fun applyTo(element: JetNameReferenceExpression, editor: Editor) {
val target = element.mainReference.resolveToDescriptors(element.analyze()).single() val target = element.mainReference.resolveToDescriptors(element.analyze()).single()
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.getContainingDeclaration()!!) as JetFunctionLiteral val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.getContainingDeclaration()!!) as JetFunctionLiteral
@@ -25,8 +25,8 @@ import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetBinaryExpression import org.jetbrains.kotlin.psi.JetBinaryExpression
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
public class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection<JetBinaryExpression>(ReplaceWithOperatorAssignmentIntention()) public class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection<JetBinaryExpression>(ReplaceWithOperatorAssignmentIntention())
@@ -35,14 +35,14 @@ public class ReplaceWithOperatorAssignmentIntention : JetSelfTargetingOffsetInde
override fun isApplicableTo(element: JetBinaryExpression): Boolean { override fun isApplicableTo(element: JetBinaryExpression): Boolean {
if (element.getOperationToken() != JetTokens.EQ) return false if (element.getOperationToken() != JetTokens.EQ) return false
val left = element.getLeft() as? JetSimpleNameExpression ?: return false val left = element.getLeft() as? JetNameReferenceExpression ?: return false
val right = element.getRight() as? JetBinaryExpression ?: return false val right = element.getRight() as? JetBinaryExpression ?: return false
if (right.getLeft() == null || right.getRight() == null) return false if (right.getLeft() == null || right.getRight() == null) return false
return checkExpressionRepeat(left, right) return checkExpressionRepeat(left, right)
} }
private fun checkExpressionRepeat(variableExpression: JetSimpleNameExpression, expression: JetBinaryExpression): Boolean { private fun checkExpressionRepeat(variableExpression: JetNameReferenceExpression, expression: JetBinaryExpression): Boolean {
val context = expression.analyze() val context = expression.analyze()
val descriptor = context[BindingContext.REFERENCE_TARGET, expression.getOperationReference()]?.getContainingDeclaration() val descriptor = context[BindingContext.REFERENCE_TARGET, expression.getOperationReference()]?.getContainingDeclaration()
val isPrimitiveOperation = descriptor is ClassDescriptor && KotlinBuiltIns.isPrimitiveType(descriptor.getDefaultType()) val isPrimitiveOperation = descriptor is ClassDescriptor && KotlinBuiltIns.isPrimitiveType(descriptor.getDefaultType())
@@ -81,14 +81,14 @@ public class ReplaceWithOperatorAssignmentIntention : JetSelfTargetingOffsetInde
override fun applyTo(element: JetBinaryExpression, editor: Editor) { override fun applyTo(element: JetBinaryExpression, editor: Editor) {
val replacement = buildOperatorAssignmentText( val replacement = buildOperatorAssignmentText(
element.getLeft() as JetSimpleNameExpression, element.getLeft() as JetNameReferenceExpression,
element.getRight() as JetBinaryExpression, element.getRight() as JetBinaryExpression,
"" ""
) )
element.replace(JetPsiFactory(element).createExpression(replacement)) element.replace(JetPsiFactory(element).createExpression(replacement))
} }
tailrec private fun buildOperatorAssignmentText(variableExpression: JetSimpleNameExpression, expression: JetBinaryExpression, tail: String): String { tailrec private fun buildOperatorAssignmentText(variableExpression: JetNameReferenceExpression, expression: JetBinaryExpression, tail: String): String {
val operationText = expression.getOperationReference().getText() val operationText = expression.getOperationReference().getText()
val variableName = variableExpression.getText() val variableName = variableExpression.getText()
@@ -20,14 +20,14 @@ import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetBinaryExpression import org.jetbrains.kotlin.psi.JetBinaryExpression
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.createExpressionByPattern import org.jetbrains.kotlin.psi.createExpressionByPattern
public class ReplaceWithOrdinaryAssignmentIntention : JetSelfTargetingIntention<JetBinaryExpression>(javaClass(), "Replace with ordinary assignment"), LowPriorityAction { public class ReplaceWithOrdinaryAssignmentIntention : JetSelfTargetingIntention<JetBinaryExpression>(javaClass(), "Replace with ordinary assignment"), LowPriorityAction {
override fun isApplicableTo(element: JetBinaryExpression, caretOffset: Int): Boolean { override fun isApplicableTo(element: JetBinaryExpression, caretOffset: Int): Boolean {
if (element.getOperationToken() !in JetTokens.AUGMENTED_ASSIGNMENTS) return false if (element.getOperationToken() !in JetTokens.AUGMENTED_ASSIGNMENTS) return false
if (element.getLeft() !is JetSimpleNameExpression) return false if (element.getLeft() !is JetNameReferenceExpression) return false
if (element.getRight() == null) return false if (element.getRight() == null) return false
return element.getOperationReference().getTextRange().containsOffset(caretOffset) return element.getOperationReference().getTextRange().containsOffset(caretOffset)
} }
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaClass(), "Split if into 2 if's") { public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaClass(), "Split if into 2 if's") {
override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean { override fun isApplicableTo(element: JetExpression, caretOffset: Int): Boolean {
return when (element) { return when (element) {
is JetSimpleNameExpression -> isOperatorValid(element) is JetOperationReferenceExpression -> isOperatorValid(element)
is JetIfExpression -> getFirstValidOperator(element) != null && element.getIfKeyword().getTextRange().containsOffset(caretOffset) is JetIfExpression -> getFirstValidOperator(element) != null && element.getIfKeyword().getTextRange().containsOffset(caretOffset)
else -> false else -> false
} }
@@ -41,7 +41,7 @@ public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaCla
override fun applyTo(element: JetExpression, editor: Editor) { override fun applyTo(element: JetExpression, editor: Editor) {
val operator = when (element) { val operator = when (element) {
is JetIfExpression -> getFirstValidOperator(element)!! is JetIfExpression -> getFirstValidOperator(element)!!
else -> element as JetSimpleNameExpression else -> element as JetOperationReferenceExpression
} }
val ifExpression = operator.getNonStrictParentOfType<JetIfExpression>() val ifExpression = operator.getNonStrictParentOfType<JetIfExpression>()
@@ -95,13 +95,13 @@ public class SplitIfIntention : JetSelfTargetingIntention<JetExpression>(javaCla
return expression return expression
} }
private fun getFirstValidOperator(element: JetIfExpression): JetSimpleNameExpression? { private fun getFirstValidOperator(element: JetIfExpression): JetOperationReferenceExpression? {
val condition = element.getCondition() ?: return null val condition = element.getCondition() ?: return null
return PsiTreeUtil.findChildrenOfType(condition, javaClass<JetSimpleNameExpression>()) return PsiTreeUtil.findChildrenOfType(condition, javaClass<JetOperationReferenceExpression>())
.firstOrNull { isOperatorValid(it) } .firstOrNull { isOperatorValid(it) }
} }
private fun isOperatorValid(element: JetSimpleNameExpression): Boolean { private fun isOperatorValid(element: JetOperationReferenceExpression): Boolean {
val operator = element.getReferencedNameElementType() val operator = element.getReferencedNameElementType()
if (operator != JetTokens.ANDAND && operator != JetTokens.OROR) return false if (operator != JetTokens.ANDAND && operator != JetTokens.OROR) return false
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.*
public class ToInfixCallIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Replace with infix function call") { public class ToInfixCallIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Replace with infix function call") {
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean { override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean {
val calleeExpr = element.getCalleeExpression() as? JetSimpleNameExpression ?: return false val calleeExpr = element.getCalleeExpression() as? JetNameReferenceExpression ?: return false
if (!calleeExpr.getTextRange().containsOffset(caretOffset)) return false if (!calleeExpr.getTextRange().containsOffset(caretOffset)) return false
val dotQualified = element.getParent() as? JetDotQualifiedExpression ?: return false val dotQualified = element.getParent() as? JetDotQualifiedExpression ?: return false
@@ -78,7 +78,7 @@ class UsePropertyAccessSyntaxIntention : JetSelfTargetingOffsetIndependentIntent
public fun detectPropertyNameToUse(callExpression: JetCallExpression): Name? { public fun detectPropertyNameToUse(callExpression: JetCallExpression): Name? {
if (callExpression.getQualifiedExpressionForSelector()?.getReceiverExpression() is JetSuperExpression) return null // cannot call extensions on "super" if (callExpression.getQualifiedExpressionForSelector()?.getReceiverExpression() is JetSuperExpression) return null // cannot call extensions on "super"
val callee = callExpression.getCalleeExpression() as? JetSimpleNameExpression ?: return null val callee = callExpression.getCalleeExpression() as? JetNameReferenceExpression ?: return null
val resolutionFacade = callExpression.getResolutionFacade() val resolutionFacade = callExpression.getResolutionFacade()
val bindingContext = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL) val bindingContext = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL)
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.JetType
fun JetCallableDeclaration.setType(type: JetType, shortenReferences: Boolean = true) { fun JetCallableDeclaration.setType(type: JetType, shortenReferences: Boolean = true) {
@@ -67,9 +68,9 @@ fun JetContainerNode.description(): String? {
return null return null
} }
fun isAutoCreatedItUsage(expression: JetSimpleNameExpression): Boolean { fun isAutoCreatedItUsage(expression: JetNameReferenceExpression): Boolean {
if (expression.getReferencedName() != "it") return false if (expression.getReferencedName() != "it") return false
val context = expression.analyze() val context = expression.analyze(BodyResolveMode.PARTIAL)
val target = expression.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return false val target = expression.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return false
return context[BindingContext.AUTO_CREATED_IT, target]!! return context[BindingContext.AUTO_CREATED_IT, target]!!
} }
@@ -101,7 +102,7 @@ val JetQualifiedExpression.callExpression: JetCallExpression?
get() = getSelectorExpression() as? JetCallExpression get() = getSelectorExpression() as? JetCallExpression
val JetQualifiedExpression.calleeName: String? val JetQualifiedExpression.calleeName: String?
get() = (callExpression?.getCalleeExpression() as? JetSimpleNameExpression)?.getText() get() = (callExpression?.getCalleeExpression() as? JetNameReferenceExpression)?.getText()
fun JetQualifiedExpression.toResolvedCall(): ResolvedCall<out CallableDescriptor>? { fun JetQualifiedExpression.toResolvedCall(): ResolvedCall<out CallableDescriptor>? {
val callExpression = callExpression ?: return null val callExpression = callExpression ?: return null
@@ -26,7 +26,7 @@ object BranchedFoldingUtils {
fun checkAssignment(expression: JetBinaryExpression): Boolean { fun checkAssignment(expression: JetBinaryExpression): Boolean {
if (expression.getOperationToken() !in JetTokens.ALL_ASSIGNMENTS) return false if (expression.getOperationToken() !in JetTokens.ALL_ASSIGNMENTS) return false
val left = expression.getLeft() as? JetSimpleNameExpression ?: return false val left = expression.getLeft() as? JetNameReferenceExpression ?: return false
if (expression.getRight() == null) return false if (expression.getRight() == null) return false
val parent = expression.getParent() val parent = expression.getParent()
@@ -17,23 +17,22 @@
package org.jetbrains.kotlin.idea.intentions.branchedTransformations package org.jetbrains.kotlin.idea.intentions.branchedTransformations
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement
import com.intellij.psi.search.LocalSearchScope import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.kotlin.JetNodeTypes import org.jetbrains.kotlin.JetNodeTypes
import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler import org.jetbrains.kotlin.idea.refactoring.inline.KotlinInlineValHandler
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
val NULL_PTR_EXCEPTION_FQ = "java.lang.NullPointerException" val NULL_PTR_EXCEPTION_FQ = "java.lang.NullPointerException"
val KOTLIN_NULL_PTR_EXCEPTION_FQ = "kotlin.KotlinNullPointerException" val KOTLIN_NULL_PTR_EXCEPTION_FQ = "kotlin.KotlinNullPointerException"
@@ -68,8 +67,9 @@ fun JetThrowExpression.throwsNullPointerExceptionWithNoArguments(): Boolean {
val thrownExpression = this.getThrownExpression() val thrownExpression = this.getThrownExpression()
if (thrownExpression !is JetCallExpression) return false if (thrownExpression !is JetCallExpression) return false
val context = this.analyze() val context = this.analyze(BodyResolveMode.PARTIAL)
val descriptor = context.get(BindingContext.REFERENCE_TARGET, thrownExpression.getCalleeExpression() as JetSimpleNameExpression) val nameExpression = thrownExpression.calleeExpression as? JetNameReferenceExpression ?: return false
val descriptor = context[BindingContext.REFERENCE_TARGET, nameExpression]
val declDescriptor = descriptor?.getContainingDeclaration() ?: return false val declDescriptor = descriptor?.getContainingDeclaration() ?: return false
val exceptionName = DescriptorUtils.getFqName(declDescriptor).asString() val exceptionName = DescriptorUtils.getFqName(declDescriptor).asString()
@@ -104,7 +104,7 @@ fun JetIfExpression.introduceValueForCondition(occurrenceInThenClause: JetExpres
null) null)
} }
fun JetSimpleNameExpression.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor: Editor) { fun JetNameReferenceExpression.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor: Editor) {
val declaration = this.mainReference.resolve() as? JetProperty ?: return val declaration = this.mainReference.resolve() as? JetProperty ?: return
val enclosingElement = JetPsiUtil.getEnclosingElementForLocalDeclaration(declaration) val enclosingElement = JetPsiUtil.getEnclosingElementForLocalDeclaration(declaration)
@@ -120,15 +120,15 @@ fun JetSimpleNameExpression.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(edi
} }
fun JetSafeQualifiedExpression.inlineReceiverIfApplicableWithPrompt(editor: Editor) { fun JetSafeQualifiedExpression.inlineReceiverIfApplicableWithPrompt(editor: Editor) {
(this.getReceiverExpression() as? JetSimpleNameExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor) (this.getReceiverExpression() as? JetNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
} }
fun JetBinaryExpression.inlineLeftSideIfApplicableWithPrompt(editor: Editor) { fun JetBinaryExpression.inlineLeftSideIfApplicableWithPrompt(editor: Editor) {
(this.getLeft() as? JetSimpleNameExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor) (this.getLeft() as? JetNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
} }
fun JetPostfixExpression.inlineBaseExpressionIfApplicableWithPrompt(editor: Editor) { fun JetPostfixExpression.inlineBaseExpressionIfApplicableWithPrompt(editor: Editor) {
(this.getBaseExpression() as? JetSimpleNameExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor) (this.getBaseExpression() as? JetNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
} }
fun JetExpression.isStableVariable(): Boolean { fun JetExpression.isStableVariable(): Boolean {
@@ -16,10 +16,10 @@
package org.jetbrains.kotlin.idea.intentions.branchedTransformations package org.jetbrains.kotlin.idea.intentions.branchedTransformations
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.core.replaced
fun JetWhenCondition.toExpression(subject: JetExpression?): JetExpression { fun JetWhenCondition.toExpression(subject: JetExpression?): JetExpression {
val factory = JetPsiFactory(this) val factory = JetPsiFactory(this)
@@ -58,7 +58,7 @@ public fun JetWhenExpression.getSubjectToIntroduce(): JetExpression? {
for (condition in conditions) { for (condition in conditions) {
if (condition !is JetWhenConditionWithExpression) return null if (condition !is JetWhenConditionWithExpression) return null
val candidate = condition.getExpression()?.getWhenConditionSubjectCandidate() as? JetSimpleNameExpression ?: return null val candidate = condition.getExpression()?.getWhenConditionSubjectCandidate() as? JetNameReferenceExpression ?: return null
if (lastCandidate == null) { if (lastCandidate == null) {
lastCandidate = candidate lastCandidate = candidate
@@ -82,7 +82,7 @@ private fun JetExpression?.getWhenConditionSubjectCandidate(): JetExpression? {
val op = getOperationToken() val op = getOperationToken()
when (op) { when (op) {
JetTokens.IN_KEYWORD, JetTokens.NOT_IN -> lhs JetTokens.IN_KEYWORD, JetTokens.NOT_IN -> lhs
JetTokens.EQEQ -> lhs as? JetSimpleNameExpression ?: getRight() JetTokens.EQEQ -> lhs as? JetNameReferenceExpression ?: getRight()
else -> null else -> null
} }
@@ -20,15 +20,15 @@ import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingIntention import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.toExpression import org.jetbrains.kotlin.idea.intentions.branchedTransformations.toExpression
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
import org.jetbrains.kotlin.psi.JetPsiFactory import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.JetWhenExpression import org.jetbrains.kotlin.psi.JetWhenExpression
import org.jetbrains.kotlin.psi.buildExpression import org.jetbrains.kotlin.psi.buildExpression
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class EliminateWhenSubjectIntention : JetSelfTargetingIntention<JetWhenExpression>(javaClass(), "Eliminate argument of 'when'"), LowPriorityAction { public class EliminateWhenSubjectIntention : JetSelfTargetingIntention<JetWhenExpression>(javaClass(), "Eliminate argument of 'when'"), LowPriorityAction {
override fun isApplicableTo(element: JetWhenExpression, caretOffset: Int): Boolean { override fun isApplicableTo(element: JetWhenExpression, caretOffset: Int): Boolean {
if (element.getSubjectExpression() !is JetSimpleNameExpression) return false if (element.getSubjectExpression() !is JetNameReferenceExpression) return false
val lBrace = element.getOpenBrace() ?: return false val lBrace = element.getOpenBrace() ?: return false
return caretOffset <= lBrace.startOffset return caretOffset <= lBrace.startOffset
} }
@@ -17,18 +17,18 @@
package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions package org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingIntention import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingIntention
import org.jetbrains.kotlin.idea.quickfix.moveCaret import org.jetbrains.kotlin.idea.quickfix.moveCaret
import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches import org.jetbrains.kotlin.idea.util.psi.patternMatching.matches
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class FlattenWhenIntention : JetSelfTargetingIntention<JetWhenExpression>(javaClass(), "Flatten 'when' expression") { public class FlattenWhenIntention : JetSelfTargetingIntention<JetWhenExpression>(javaClass(), "Flatten 'when' expression") {
override fun isApplicableTo(element: JetWhenExpression, caretOffset: Int): Boolean { override fun isApplicableTo(element: JetWhenExpression, caretOffset: Int): Boolean {
val subject = element.getSubjectExpression() val subject = element.getSubjectExpression()
if (subject != null && subject !is JetSimpleNameExpression) return false if (subject != null && subject !is JetNameReferenceExpression) return false
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(element)) return false if (!JetPsiUtil.checkWhenExpressionHasSingleElse(element)) return false
@@ -21,7 +21,7 @@ import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import java.util.ArrayList import java.util.*
public class FoldWhenToAssignmentIntention : JetSelfTargetingRangeIntention<JetWhenExpression>(javaClass(), "Replace 'when' expression with assignment") { public class FoldWhenToAssignmentIntention : JetSelfTargetingRangeIntention<JetWhenExpression>(javaClass(), "Replace 'when' expression with assignment") {
override fun applicabilityRange(element: JetWhenExpression): TextRange? { override fun applicabilityRange(element: JetWhenExpression): TextRange? {
@@ -53,7 +53,7 @@ public class FoldWhenToAssignmentIntention : JetSelfTargetingRangeIntention<JetW
val firstAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getEntries().get(0).getExpression()!!)!! val firstAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getEntries().get(0).getExpression()!!)!!
val op = firstAssignment.getOperationReference().getText() val op = firstAssignment.getOperationReference().getText()
val lhs = firstAssignment.getLeft() as JetSimpleNameExpression val lhs = firstAssignment.getLeft() as JetNameReferenceExpression
val assignment = JetPsiFactory(element).createExpressionByPattern("$0 $1 $2", lhs, op, element) val assignment = JetPsiFactory(element).createExpressionByPattern("$0 $1 $2", lhs, op, element)
val newWhenExpression = (assignment as JetBinaryExpression).getRight() as JetWhenExpression val newWhenExpression = (assignment as JetBinaryExpression).getRight() as JetWhenExpression
@@ -16,26 +16,24 @@
package org.jetbrains.kotlin.idea.refactoring.rename package org.jetbrains.kotlin.idea.refactoring.rename
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.project.Project
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.application.ApplicationManager
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
import org.jetbrains.kotlin.idea.intentions.ReplaceItWithExplicitFunctionLiteralParamIntention
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
public class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() { public class RenameKotlinImplicitLambdaParameter: VariableInplaceRenameHandler() {
override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean { override fun isAvailable(element: PsiElement?, editor: Editor, file: PsiFile): Boolean {
val simpleNameExpression = PsiTreeUtil.findElementOfClassAtOffset( val nameExpression = PsiTreeUtil.findElementOfClassAtOffset(
file, editor.getCaretModel().getOffset(), javaClass<JetSimpleNameExpression>(), false) file, editor.getCaretModel().getOffset(), javaClass<JetNameReferenceExpression>(), false)
return simpleNameExpression != null && isAutoCreatedItUsage(simpleNameExpression) return nameExpression != null && isAutoCreatedItUsage(nameExpression)
} }
override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) { override fun invoke(project: Project, editor: Editor, file: PsiFile, dataContext: DataContext?) {