Misc: Cleanup "org.jetbrains.kotlin.idea.intentions" package

This commit is contained in:
Alexey Sedunov
2015-12-17 19:33:02 +03:00
parent 3fca8f765c
commit 2fb3c727a7
89 changed files with 927 additions and 980 deletions
@@ -21,47 +21,47 @@ import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class AddBracesIntention : SelfTargetingIntention<KtExpression>(javaClass(), "Add braces") {
public class AddBracesIntention : SelfTargetingIntention<KtExpression>(KtExpression::class.java, "Add braces") {
override fun isApplicableTo(element: KtExpression, caretOffset: Int): Boolean {
val expression = element.getTargetExpression(caretOffset) ?: return false
if (expression is KtBlockExpression) return false
val description = (expression.getParent() as KtContainerNode).description()!!
setText("Add braces to '$description' statement")
val description = (expression.parent as KtContainerNode).description()!!
text = "Add braces to '$description' statement"
return true
}
override fun applyTo(element: KtExpression, editor: Editor) {
val expression = element.getTargetExpression(editor.getCaretModel().getOffset())!!
val expression = element.getTargetExpression(editor.caretModel.offset)!!
if (element.getNextSibling()?.getText() == ";") {
element.getNextSibling()!!.delete()
if (element.nextSibling?.text == ";") {
element.nextSibling!!.delete()
}
val psiFactory = KtPsiFactory(element)
expression.replace(psiFactory.createSingleStatementBlock(expression))
if (element is KtDoWhileExpression) { // remove new line between '}' and while
(element.getBody()!!.getParent().getNextSibling() as? PsiWhiteSpace)?.delete()
(element.body!!.parent.nextSibling as? PsiWhiteSpace)?.delete()
}
}
private fun KtExpression.getTargetExpression(caretLocation: Int): KtExpression? {
when (this) {
is KtIfExpression -> {
val thenExpr = getThen() ?: return null
val elseExpr = getElse()
if (elseExpr != null && caretLocation >= getElseKeyword()!!.startOffset) {
val thenExpr = then ?: return null
val elseExpr = `else`
if (elseExpr != null && caretLocation >= elseKeyword!!.startOffset) {
return elseExpr
}
return thenExpr
}
is KtWhileExpression -> return getBody()
is KtWhileExpression -> return body
is KtDoWhileExpression -> return getBody()
is KtDoWhileExpression -> return body
is KtForExpression -> return getBody()
is KtForExpression -> return body
else -> return null
}
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class AddForLoopIndicesIntention : SelfTargetingRangeIntention<KtForExpression>(javaClass(), "Add indices to 'for' loop"), LowPriorityAction {
public class AddForLoopIndicesIntention : SelfTargetingRangeIntention<KtForExpression>(KtForExpression::class.java, "Add indices to 'for' loop"), LowPriorityAction {
private val WITH_INDEX_NAME = "withIndex"
private val WITH_INDEX_FQ_NAMES = listOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$WITH_INDEX_NAME" }.toSet()
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.idea.conversion.copy.end
import org.jetbrains.kotlin.idea.conversion.copy.start
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatchStatus
@@ -32,16 +31,16 @@ import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class AddNameToArgumentIntention
: SelfTargetingIntention<KtValueArgument>(javaClass(), "Add name to argument"), LowPriorityAction {
: SelfTargetingIntention<KtValueArgument>(KtValueArgument::class.java, "Add name to argument"), LowPriorityAction {
override fun isApplicableTo(element: KtValueArgument, caretOffset: Int): Boolean {
val expression = element.getArgumentExpression() ?: return false
val name = detectNameToAdd(element) ?: return false
setText("Add '$name =' to argument")
text = "Add '$name =' to argument"
if (expression is KtLambdaExpression) {
val range = expression.getTextRange()
val range = expression.textRange
return caretOffset == range.start || caretOffset == range.end
}
@@ -61,21 +60,21 @@ public class AddNameToArgumentIntention
if (argument.isNamed()) return null
if (argument is KtLambdaArgument) return null
val argumentList = argument.getParent() as? KtValueArgumentList ?: return null
val argumentList = argument.parent as? KtValueArgumentList ?: return null
if (argument != argumentList.arguments.last { !it.isNamed() }) return null
val callExpr = argumentList.getParent() as? KtExpression ?: return null
val callExpr = argumentList.parent as? KtExpression ?: return null
val resolvedCall = callExpr.getResolvedCall(callExpr.analyze(BodyResolveMode.PARTIAL)) ?: return null
val argumentMatch = resolvedCall.getArgumentMapping(argument) as? ArgumentMatch ?: return null
if (argumentMatch.status != ArgumentMatchStatus.SUCCESS) return null
if (!resolvedCall.getResultingDescriptor().hasStableParameterNames()) return null
if (!resolvedCall.resultingDescriptor.hasStableParameterNames()) return null
if (argumentMatch.valueParameter.varargElementType != null) {
val varargArgument = resolvedCall.getValueArguments()[argumentMatch.valueParameter] as? VarargValueArgument ?: return null
if (varargArgument.getArguments().size() != 1) return null
val varargArgument = resolvedCall.valueArguments[argumentMatch.valueParameter] as? VarargValueArgument ?: return null
if (varargArgument.arguments.size != 1) return null
}
return argumentMatch.valueParameter.getName()
return argumentMatch.valueParameter.name
}
}
@@ -21,14 +21,13 @@ import com.intellij.openapi.util.TextRange
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.inspections.RedundantSamConstructorInspection
import org.jetbrains.kotlin.idea.util.CommentSaver
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.psiUtil.contentRange
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class AnonymousFunctionToLambdaIntention : SelfTargetingRangeIntention<KtNamedFunction>(
KtNamedFunction::class.java,
@@ -32,39 +32,39 @@ import org.jetbrains.kotlin.resolve.BindingContext
public open class ChangeVisibilityModifierIntention protected constructor(
val modifier: KtModifierKeywordToken
) : SelfTargetingRangeIntention<KtDeclaration>(javaClass(), "Make ${modifier.getValue()}") {
) : SelfTargetingRangeIntention<KtDeclaration>(KtDeclaration::class.java, "Make ${modifier.value}") {
override fun applicabilityRange(element: KtDeclaration): TextRange? {
val modifierList = element.getModifierList()
val modifierList = element.modifierList
if (modifierList?.hasModifier(modifier) ?: false) return null
var descriptor = element.toDescriptor() as? DeclarationDescriptorWithVisibility ?: return null
val targetVisibility = modifier.toVisibility()
if (descriptor.getVisibility() == targetVisibility) return null
if (descriptor.visibility == targetVisibility) return null
if (modifierList?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false) {
val callableDescriptor = descriptor as? CallableDescriptor ?: return null
// cannot make visibility less than (or non-comparable with) any of the supers
if (callableDescriptor.getOverriddenDescriptors()
.map { Visibilities.compare(it.getVisibility(), targetVisibility) }
if (callableDescriptor.overriddenDescriptors
.map { Visibilities.compare(it.visibility, targetVisibility) }
.any { it == null || it > 0 }) return null
}
setText(defaultText)
text = defaultText
val modifierElement = element.visibilityModifier()
if (modifierElement != null) {
return modifierElement.getTextRange()
return modifierElement.textRange
}
val defaultRange = noModifierYetApplicabilityRange(element) ?: return null
if (element is KtPrimaryConstructor && defaultRange.isEmpty()) {
setText("Make primary constructor ${modifier.getValue()}") // otherwise it may be confusing
if (element is KtPrimaryConstructor && defaultRange.isEmpty) {
text = "Make primary constructor ${modifier.value}" // otherwise it may be confusing
}
return if (modifierList != null)
TextRange(modifierList.startOffset, defaultRange.getEndOffset()) //TODO: smaller range? now it includes annotations too
TextRange(modifierList.startOffset, defaultRange.endOffset) //TODO: smaller range? now it includes annotations too
else
defaultRange
}
@@ -73,7 +73,7 @@ public open class ChangeVisibilityModifierIntention protected constructor(
val bindingContext = analyze()
// TODO: temporary code
if (this is KtPrimaryConstructor) {
return (this.getContainingClassOrObject().resolveToDescriptor() as ClassDescriptor).getUnsubstitutedPrimaryConstructor()
return (this.getContainingClassOrObject().resolveToDescriptor() as ClassDescriptor).unsubstitutedPrimaryConstructor
}
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this]
@@ -100,13 +100,13 @@ public open class ChangeVisibilityModifierIntention protected constructor(
private fun noModifierYetApplicabilityRange(declaration: KtDeclaration): TextRange? {
if (KtPsiUtil.isLocal(declaration)) return null
return when (declaration) {
is KtNamedFunction -> declaration.getFunKeyword()?.getTextRange()
is KtProperty -> declaration.getValOrVarKeyword().getTextRange()
is KtClass -> declaration.getClassOrInterfaceKeyword()?.getTextRange()
is KtObjectDeclaration -> declaration.getObjectKeyword().getTextRange()
is KtPrimaryConstructor -> declaration.getValueParameterList()?.let { TextRange.from(it.startOffset, 0) } //TODO: use constructor keyword if exist
is KtSecondaryConstructor -> declaration.getConstructorKeyword().getTextRange()
is KtParameter -> declaration.getValOrVarKeyword()?.getTextRange()
is KtNamedFunction -> declaration.funKeyword?.textRange
is KtProperty -> declaration.valOrVarKeyword.textRange
is KtClass -> declaration.getClassOrInterfaceKeyword()?.textRange
is KtObjectDeclaration -> declaration.getObjectKeyword().textRange
is KtPrimaryConstructor -> declaration.valueParameterList?.let { TextRange.from(it.startOffset, 0) } //TODO: use constructor keyword if exist
is KtSecondaryConstructor -> declaration.getConstructorKeyword().textRange
is KtParameter -> declaration.valOrVarKeyword?.textRange
else -> null
}
}
@@ -115,11 +115,11 @@ public open class ChangeVisibilityModifierIntention protected constructor(
public class Private : ChangeVisibilityModifierIntention(KtTokens.PRIVATE_KEYWORD), HighPriorityAction {
override fun applicabilityRange(element: KtDeclaration): TextRange? {
return if (canBePrivate(element)) super<ChangeVisibilityModifierIntention>.applicabilityRange(element) else null
return if (canBePrivate(element)) super.applicabilityRange(element) else null
}
private fun canBePrivate(declaration: KtDeclaration): Boolean {
if (declaration.getModifierList()?.hasModifier(KtTokens.ABSTRACT_KEYWORD) ?: false) return false
if (declaration.modifierList?.hasModifier(KtTokens.ABSTRACT_KEYWORD) ?: false) return false
return true
}
}
@@ -130,9 +130,9 @@ public open class ChangeVisibilityModifierIntention protected constructor(
}
private fun canBeProtected(declaration: KtDeclaration): Boolean {
var parent = declaration.getParent()
var parent = declaration.parent
if (parent is KtClassBody) {
parent = parent.getParent()
parent = parent.parent
}
return parent is KtClass
}
@@ -16,18 +16,12 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.completion.InsertHandler
import com.intellij.codeInsight.completion.InsertionContext
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.codeInsight.template.Expression
import com.intellij.codeInsight.template.ExpressionContext
import com.intellij.codeInsight.template.Result
import com.intellij.codeInsight.template.TextResult
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.impl.TemplateState
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil
//TODO: move it somewhere else and reuse
@@ -41,21 +35,20 @@ public abstract class ChooseValueExpression<T : Any>(
protected abstract fun getResult(element: T): String
protected val lookupItems: Array<LookupElement> = lookupItems.map { suggestion ->
LookupElementBuilder.create(suggestion, getLookupString(suggestion)).withInsertHandler(object : InsertHandler<LookupElement> {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
val topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(context.getEditor())
val templateState = TemplateManagerImpl.getTemplateState(topLevelEditor)
if (templateState != null) {
val range = templateState.getCurrentVariableRange()
if (range != null) {
topLevelEditor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), getResult(item.getObject() as T))
}
LookupElementBuilder.create(suggestion, getLookupString(suggestion)).withInsertHandler { context, item ->
val topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(context.editor)
val templateState = TemplateManagerImpl.getTemplateState(topLevelEditor)
if (templateState != null) {
val range = templateState.currentVariableRange
if (range != null) {
@Suppress("UNCHECKED_CAST")
topLevelEditor.document.replaceString(range.startOffset, range.endOffset, getResult(item.`object` as T))
}
}
})
}
}.toTypedArray()
override fun calculateLookupItems(context: ExpressionContext) = if (lookupItems.size() > 1) lookupItems else null
override fun calculateLookupItems(context: ExpressionContext) = if (lookupItems.size > 1) lookupItems else null
override fun calculateQuickResult(context: ExpressionContext) = calculateResult(context)
@@ -30,24 +30,24 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.check
public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCallExpression>(javaClass(), "Replace 'assert' with 'if' statement"), LowPriorityAction {
public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCallExpression>(KtCallExpression::class.java, "Replace 'assert' with 'if' statement"), LowPriorityAction {
override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
val callee = element.getCalleeExpression() ?: return false
if (!callee.getTextRange().containsOffset(caretOffset)) return false
val callee = element.calleeExpression ?: return false
if (!callee.textRange.containsOffset(caretOffset)) return false
val argumentSize = element.getValueArguments().size()
val argumentSize = element.valueArguments.size
if (argumentSize !in 1..2) return false
val functionLiterals = element.getLambdaArguments()
if (functionLiterals.size() > 1) return false
if (functionLiterals.size() == 1 && argumentSize == 1) return false // "assert {...}" is incorrect
val functionLiterals = element.lambdaArguments
if (functionLiterals.size > 1) return false
if (functionLiterals.size == 1 && argumentSize == 1) return false // "assert {...}" is incorrect
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return false
return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).asString() == "kotlin.assert"
return DescriptorUtils.getFqName(resolvedCall.resultingDescriptor).asString() == "kotlin.assert"
}
override fun applyTo(element: KtCallExpression, editor: Editor) {
val args = element.getValueArguments()
val conditionText = args[0]?.getArgumentExpression()?.getText() ?: return
val args = element.valueArguments
val conditionText = args[0]?.getArgumentExpression()?.text ?: return
val functionLiteralArgument = element.lambdaArguments.singleOrNull()
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
val psiFactory = KtPsiFactory(element)
@@ -66,29 +66,29 @@ public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCall
val ifExpression = replaceWithIfThenThrowExpression(element)
// shorten java.lang.AssertionError
ShortenReferences.DEFAULT.process(ifExpression.getThen()!!)
ShortenReferences.DEFAULT.process(ifExpression.then!!)
val ifCondition = ifExpression.getCondition() as KtPrefixExpression
ifCondition.getBaseExpression()!!.replace(psiFactory.createExpression(conditionText))
val ifCondition = ifExpression.condition as KtPrefixExpression
ifCondition.baseExpression!!.replace(psiFactory.createExpression(conditionText))
val thrownExpression = ((ifExpression.getThen() as KtBlockExpression).getStatements().single() as KtThrowExpression).getThrownExpression()
val thrownExpression = ((ifExpression.then as KtBlockExpression).statements.single() as KtThrowExpression).thrownExpression
val assertionErrorCall = if (thrownExpression is KtCallExpression)
thrownExpression
else
(thrownExpression as KtDotQualifiedExpression).getSelectorExpression() as KtCallExpression
(thrownExpression as KtDotQualifiedExpression).selectorExpression as KtCallExpression
val message = psiFactory.createExpression(
if (messageIsFunction && messageExpr is KtCallableReferenceExpression) {
messageExpr.getCallableReference().getText() + "()"
messageExpr.callableReference.text + "()"
}
else if (messageIsFunction) {
messageExpr.getText() + "()"
messageExpr.text + "()"
}
else {
messageExpr.getText()
messageExpr.text
}
)
assertionErrorCall.getValueArguments().single().getArgumentExpression()!!.replace(message)
assertionErrorCall.valueArguments.single().getArgumentExpression()!!.replace(message)
simplifyConditionIfPossible(ifExpression)
}
@@ -101,12 +101,12 @@ public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCall
private fun messageIsFunction(callExpr: KtCallExpression, bindingContext: BindingContext): Boolean {
val resolvedCall = callExpr.getResolvedCall(bindingContext) ?: return false
val valParameters = resolvedCall.getResultingDescriptor().getValueParameters()
return valParameters.size() > 1 && !KotlinBuiltIns.isAny(valParameters[1].type)
val valParameters = resolvedCall.resultingDescriptor.valueParameters
return valParameters.size > 1 && !KotlinBuiltIns.isAny(valParameters[1].type)
}
private fun simplifyConditionIfPossible(ifExpression: KtIfExpression) {
val condition = ifExpression.getCondition() as KtPrefixExpression
val condition = ifExpression.condition as KtPrefixExpression
val simplifier = SimplifyNegatedBinaryExpressionIntention()
if (simplifier.isApplicableTo(condition)) {
simplifier.applyTo(condition)
@@ -115,7 +115,7 @@ public class ConvertAssertToIfWithThrowIntention : SelfTargetingIntention<KtCall
private fun replaceWithIfThenThrowExpression(original: KtCallExpression): KtIfExpression {
val replacement = KtPsiFactory(original).createExpression("if (!true) { throw java.lang.AssertionError(\"\") }") as KtIfExpression
val parent = original.getParent()
val parent = original.parent
return if (parent is KtDotQualifiedExpression)
parent.replaced(replacement)
else
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
public class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIntention<KtSimpleNameExpression>(javaClass(), "Replace with a 'for' loop") {
public class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIntention<KtSimpleNameExpression>(KtSimpleNameExpression::class.java, "Replace with a 'for' loop") {
private val FOR_EACH_NAME = "forEach"
private val FOR_EACH_FQ_NAMES = listOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$FOR_EACH_NAME" }.toSet()
@@ -33,8 +33,8 @@ public class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIn
if (element.getReferencedName() != FOR_EACH_NAME) return false
val data = extractData(element) ?: return false
if (data.functionLiteral.getValueParameters().size() > 1) return false
if (data.functionLiteral.getBodyExpression() == null) return false
if (data.functionLiteral.valueParameters.size > 1) return false
if (data.functionLiteral.bodyExpression == null) return false
return true
}
@@ -57,18 +57,18 @@ public class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIn
)
private fun extractData(nameExpr: KtSimpleNameExpression): Data? {
val parent = nameExpr.getParent()
val parent = nameExpr.parent
val expression = (when (parent) {
is KtCallExpression -> parent.getParent() as? KtDotQualifiedExpression
is KtCallExpression -> parent.parent as? KtDotQualifiedExpression
is KtBinaryExpression -> parent
else -> null
} ?: return null) as KtExpression //TODO: submit bug
val resolvedCall = expression.getResolvedCall(expression.analyze()) ?: return null
if (DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() !in FOR_EACH_FQ_NAMES) return null
if (DescriptorUtils.getFqName(resolvedCall.resultingDescriptor).toString() !in FOR_EACH_FQ_NAMES) return null
val receiver = resolvedCall.getCall().getExplicitReceiver() as? ExpressionReceiver ?: return null
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
val receiver = resolvedCall.call.explicitReceiver as? ExpressionReceiver ?: return null
val argument = resolvedCall.call.valueArguments.singleOrNull() ?: return null
val functionLiteral = argument.getArgumentExpression() as? KtLambdaExpression ?: return null
return Data(expression, receiver.expression, functionLiteral)
}
@@ -76,8 +76,8 @@ public class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIn
private fun generateLoop(functionLiteral: KtLambdaExpression, receiver: KtExpression): KtExpression {
val factory = KtPsiFactory(functionLiteral)
val loopRange = KtPsiUtil.safeDeparenthesize(receiver)
val body = functionLiteral.getBodyExpression()!!
val parameter = functionLiteral.getValueParameters().singleOrNull()
val body = functionLiteral.bodyExpression!!
val parameter = functionLiteral.valueParameters.singleOrNull()
return factory.createExpressionByPattern("for($0 in $1){ $2 }", parameter ?: "it", loopRange, body)
}
}
@@ -56,13 +56,13 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.types.typeUtil.supertypes
import java.util.*
public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamedFunction>(javaClass(), "Convert function to property"), LowPriorityAction {
public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamedFunction>(KtNamedFunction::class.java, "Convert function to property"), LowPriorityAction {
private var KtNamedFunction.typeFqNameToAdd: String? by UserDataProperty(Key.create("TYPE_FQ_NAME_TO_ADD"))
private inner class Converter(
project: Project,
descriptor: FunctionDescriptor
): CallableRefactoring<FunctionDescriptor>(project, descriptor, getText()) {
): CallableRefactoring<FunctionDescriptor>(project, descriptor, text) {
private val elementsToShorten = ArrayList<KtElement>()
private val newName: String by lazy {
@@ -75,31 +75,31 @@ public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamed
val propertySample = psiFactory.createProperty("val foo: Int get() = 1")
val needsExplicitType = function.getTypeReference() == null
val needsExplicitType = function.typeReference == null
if (needsExplicitType) {
originalFunction.typeFqNameToAdd?.let { function.setTypeReference(psiFactory.createType(it)) }
}
function.getFunKeyword()!!.replace(propertySample.getValOrVarKeyword())
function.getValueParameterList()?.delete()
val insertAfter = (function.getEqualsToken() ?: function.getBodyExpression())
function.funKeyword!!.replace(propertySample.valOrVarKeyword)
function.valueParameterList?.delete()
val insertAfter = (function.equalsToken ?: function.bodyExpression)
?.siblings(forward = false, withItself = false)
?.firstOrNull { it !is PsiWhiteSpace }
if (insertAfter != null) {
function.addAfter(psiFactory.createParameterList("()"), insertAfter)
function.addAfter(propertySample.getGetter()!!.getNamePlaceholder(), insertAfter)
function.addAfter(propertySample.getter!!.namePlaceholder, insertAfter)
}
function.setName(newName)
val property = originalFunction.replace(psiFactory.createProperty(function.getText())) as KtProperty
val property = originalFunction.replace(psiFactory.createProperty(function.text)) as KtProperty
if (needsExplicitType) {
elementsToShorten.add(property.getTypeReference()!!)
elementsToShorten.add(property.typeReference!!)
}
}
override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) {
val conflicts = MultiMap<PsiElement, String>()
val getterName = JvmAbi.getterName(callableDescriptor.getName().asString())
val getterName = JvmAbi.getterName(callableDescriptor.name.asString())
val callables = getAffectedCallables(project, descriptorsForChange)
val kotlinCalls = ArrayList<KtCallElement>()
val kotlinRefsToRename = ArrayList<PsiReference>()
@@ -112,13 +112,13 @@ public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamed
}
if (callable is KtNamedFunction) {
if (callable.getTypeReference() == null) {
if (callable.typeReference == null) {
val functionDescriptor = callable.resolveToDescriptor() as FunctionDescriptor
val type = functionDescriptor.getReturnType()
val type = functionDescriptor.returnType
val typeToInsert = when {
type == null || type.isError() -> null
type.getConstructor().isDenotable() -> type
else -> type.supertypes().firstOrNull { it.getConstructor().isDenotable() }
type == null || type.isError -> null
type.constructor.isDenotable -> type
else -> type.supertypes().firstOrNull { it.constructor.isDenotable }
} ?: functionDescriptor.builtIns.nullableAnyType
callable.typeFqNameToAdd = IdeDescriptorRenderers.SOURCE_CODE.renderType(typeToInsert)
}
@@ -130,10 +130,10 @@ public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamed
}
if (callable is PsiMethod) {
callable.getContainingClass()
callable.containingClass
?.findMethodsByName(getterName, true)
// as is necessary here: see KT-10386
?.firstOrNull { it.getParameterList().getParametersCount() == 0 && it.namedUnwrappedElement as PsiElement? !in callables }
?.firstOrNull { it.parameterList.parametersCount == 0 && !callables.contains(it.namedUnwrappedElement as PsiElement?) }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
@@ -141,19 +141,19 @@ public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamed
for (usage in usages) {
if (usage is KtSimpleNameReference) {
val expression = usage.expression
val callElement = expression.getParentOfTypeAndBranch<KtCallElement> { getCalleeExpression() }
val callElement = expression.getParentOfTypeAndBranch<KtCallElement> { calleeExpression }
if (callElement != null && expression.getStrictParentOfType<KtCallableReferenceExpression>() == null) {
if (callElement.getTypeArguments().isNotEmpty()) {
if (callElement.typeArguments.isNotEmpty()) {
conflicts.putValue(
callElement,
"Type arguments will be lost after conversion: ${StringUtil.htmlEmphasize(callElement.getText())}"
"Type arguments will be lost after conversion: ${StringUtil.htmlEmphasize(callElement.text)}"
)
}
if (callElement.getValueArguments().isNotEmpty()) {
if (callElement.valueArguments.isNotEmpty()) {
conflicts.putValue(
callElement,
"Call with arguments will be skipped: ${StringUtil.htmlEmphasize(callElement.getText())}"
"Call with arguments will be skipped: ${StringUtil.htmlEmphasize(callElement.text)}"
)
continue
}
@@ -171,7 +171,7 @@ public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamed
}
project.checkConflictsInteractively(conflicts) {
project.executeWriteCommand(getText()) {
project.executeWriteCommand(text) {
val psiFactory = KtPsiFactory(project)
val newGetterName = JvmAbi.getterName(newName)
val newRefExpr = psiFactory.createExpression(newName)
@@ -195,25 +195,25 @@ public class ConvertFunctionToPropertyIntention : SelfTargetingIntention<KtNamed
override fun startInWriteAction(): Boolean = false
override fun isApplicableTo(element: KtNamedFunction, caretOffset: Int): Boolean {
val identifier = element.getNameIdentifier() ?: return false
if (!identifier.getTextRange().containsOffset(caretOffset)) return false
val identifier = element.nameIdentifier ?: return false
if (!identifier.textRange.containsOffset(caretOffset)) return false
if (element.getValueParameters().isNotEmpty() || element.isLocal()) return false
if (element.valueParameters.isNotEmpty() || element.isLocal) return false
val name = element.getName()!!
if (name == "invoke" || name == "iterator" || Name.identifier(name) in OperatorConventions.UNARY_OPERATION_NAMES.inverse().keySet()) {
val name = element.name!!
if (name == "invoke" || name == "iterator" || Name.identifier(name) in OperatorConventions.UNARY_OPERATION_NAMES.inverse().keys) {
return false
}
val descriptor = element.analyze(BodyResolveMode.PARTIAL)[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? FunctionDescriptor
?: return false
val returnType = descriptor.getReturnType() ?: return false
val returnType = descriptor.returnType ?: return false
return !KotlinBuiltIns.isUnit(returnType) && !KotlinBuiltIns.isNothing(returnType)
}
override fun applyTo(element: KtNamedFunction, editor: Editor) {
val context = element.analyze(BodyResolveMode.PARTIAL)
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as FunctionDescriptor
Converter(element.getProject(), descriptor).run()
Converter(element.project, descriptor).run()
}
}
@@ -17,48 +17,46 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.unwrapBlockOrParenthesis
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.core.copied
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.unwrapBlockOrParenthesis
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
public class ConvertIfWithThrowToAssertIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(javaClass(), "Replace 'if' with 'assert' statement") {
public class ConvertIfWithThrowToAssertIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' with 'assert' statement") {
override fun isApplicableTo(element: KtIfExpression): Boolean {
if (element.getElse() != null) return false
if (element.`else` != null) return false
val throwExpr = element.getThen()?.unwrapBlockOrParenthesis() as? KtThrowExpression
val thrownExpr = getSelector(throwExpr?.getThrownExpression())
val throwExpr = element.then?.unwrapBlockOrParenthesis() as? KtThrowExpression
val thrownExpr = getSelector(throwExpr?.thrownExpression)
if (thrownExpr !is KtCallExpression) return false
if (thrownExpr.getValueArguments().size() > 1) return false
if (thrownExpr.valueArguments.size > 1) return false
val resolvedCall = thrownExpr.getResolvedCall(thrownExpr.analyze()) ?: return false
return DescriptorUtils.getFqName(resolvedCall.getResultingDescriptor()).toString() == "java.lang.AssertionError.<init>"
return DescriptorUtils.getFqName(resolvedCall.resultingDescriptor).toString() == "java.lang.AssertionError.<init>"
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
val condition = element.getCondition() ?: return
val condition = element.condition ?: return
val thenExpr = element.getThen()?.unwrapBlockOrParenthesis() as KtThrowExpression
val thrownExpr = getSelector(thenExpr.getThrownExpression()) as KtCallExpression
val thenExpr = element.then?.unwrapBlockOrParenthesis() as KtThrowExpression
val thrownExpr = getSelector(thenExpr.thrownExpression) as KtCallExpression
val psiFactory = KtPsiFactory(element)
condition.replace(psiFactory.createExpressionByPattern("!$0", condition))
var newCondition = element.getCondition()!!
var newCondition = element.condition!!
val simplifier = SimplifyNegatedBinaryExpressionIntention()
if (simplifier.isApplicableTo(newCondition as KtPrefixExpression)) {
simplifier.applyTo(newCondition, editor)
newCondition = element.getCondition()!!
newCondition = element.condition!!
}
val arg = thrownExpr.getValueArguments().singleOrNull()?.getArgumentExpression()
val arg = thrownExpr.valueArguments.singleOrNull()?.getArgumentExpression()
val assertExpr = if (arg != null && !arg.isNullExpression())
psiFactory.createExpressionByPattern("kotlin.assert($0) {$1}", newCondition, arg)
else
@@ -70,7 +68,7 @@ public class ConvertIfWithThrowToAssertIntention : SelfTargetingOffsetIndependen
private fun getSelector(element: KtExpression?): KtExpression? {
if (element is KtDotQualifiedExpression) {
return element.getSelectorExpression()
return element.selectorExpression
}
return element
}
@@ -17,32 +17,30 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import java.util.LinkedList
import java.util.*
public class ConvertNegatedBooleanSequenceIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(
javaClass(), "Replace negated sequence with DeMorgan equivalent") {
KtBinaryExpression::class.java, "Replace negated sequence with DeMorgan equivalent"
) {
override fun isApplicableTo(element: KtBinaryExpression): Boolean {
if (element.getParent() is KtBinaryExpression) return false // operate only on the longest sequence
val opToken = element.getOperationToken()
if (element.parent is KtBinaryExpression) return false // operate only on the longest sequence
val opToken = element.operationToken
if (opToken != KtTokens.ANDAND && opToken != KtTokens.OROR) return false
return splitBooleanSequence(element) != null
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
val operatorText = when(element.getOperationToken()) {
KtTokens.ANDAND -> KtTokens.OROR.getValue()
KtTokens.OROR -> KtTokens.ANDAND.getValue()
val operatorText = when(element.operationToken) {
KtTokens.ANDAND -> KtTokens.OROR.value
KtTokens.OROR -> KtTokens.ANDAND.value
else -> throw IllegalArgumentException() // checked in isApplicableTo
}
val elements = splitBooleanSequence(element)!!
val bareExpressions = elements.map { prefixExpression -> prefixExpression.getBaseExpression()!!.getText() }
val bareExpressions = elements.map { prefixExpression -> prefixExpression.baseExpression!!.text }
val negatedExpression = bareExpressions.subList(0, bareExpressions.lastIndex).foldRight(
"!(${bareExpressions.last()}", { negated, expression -> "$expression $operatorText $negated" }
)
@@ -50,7 +48,7 @@ public class ConvertNegatedBooleanSequenceIntention : SelfTargetingOffsetIndepen
val newExpression = KtPsiFactory(element).createExpression("$negatedExpression)")
val insertedElement = element.replace(newExpression)
val insertedElementParent = insertedElement.getParent() as? KtParenthesizedExpression ?: return
val insertedElementParent = insertedElement.parent as? KtParenthesizedExpression ?: return
if (KtPsiUtil.areParenthesesUseless(insertedElementParent)) {
insertedElementParent.replace(insertedElement)
@@ -59,16 +57,16 @@ public class ConvertNegatedBooleanSequenceIntention : SelfTargetingOffsetIndepen
private fun splitBooleanSequence(expression: KtBinaryExpression): List<KtPrefixExpression>? {
val itemList = LinkedList<KtPrefixExpression>()
val firstOperator = expression.getOperationToken()
val firstOperator = expression.operationToken
var currentItem: KtBinaryExpression? = expression
while (currentItem != null) {
if (currentItem.getOperationToken() != firstOperator) return null //Boolean sequence must be homogeneous
if (currentItem.operationToken != firstOperator) return null //Boolean sequence must be homogeneous
val rightChild = currentItem.getRight() as? KtPrefixExpression ?: return null
val rightChild = currentItem.right as? KtPrefixExpression ?: return null
itemList.add(rightChild)
val leftChild = currentItem.getLeft()
val leftChild = currentItem.left
when (leftChild) {
is KtPrefixExpression -> itemList.add(leftChild)
!is KtBinaryExpression -> return null
@@ -21,18 +21,17 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import java.util.*
public class ConvertNegatedExpressionWithDemorgansLawIntention : SelfTargetingOffsetIndependentIntention<KtPrefixExpression>(javaClass(), "DeMorgan Law") {
public class ConvertNegatedExpressionWithDemorgansLawIntention : SelfTargetingOffsetIndependentIntention<KtPrefixExpression>(KtPrefixExpression::class.java, "DeMorgan Law") {
override fun isApplicableTo(element: KtPrefixExpression): Boolean {
val prefixOperator = element.getOperationReference().getReferencedNameElementType()
val prefixOperator = element.operationReference.getReferencedNameElementType()
if (prefixOperator != KtTokens.EXCL) return false
val parenthesizedExpression = element.getBaseExpression() as? KtParenthesizedExpression
val baseExpression = parenthesizedExpression?.getExpression() as? KtBinaryExpression ?: return false
val parenthesizedExpression = element.baseExpression as? KtParenthesizedExpression
val baseExpression = parenthesizedExpression?.expression as? KtBinaryExpression ?: return false
when (baseExpression.getOperationToken()) {
KtTokens.ANDAND -> setText("Replace '&&' with '||'")
KtTokens.OROR -> setText("Replace '||' with '&&'")
when (baseExpression.operationToken) {
KtTokens.ANDAND -> text = "Replace '&&' with '||'"
KtTokens.OROR -> text = "Replace '||' with '&&'"
else -> return false
}
@@ -44,12 +43,12 @@ public class ConvertNegatedExpressionWithDemorgansLawIntention : SelfTargetingOf
}
fun applyTo(element: KtPrefixExpression) {
val parenthesizedExpression = element.getBaseExpression() as KtParenthesizedExpression
val baseExpression = parenthesizedExpression.getExpression() as KtBinaryExpression
val parenthesizedExpression = element.baseExpression as KtParenthesizedExpression
val baseExpression = parenthesizedExpression.expression as KtBinaryExpression
val operatorText = when (baseExpression.getOperationToken()) {
KtTokens.ANDAND -> KtTokens.OROR.getValue()
KtTokens.OROR -> KtTokens.ANDAND.getValue()
val operatorText = when (baseExpression.operationToken) {
KtTokens.ANDAND -> KtTokens.OROR.value
KtTokens.OROR -> KtTokens.ANDAND.value
else -> throw IllegalArgumentException()
}
@@ -64,19 +63,19 @@ public class ConvertNegatedExpressionWithDemorgansLawIntention : SelfTargetingOf
private fun splitBooleanSequence(expression: KtBinaryExpression): List<KtExpression>? {
val result = ArrayList<KtExpression>()
val firstOperator = expression.getOperationToken()
val firstOperator = expression.operationToken
var remainingExpression: KtExpression = expression
while (true) {
if (remainingExpression !is KtBinaryExpression) break
val operation = remainingExpression.getOperationToken()
val operation = remainingExpression.operationToken
if (operation != KtTokens.ANDAND && operation != KtTokens.OROR) break
if (operation != firstOperator) return null //Boolean sequence must be homogenous
result.add(remainingExpression.getRight() ?: return null)
remainingExpression = remainingExpression.getLeft() ?: return null
result.add(remainingExpression.right ?: return null)
remainingExpression = remainingExpression.left ?: return null
}
result.add(remainingExpression)
@@ -29,19 +29,19 @@ import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
public class ConvertParameterToReceiverIntention : SelfTargetingIntention<KtParameter>(javaClass(), "Convert parameter to receiver") {
public class ConvertParameterToReceiverIntention : SelfTargetingIntention<KtParameter>(KtParameter::class.java, "Convert parameter to receiver") {
override fun isApplicableTo(element: KtParameter, caretOffset: Int): Boolean {
val identifier = element.getNameIdentifier() ?: return false
if (!identifier.getTextRange().containsOffset(caretOffset)) return false
if (element.isVarArg()) return false
val identifier = element.nameIdentifier ?: return false
if (!identifier.textRange.containsOffset(caretOffset)) return false
if (element.isVarArg) return false
val function = element.getStrictParentOfType<KtNamedFunction>() ?: return false
return function.getValueParameterList() == element.getParent() && function.getReceiverTypeReference() == null
return function.valueParameterList == element.parent && function.receiverTypeReference == null
}
private fun configureChangeSignature(parameterIndex: Int): KotlinChangeSignatureConfiguration {
return object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify { it.receiver = originalDescriptor.getParameters()[parameterIndex] }
return originalDescriptor.modify { it.receiver = originalDescriptor.parameters[parameterIndex] }
}
override fun performSilently(affectedFunctions: Collection<PsiElement>) = true
@@ -52,9 +52,9 @@ public class ConvertParameterToReceiverIntention : SelfTargetingIntention<KtPara
override fun applyTo(element: KtParameter, editor: Editor) {
val function = element.getStrictParentOfType<KtNamedFunction>() ?: return
val parameterIndex = function.getValueParameters().indexOf(element)
val parameterIndex = function.valueParameters.indexOf(element)
val context = function.analyze()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor ?: return
runChangeSignature(element.project, descriptor, configureChangeSignature(parameterIndex), element, getText())
runChangeSignature(element.project, descriptor, configureChangeSignature(parameterIndex), element, text)
}
}
@@ -17,16 +17,11 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
class ConvertPropertyInitializerToGetterIntention : SelfTargetingIntention<KtProperty>(javaClass(), "Convert property initializer to getter") {
class ConvertPropertyInitializerToGetterIntention : SelfTargetingIntention<KtProperty>(KtProperty::class.java, "Convert property initializer to getter") {
override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean {
return element.initializer != null
&& element.initializer?.textRange?.containsOffset(caretOffset) == true
@@ -35,8 +30,8 @@ class ConvertPropertyInitializerToGetterIntention : SelfTargetingIntention<KtPro
&& !element.isLocal
}
override fun applyTo(property: KtProperty, editor: Editor) {
convertPropertyInitializerToGetter(property, editor)
override fun applyTo(element: KtProperty, editor: Editor) {
convertPropertyInitializerToGetter(element, editor)
}
companion object {
@@ -50,44 +50,44 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
import java.util.*
public class ConvertPropertyToFunctionIntention : SelfTargetingIntention<KtProperty>(javaClass(), "Convert property to function"), LowPriorityAction {
public class ConvertPropertyToFunctionIntention : SelfTargetingIntention<KtProperty>(KtProperty::class.java, "Convert property to function"), LowPriorityAction {
private inner class Converter(
project: Project,
descriptor: CallableDescriptor
): CallableRefactoring<CallableDescriptor>(project, descriptor, getText()) {
): CallableRefactoring<CallableDescriptor>(project, descriptor, text) {
private val newName: String = JvmAbi.getterName(callableDescriptor.name.asString())
private fun convertProperty(originalProperty: KtProperty, psiFactory: KtPsiFactory) {
val property = originalProperty.copy() as KtProperty;
val getter = property.getGetter();
val getter = property.getter;
val sampleFunction = psiFactory.createFunction("fun foo() {\n\n}");
property.getValOrVarKeyword().replace(sampleFunction.getFunKeyword()!!);
property.addAfter(psiFactory.createParameterList("()"), property.getNameIdentifier());
if (property.getInitializer() == null) {
property.valOrVarKeyword.replace(sampleFunction.funKeyword!!);
property.addAfter(psiFactory.createParameterList("()"), property.nameIdentifier);
if (property.initializer == null) {
if (getter != null) {
val dropGetterTo = (getter.getEqualsToken() ?: getter.getBodyExpression())
val dropGetterTo = (getter.equalsToken ?: getter.bodyExpression)
?.siblings(forward = false, withItself = false)
?.firstOrNull { it !is PsiWhiteSpace }
getter.deleteChildRange(getter.getFirstChild(), dropGetterTo)
getter.deleteChildRange(getter.firstChild, dropGetterTo)
val dropPropertyFrom = getter
.siblings(forward = false, withItself = false)
.first { it !is PsiWhiteSpace }
.getNextSibling()
property.deleteChildRange(dropPropertyFrom, getter.getPrevSibling())
.nextSibling
property.deleteChildRange(dropPropertyFrom, getter.prevSibling)
}
}
property.setName(newName)
originalProperty.replace(psiFactory.createFunction(property.getText()))
originalProperty.replace(psiFactory.createFunction(property.text))
}
override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) {
val propertyName = callableDescriptor.getName().asString()
val propertyName = callableDescriptor.name.asString()
val nameChanged = propertyName != newName
val getterName = JvmAbi.getterName(callableDescriptor.getName().asString())
val getterName = JvmAbi.getterName(callableDescriptor.name.asString())
val conflicts = MultiMap<PsiElement, String>()
val callables = getAffectedCallables(project, descriptorsForChange)
val kotlinRefsToReplaceWithCall = ArrayList<KtSimpleNameExpression>()
@@ -108,10 +108,10 @@ public class ConvertPropertyToFunctionIntention : SelfTargetingIntention<KtPrope
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
else if (callable is PsiMethod) {
callable.getContainingClass()
callable.containingClass
?.findMethodsByName(propertyName, true)
// as is necessary here: see KT-10386
?.firstOrNull { it.getParameterList().getParametersCount() == 0 && it.namedUnwrappedElement as PsiElement? !in callables }
?.firstOrNull { it.parameterList.parametersCount == 0 && !callables.contains(it.namedUnwrappedElement as PsiElement?) }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
@@ -129,18 +129,18 @@ public class ConvertPropertyToFunctionIntention : SelfTargetingIntention<KtPrope
}
}
else {
val refElement = usage.getElement()
val refElement = usage.element
conflicts.putValue(
refElement,
"Unrecognized reference will be skipped: " + StringUtil.htmlEmphasize(refElement.getText())
"Unrecognized reference will be skipped: " + StringUtil.htmlEmphasize(refElement.text)
)
}
continue
}
val refElement = usage.getElement()
val refElement = usage.element
if (refElement.getText().endsWith(getterName)) continue
if (refElement.text.endsWith(getterName)) continue
if (usage is PsiJavaReference) {
if (usage.resolve() is PsiField && usage is PsiReferenceExpression) {
@@ -151,13 +151,13 @@ public class ConvertPropertyToFunctionIntention : SelfTargetingIntention<KtPrope
conflicts.putValue(
refElement,
"Can't replace foreign reference with call expression: " + StringUtil.htmlEmphasize(refElement.getText())
"Can't replace foreign reference with call expression: " + StringUtil.htmlEmphasize(refElement.text)
)
}
}
project.checkConflictsInteractively(conflicts) {
project.executeWriteCommand(getText()) {
project.executeWriteCommand(text) {
val kotlinPsiFactory = KtPsiFactory(project)
val javaPsiFactory = PsiElementFactory.SERVICE.getInstance(project)
val newKotlinCallExpr = kotlinPsiFactory.createExpression("$newName()")
@@ -182,14 +182,14 @@ public class ConvertPropertyToFunctionIntention : SelfTargetingIntention<KtPrope
override fun startInWriteAction(): Boolean = false
override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean {
val identifier = element.getNameIdentifier() ?: return false
if (!identifier.getTextRange().containsOffset(caretOffset)) return false
return element.getDelegate() == null && !element.isVar() && !element.isLocal()
val identifier = element.nameIdentifier ?: return false
if (!identifier.textRange.containsOffset(caretOffset)) return false
return element.delegate == null && !element.isVar && !element.isLocal
}
override fun applyTo(element: KtProperty, editor: Editor) {
val context = element.analyze()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableDescriptor ?: return
Converter(element.getProject(), descriptor).run()
Converter(element.project, descriptor).run()
}
}
@@ -28,9 +28,9 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingContext
public class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependentIntention<KtTypeReference>(javaClass(), "Convert receiver to parameter"), LowPriorityAction {
public class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependentIntention<KtTypeReference>(KtTypeReference::class.java, "Convert receiver to parameter"), LowPriorityAction {
override fun isApplicableTo(element: KtTypeReference): Boolean {
return (element.getParent() as? KtNamedFunction)?.getReceiverTypeReference() == element
return (element.parent as? KtNamedFunction)?.receiverTypeReference == element
}
private fun configureChangeSignature(): KotlinChangeSignatureConfiguration {
@@ -44,9 +44,9 @@ public class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependen
override fun startInWriteAction() = false
override fun applyTo(element: KtTypeReference, editor: Editor) {
val function = element.getParent() as? KtNamedFunction ?: return
val function = element.parent as? KtNamedFunction ?: return
val context = function.analyze()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor ?: return
runChangeSignature(element.project, descriptor, configureChangeSignature(), element, getText())
runChangeSignature(element.project, descriptor, configureChangeSignature(), element, text)
}
}
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.KotlinType
public class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationWithBody>(
javaClass(), "Convert to block body"
KtDeclarationWithBody::class.java, "Convert to block body"
), LowPriorityAction {
override fun isApplicableTo(element: KtDeclarationWithBody, caretOffset: Int): Boolean {
if (element is KtFunctionLiteral || element.hasBlockBody() || !element.hasBody()) return false
@@ -35,7 +35,7 @@ public class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationW
when (element) {
is KtNamedFunction -> {
val returnType = element.returnType() ?: return false
if (!element.hasDeclaredReturnType() && returnType.isError()) return false// do not convert when type is implicit and unknown
if (!element.hasDeclaredReturnType() && returnType.isError) return false// do not convert when type is implicit and unknown
return true
}
@@ -53,7 +53,7 @@ public class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationW
companion object {
public fun convert(declaration: KtDeclarationWithBody): KtDeclarationWithBody {
val body = declaration.getBodyExpression()!!
val body = declaration.bodyExpression!!
fun generateBody(returnsValue: Boolean): KtExpression {
val bodyType = body.analyze().getType(body)
@@ -74,19 +74,19 @@ public class ConvertToBlockBodyIntention : SelfTargetingIntention<KtDeclarationW
generateBody(!KotlinBuiltIns.isUnit(returnType) && !KotlinBuiltIns.isNothing(returnType))
}
is KtPropertyAccessor -> generateBody(declaration.isGetter())
is KtPropertyAccessor -> generateBody(declaration.isGetter)
else -> throw RuntimeException("Unknown declaration type: $declaration")
}
declaration.getEqualsToken()!!.delete()
declaration.equalsToken!!.delete()
body.replace(newBody)
return declaration
}
private fun KtNamedFunction.returnType(): KotlinType? {
val descriptor = analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, this] ?: return null
return (descriptor as FunctionDescriptor).getReturnType()
return (descriptor as FunctionDescriptor).returnType
}
}
}
@@ -22,21 +22,20 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContextUtils
public class ConvertToConcatenatedStringIntention : SelfTargetingOffsetIndependentIntention<KtStringTemplateExpression>(javaClass(), "Convert template to concatenated string"), LowPriorityAction {
public class ConvertToConcatenatedStringIntention : SelfTargetingOffsetIndependentIntention<KtStringTemplateExpression>(KtStringTemplateExpression::class.java, "Convert template to concatenated string"), LowPriorityAction {
override fun isApplicableTo(element: KtStringTemplateExpression): Boolean {
if (element.getLastChild().getNode().getElementType() != KtTokens.CLOSING_QUOTE) return false // not available for unclosed literal
return element.getEntries().any { it is KtStringTemplateEntryWithExpression }
if (element.lastChild.node.elementType != KtTokens.CLOSING_QUOTE) return false // not available for unclosed literal
return element.entries.any { it is KtStringTemplateEntryWithExpression }
}
override fun applyTo(element: KtStringTemplateExpression, editor: Editor) {
val tripleQuoted = isTripleQuoted(element.getText()!!)
val tripleQuoted = isTripleQuoted(element.text!!)
val quote = if (tripleQuoted) "\"\"\"" else "\""
val entries = element.getEntries()
val entries = element.entries
val text = entries
.filterNot { it is KtStringTemplateEntryWithExpression && it.getExpression() == null }
.filterNot { it is KtStringTemplateEntryWithExpression && it.expression == null }
.mapIndexed { index, entry ->
entry.toSeparateString(quote, convertExplicitly = (index == 0), isFinalEntry = (index == entries.lastIndex))
}
@@ -51,15 +50,15 @@ public class ConvertToConcatenatedStringIntention : SelfTargetingOffsetIndepende
private fun KtStringTemplateEntry.toSeparateString(quote: String, convertExplicitly: Boolean, isFinalEntry: Boolean): String {
if (this !is KtStringTemplateEntryWithExpression) {
return getText().quote(quote)
return text.quote(quote)
}
val expression = getExpression()!! // checked before
val expression = expression!! // checked before
val text = if (needsParenthesis(expression, isFinalEntry))
"(" + expression.getText() + ")"
"(" + expression.text + ")"
else
expression.getText()
expression.text
return if (convertExplicitly && !expression.isStringExpression())
text + ".toString()"
@@ -70,7 +69,7 @@ public class ConvertToConcatenatedStringIntention : SelfTargetingOffsetIndepende
private fun needsParenthesis(expression: KtExpression, isFinalEntry: Boolean): Boolean {
return when (expression) {
is KtBinaryExpression -> true
is KtIfExpression -> expression.getElse() !is KtBlockExpression && !isFinalEntry
is KtIfExpression -> expression.`else` !is KtBlockExpression && !isFinalEntry
else -> false
}
}
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.utils.addToStdlib.check
public class ConvertToExpressionBodyIntention : SelfTargetingOffsetIndependentIntention<KtDeclarationWithBody>(
javaClass(), "Convert to expression body"
KtDeclarationWithBody::class.java, "Convert to expression body"
) {
override fun isApplicableTo(element: KtDeclarationWithBody): Boolean {
val value = calcValue(element) ?: return false
@@ -53,7 +53,7 @@ public class ConvertToExpressionBodyIntention : SelfTargetingOffsetIndependentIn
public fun applyTo(declaration: KtDeclarationWithBody, canDeleteTypeRef: Boolean) {
val deleteTypeHandler: (KtCallableDeclaration) -> Unit = {
it.deleteChildRange(it.getColon()!!, it.getTypeReference()!!)
it.deleteChildRange(it.colon!!, it.typeReference!!)
}
applyTo(declaration, deleteTypeHandler.check { canDeleteTypeRef })
}
@@ -68,7 +68,7 @@ public class ConvertToExpressionBodyIntention : SelfTargetingOffsetIndependentIn
}
}
val body = declaration.getBodyExpression()!!
val body = declaration.bodyExpression!!
val commentSaver = CommentSaver(body)
@@ -86,13 +86,13 @@ public class ConvertToExpressionBodyIntention : SelfTargetingOffsetIndependentIn
private fun calcValue(declaration: KtDeclarationWithBody): KtExpression? {
if (declaration is KtFunctionLiteral) return null
val body = declaration.getBodyExpression()
val body = declaration.bodyExpression
if (!declaration.hasBlockBody() || body !is KtBlockExpression) return null
val statement = body.getStatements().singleOrNull() ?: return null
val statement = body.statements.singleOrNull() ?: return null
when(statement) {
is KtReturnExpression -> {
return statement.getReturnedExpression()
return statement.returnedExpression
}
//TODO: IMO this is not good code, there should be a way to detect that JetExpression does not have value
@@ -25,23 +25,23 @@ import org.jetbrains.kotlin.psi.createExpressionByPattern
import org.jetbrains.kotlin.psi.psiUtil.contentRange
import org.jetbrains.kotlin.psi.psiUtil.endOffset
public class ConvertToForEachFunctionCallIntention : SelfTargetingIntention<KtForExpression>(javaClass(), "Replace with a 'forEach' function call") {
public class ConvertToForEachFunctionCallIntention : SelfTargetingIntention<KtForExpression>(KtForExpression::class.java, "Replace with a 'forEach' function call") {
override fun isApplicableTo(element: KtForExpression, caretOffset: Int): Boolean {
val rParen = element.getRightParenthesis() ?: return false
val rParen = element.rightParenthesis ?: return false
if (caretOffset > rParen.endOffset) return false // available only on the loop header, not in the body
return element.getLoopRange() != null && element.getLoopParameter() != null && element.getBody() != null
return element.loopRange != null && element.loopParameter != null && element.body != null
}
override fun applyTo(element: KtForExpression, editor: Editor) {
val commentSaver = CommentSaver(element)
val body = element.getBody()!!
val loopParameter = element.getLoopParameter()!!
val body = element.body!!
val loopParameter = element.loopParameter!!
val functionBodyArgument: Any = if (body is KtBlockExpression) body.contentRange() else body
val foreachExpression = KtPsiFactory(element).createExpressionByPattern(
"$0.forEach{$1->$2}", element.getLoopRange()!!, loopParameter, functionBodyArgument)
"$0.forEach{$1->$2}", element.loopRange!!, loopParameter, functionBodyArgument)
val result = element.replace(foreachExpression)
commentSaver.restore(result)
@@ -32,11 +32,11 @@ public class ConvertToStringTemplateInspection : IntentionBasedInspection<KtBina
{ ConvertToStringTemplateIntention().shouldSuggestToConvert(it) }
)
public class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(javaClass(), "Convert concatenation to template") {
public class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Convert concatenation to template") {
override fun isApplicableTo(element: KtBinaryExpression): Boolean {
if (!isApplicableToNoParentCheck(element)) return false
val parent = element.getParent()
val parent = element.parent
if (parent is KtBinaryExpression && isApplicableToNoParentCheck(parent)) return false
return true
@@ -58,25 +58,25 @@ public class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIn
}
private fun isApplicableToNoParentCheck(expression: KtBinaryExpression): Boolean {
if (expression.getOperationToken() != KtTokens.PLUS) return false
if (expression.operationToken != KtTokens.PLUS) return false
if (!KotlinBuiltIns.isString(expression.analyze().getType(expression))) return false
val left = expression.getLeft() ?: return false
val right = expression.getRight() ?: return false
val left = expression.left ?: return false
val right = expression.right ?: return false
return !PsiUtilCore.hasErrorElementChild(left) && !PsiUtilCore.hasErrorElementChild(right)
}
private fun buildReplacement(expression: KtBinaryExpression): KtStringTemplateExpression {
val rightText = buildText(expression.getRight(), false)
return fold(expression.getLeft(), rightText, KtPsiFactory(expression))
val rightText = buildText(expression.right, false)
return fold(expression.left, rightText, KtPsiFactory(expression))
}
private fun fold(left: KtExpression?, right: String, factory: KtPsiFactory): KtStringTemplateExpression {
val forceBraces = !right.isEmpty() && right.first() != '$' && right.first().isJavaIdentifierPart()
if (left is KtBinaryExpression && isApplicableToNoParentCheck(left)) {
val leftRight = buildText(left.getRight(), forceBraces)
return fold(left.getLeft(), leftRight + right, factory)
val leftRight = buildText(left.right, forceBraces)
return fold(left.left, leftRight + right, factory)
}
else {
val leftText = buildText(left, forceBraces)
@@ -87,7 +87,7 @@ public class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIn
private fun buildText(expr: KtExpression?, forceBraces: Boolean): String {
if (expr == null) return ""
val expression = KtPsiUtil.safeDeparenthesize(expr)
val expressionText = expression.getText()
val expressionText = expression.text
return when (expression) {
is KtConstantExpression -> {
val bindingContext = expression.analyze()
@@ -97,7 +97,7 @@ public class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIn
is KtStringTemplateExpression -> {
val base = if (expressionText.startsWith("\"\"\"") && expressionText.endsWith("\"\"\"")) {
val unquoted = expressionText.substring(3, expressionText.length() - 3)
val unquoted = expressionText.substring(3, expressionText.length - 3)
StringUtil.escapeStringCharacters(unquoted)
}
else {
@@ -114,8 +114,6 @@ public class ConvertToStringTemplateIntention : SelfTargetingOffsetIndependentIn
is KtNameReferenceExpression ->
"$" + (if (forceBraces) "{$expressionText}" else expressionText)
null -> ""
else -> "\${" + expressionText.replace("\n+".toRegex(), " ") + "}"
}
}
@@ -45,14 +45,14 @@ import java.util.*
public class DeprecatedCallableAddReplaceWithInspection : IntentionBasedInspection<KtCallableDeclaration>(DeprecatedCallableAddReplaceWithIntention())
public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeIntention<KtCallableDeclaration>(
javaClass(), "Add 'replaceWith' argument to specify replacement pattern", "Add 'replaceWith' argument to 'Deprecated' annotation"
KtCallableDeclaration::class.java, "Add 'replaceWith' argument to specify replacement pattern", "Add 'replaceWith' argument to 'Deprecated' annotation"
) {
private class ReplaceWith(val expression: String, vararg val imports: String)
override fun applicabilityRange(element: KtCallableDeclaration): TextRange? {
val annotationEntry = element.deprecatedAnnotationWithNoReplaceWith() ?: return null
if (element.suggestReplaceWith() == null) return null
return annotationEntry.getTextRange()
return annotationEntry.textRange
}
override fun applyTo(element: KtCallableDeclaration, editor: Editor) {
@@ -69,9 +69,9 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
// escape '$' if it's followed by a letter or '{'
if (escapedText.contains('$')) {
escapedText = StringBuilder {
escapedText = StringBuilder().apply {
var i = 0
val length = escapedText.length()
val length = escapedText.length
while (i < length) {
val c = escapedText[i++]
if (c == '$' && i < length) {
@@ -85,7 +85,7 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
}.toString()
}
val argumentText = StringBuilder {
val argumentText = StringBuilder().apply {
append("kotlin.ReplaceWith(\"")
append(escapedText)
append("\"")
@@ -95,30 +95,30 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
}.toString()
var argument = psiFactory.createArgument(psiFactory.createExpression(argumentText))
argument = annotationEntry.getValueArgumentList()!!.addArgument(argument)
argument = annotationEntry.valueArgumentList!!.addArgument(argument)
argument = ShortenReferences.DEFAULT.process(argument) as KtValueArgument
PsiDocumentManager.getInstance(argument.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument())
editor.moveCaret(argument.getTextOffset())
PsiDocumentManager.getInstance(argument.project).doPostponedOperationsAndUnblockDocument(editor.document)
editor.moveCaret(argument.textOffset)
}
private fun KtCallableDeclaration.deprecatedAnnotationWithNoReplaceWith(): KtAnnotationEntry? {
val bindingContext = this.analyze()
// val deprecatedConstructor = KotlinBuiltIns.getInstance().getDeprecatedAnnotation().getUnsubstitutedPrimaryConstructor()
for (entry in getAnnotationEntries()) {
for (entry in annotationEntries) {
entry.analyze()
val resolvedCall = entry.getCalleeExpression().getResolvedCall(bindingContext) ?: continue
val resolvedCall = entry.calleeExpression.getResolvedCall(bindingContext) ?: continue
if (!resolvedCall.isReallySuccess()) continue
// if (resolvedCall.getResultingDescriptor() != deprecatedConstructor) continue
//TODO
val descriptor = resolvedCall.getResultingDescriptor().getContainingDeclaration()
val descriptor = resolvedCall.resultingDescriptor.containingDeclaration
val descriptorFqName = DescriptorUtils.getFqName(descriptor).toSafe()
if (descriptorFqName != KotlinBuiltIns.FQ_NAMES.deprecated) continue
val replaceWithArguments = resolvedCall.getValueArguments().entrySet()
.single { it.key.getName().asString() == "replaceWith"/*TODO: kotlin.deprecated::replaceWith.name*/ }.value
return if (replaceWithArguments.getArguments().isEmpty()) entry else null
val replaceWithArguments = resolvedCall.valueArguments.entries
.single { it.key.name.asString() == "replaceWith"/*TODO: kotlin.deprecated::replaceWith.name*/ }.value
return if (replaceWithArguments.arguments.isEmpty()) entry else null
}
return null
}
@@ -128,8 +128,8 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
is KtNamedFunction -> replacementExpressionFromBody()
is KtProperty -> {
if (isVar()) return null //TODO
getGetter()?.replacementExpressionFromBody()
if (isVar) return null //TODO
getter?.replacementExpressionFromBody()
}
else -> null
@@ -146,7 +146,7 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
}
override fun visitBlockExpression(expression: KtBlockExpression) {
if (expression.getStatements().size() > 1) {
if (expression.statements.size > 1) {
isGood = false
return
}
@@ -155,7 +155,7 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
val target = expression.analyze()[BindingContext.REFERENCE_TARGET, expression] as? DeclarationDescriptorWithVisibility ?: return
if (Visibilities.isPrivate((target.getVisibility()))) {
if (Visibilities.isPrivate((target.visibility))) {
isGood = false
}
}
@@ -168,34 +168,34 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
//TODO: check that no receivers that cannot be referenced from outside involved
val text = replacementExpression.getText()
val text = replacementExpression.text
var expression = try {
KtPsiFactory(this).createExpression(text.replace('\n', ' '))
}
catch(e: Throwable) { // does not parse in one line
return null
}
expression = CodeStyleManager.getInstance(getProject()).reformat(expression, true) as KtExpression
expression = CodeStyleManager.getInstance(project).reformat(expression, true) as KtExpression
return ReplaceWith(expression.getText(), *extractImports(replacementExpression).toTypedArray())
return ReplaceWith(expression.text, *extractImports(replacementExpression).toTypedArray())
}
private fun KtDeclarationWithBody.replacementExpressionFromBody(): KtExpression? {
val body = getBodyExpression() ?: return null
val body = bodyExpression ?: return null
if (!hasBlockBody()) return body
val block = body as? KtBlockExpression ?: return null
val statement = block.getStatements().singleOrNull() as? KtExpression ?: return null
val returnsUnit = (analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? FunctionDescriptor)?.getReturnType()?.isUnit() ?: return null
val statement = block.statements.singleOrNull() as? KtExpression ?: return null
val returnsUnit = (analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? FunctionDescriptor)?.returnType?.isUnit() ?: return null
return when (statement) {
is KtReturnExpression -> statement.getReturnedExpression()
is KtReturnExpression -> statement.returnedExpression
else -> if (returnsUnit) statement else null
}
}
private fun extractImports(expression: KtExpression): Collection<String> {
val file = expression.getContainingKtFile()
val currentPackageFqName = file.getPackageFqName()
val importHelper = ImportInsertHelper.getInstance(expression.getProject())
val currentPackageFqName = file.packageFqName
val importHelper = ImportInsertHelper.getInstance(expression.project)
val result = ArrayList<String>()
expression.accept(object : KtVisitorVoid(){
@@ -207,7 +207,7 @@ public class DeprecatedCallableAddReplaceWithIntention : SelfTargetingRangeInten
if (target.isExtension || expression.getReceiverExpression() == null) {
val fqName = target.importableFqName ?: return
if (!importHelper.isImportedWithDefault(ImportPath(fqName, false), file)
&& (target.getContainingDeclaration() as? PackageFragmentDescriptor)?.fqName != currentPackageFqName) {
&& (target.containingDeclaration as? PackageFragmentDescriptor)?.fqName != currentPackageFqName) {
result.add(fqName.asString())
}
}
@@ -36,27 +36,27 @@ import java.util.*
public class IfNullToElvisInspection : IntentionBasedInspection<KtIfExpression>(IfNullToElvisIntention())
public class IfNullToElvisIntention : SelfTargetingRangeIntention<KtIfExpression>(javaClass(), "Replace 'if' with elvis operator"){
public class IfNullToElvisIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' with elvis operator"){
override fun applicabilityRange(element: KtIfExpression): TextRange? {
val data = calcData(element) ?: return null
val type = data.ifNullExpression.analyze().getType(data.ifNullExpression) ?: return null
if (!type.isNothing()) return null
val rParen = element.getRightParenthesis() ?: return null
val rParen = element.rightParenthesis ?: return null
return TextRange(element.startOffset, rParen.endOffset)
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
val newElvis = applyTo(element)
editor.getCaretModel().moveToOffset(newElvis.getRight()!!.getTextOffset())
editor.caretModel.moveToOffset(newElvis.right!!.textOffset)
}
public fun applyTo(element: KtIfExpression): KtBinaryExpression {
val (initializer, declaration, ifNullExpr) = calcData(element)!!
val factory = KtPsiFactory(element)
val explicitTypeToAdd = if (declaration.isVar() && declaration.getTypeReference() == null)
val explicitTypeToAdd = if (declaration.isVar && declaration.typeReference == null)
initializer.analyze().getType(initializer)
else
null
@@ -73,7 +73,7 @@ public class IfNullToElvisIntention : SelfTargetingRangeIntention<KtIfExpression
val newElvis = initializer.replaced(elvis)
element.delete()
if (explicitTypeToAdd != null && !explicitTypeToAdd.isError()) {
if (explicitTypeToAdd != null && !explicitTypeToAdd.isError) {
declaration.setType(explicitTypeToAdd)
}
@@ -87,22 +87,22 @@ public class IfNullToElvisIntention : SelfTargetingRangeIntention<KtIfExpression
)
private fun calcData(ifExpression: KtIfExpression): Data? {
if (ifExpression.getElse() != null) return null
if (ifExpression.`else` != null) return null
val binaryExpression = ifExpression.getCondition() as? KtBinaryExpression ?: return null
if (binaryExpression.getOperationToken() != KtTokens.EQEQ) return null
val binaryExpression = ifExpression.condition as? KtBinaryExpression ?: return null
if (binaryExpression.operationToken != KtTokens.EQEQ) return null
val value = binaryExpression.expressionComparedToNull() as? KtNameReferenceExpression ?: return null
if (ifExpression.getParent() !is KtBlockExpression) return null
if (ifExpression.parent !is KtBlockExpression) return null
val prevStatement = ifExpression.siblings(forward = false, withItself = false)
.firstIsInstanceOrNull<KtExpression>() ?: return null
if (prevStatement !is KtVariableDeclaration) return null
if (prevStatement.getNameAsName() != value.getReferencedNameAsName()) return null
val initializer = prevStatement.getInitializer() ?: return null
val then = ifExpression.getThen() ?: return null
if (prevStatement.nameAsName != value.getReferencedNameAsName()) return null
val initializer = prevStatement.initializer ?: return null
val then = ifExpression.then ?: return null
if (then is KtBlockExpression) {
val statement = then.getStatements().singleOrNull() ?: return null
val statement = then.statements.singleOrNull() ?: return null
return Data(initializer, prevStatement, statement)
}
else {
@@ -20,10 +20,10 @@ import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
public class InfixCallToOrdinaryIntention : SelfTargetingIntention<KtBinaryExpression>(javaClass(), "Replace infix call with ordinary call") {
public class InfixCallToOrdinaryIntention : SelfTargetingIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Replace infix call with ordinary call") {
override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean {
if (element.getOperationToken() != KtTokens.IDENTIFIER || element.getLeft() == null || element.getRight() == null) return false
return element.getOperationReference().getTextRange().containsOffset(caretOffset)
if (element.operationToken != KtTokens.IDENTIFIER || element.left == null || element.right == null) return false
return element.operationReference.textRange.containsOffset(caretOffset)
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
@@ -32,12 +32,12 @@ public class InfixCallToOrdinaryIntention : SelfTargetingIntention<KtBinaryExpre
companion object {
public fun convert(element: KtBinaryExpression): KtExpression {
val argument = KtPsiUtil.safeDeparenthesize(element.getRight()!!)
val argument = KtPsiUtil.safeDeparenthesize(element.right!!)
val pattern = "$0.$1" + when (argument) {
is KtLambdaExpression -> " $2:'{}'"
else -> "($2)"
}
val replacement = KtPsiFactory(element).createExpressionByPattern(pattern, element.getLeft()!!, element.getOperationReference().getText(), argument)
val replacement = KtPsiFactory(element).createExpressionByPattern(pattern, element.left!!, element.operationReference.text, argument)
return element.replace(replacement) as KtExpression
}
}
@@ -22,12 +22,12 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtSimpleNameStringTemplateEntry
public class InsertCurlyBracesToTemplateIntention : SelfTargetingOffsetIndependentIntention<KtSimpleNameStringTemplateEntry> (
javaClass(), "Insert curly braces around variable"), LowPriorityAction {
KtSimpleNameStringTemplateEntry::class.java, "Insert curly braces around variable"), LowPriorityAction {
override fun isApplicableTo(element: KtSimpleNameStringTemplateEntry): Boolean = true
override fun applyTo(element: KtSimpleNameStringTemplateEntry, editor: Editor) {
val expression = element.getExpression() ?: return
val expression = element.expression ?: return
element.replace(KtPsiFactory(element).createBlockStringTemplateEntry(expression))
}
}
@@ -29,15 +29,15 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.types.ErrorUtils
public class InsertExplicitTypeArgumentsIntention : SelfTargetingRangeIntention<KtCallExpression>(javaClass(), "Add explicit type arguments"), LowPriorityAction {
public class InsertExplicitTypeArgumentsIntention : SelfTargetingRangeIntention<KtCallExpression>(KtCallExpression::class.java, "Add explicit type arguments"), LowPriorityAction {
override fun applicabilityRange(element: KtCallExpression): TextRange? {
return if (isApplicableTo(element, element.analyze())) element.getCalleeExpression()!!.getTextRange() else null
return if (isApplicableTo(element, element.analyze())) element.calleeExpression!!.textRange else null
}
override fun applyTo(element: KtCallExpression, editor: Editor) {
val argumentList = createTypeArguments(element, element.analyze())!!
val callee = element.getCalleeExpression()!!
val callee = element.calleeExpression!!
val newArgumentList = element.addAfter(argumentList, callee) as KtTypeArgumentList
ShortenReferences.DEFAULT.process(newArgumentList)
@@ -45,19 +45,19 @@ public class InsertExplicitTypeArgumentsIntention : SelfTargetingRangeIntention<
companion object {
public fun isApplicableTo(element: KtCallExpression, bindingContext: BindingContext): Boolean {
if (!element.getTypeArguments().isEmpty()) return false
if (element.getCalleeExpression() == null) return false
if (!element.typeArguments.isEmpty()) return false
if (element.calleeExpression == null) return false
val resolvedCall = element.getResolvedCall(bindingContext) ?: return false
val typeArgs = resolvedCall.getTypeArguments()
return typeArgs.isNotEmpty() && typeArgs.values().none { ErrorUtils.containsErrorType(it) }
val typeArgs = resolvedCall.typeArguments
return typeArgs.isNotEmpty() && typeArgs.values.none { ErrorUtils.containsErrorType(it) }
}
public fun createTypeArguments(element: KtCallExpression, bindingContext: BindingContext): KtTypeArgumentList? {
val resolvedCall = element.getResolvedCall(bindingContext) ?: return null
val args = resolvedCall.getTypeArguments()
val types = resolvedCall.getCandidateDescriptor().getTypeParameters()
val args = resolvedCall.typeArguments
val types = resolvedCall.candidateDescriptor.typeParameters
val text = types.map { IdeDescriptorRenderers.SOURCE_CODE.renderType(args[it]!!) }.joinToString(", ", "<", ">")
@@ -16,24 +16,17 @@
package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
class IntroduceBackingPropertyIntention(): SelfTargetingIntention<KtProperty>(javaClass(), "Introduce backing property") {
class IntroduceBackingPropertyIntention(): SelfTargetingIntention<KtProperty>(KtProperty::class.java, "Introduce backing property") {
override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean {
if (!canIntroduceBackingProperty(element)) return false
return element.nameIdentifier?.textRange?.containsOffset(caretOffset) == true
@@ -97,7 +90,7 @@ class IntroduceBackingPropertyIntention(): SelfTargetingIntention<KtProperty>(ja
}
private fun KtProperty.addAccessor(newAccessor: KtPropertyAccessor) {
val semicolon = getNode().findChildByType(KtTokens.SEMICOLON)
val semicolon = node.findChildByType(KtTokens.SEMICOLON)
addBefore(newAccessor, semicolon?.psi)
}
@@ -136,24 +129,3 @@ class IntroduceBackingPropertyIntention(): SelfTargetingIntention<KtProperty>(ja
}
}
}
class IntroduceBackingPropertyFix(prop: KtProperty): KotlinQuickFixAction<KtProperty>(prop) {
override fun getText(): String = "Introduce backing property"
override fun getFamilyName(): String = getText()
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
IntroduceBackingPropertyIntention.introduceBackingProperty(element)
}
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val resolveResult = diagnostic.psiElement.reference?.resolve()
if (resolveResult is KtProperty &&
IntroduceBackingPropertyIntention.canIntroduceBackingProperty(resolveResult)) {
return IntroduceBackingPropertyFix(resolveResult)
}
return null
}
}
}
@@ -29,14 +29,14 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>(javaClass(), "Invert 'if' condition") {
public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>(KtIfExpression::class.java, "Invert 'if' condition") {
override fun isApplicableTo(element: KtIfExpression, caretOffset: Int): Boolean {
if (!element.getIfKeyword().getTextRange().containsOffset(caretOffset)) return false
return element.getCondition() != null && element.getThen() != null
if (!element.ifKeyword.textRange.containsOffset(caretOffset)) return false
return element.condition != null && element.then != null
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
val newCondition = element.getCondition()!!.negate()
val newCondition = element.condition!!.negate()
val newIf = handleSpecialCases(element, newCondition)
?: handleStandardCase(element, newCondition)
@@ -47,22 +47,22 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
simplifyIntention.applyTo(newIfCondition)
}
PsiDocumentManager.getInstance(newIf.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument())
editor.moveCaret(newIf.getTextOffset())
PsiDocumentManager.getInstance(newIf.project).doPostponedOperationsAndUnblockDocument(editor.document)
editor.moveCaret(newIf.textOffset)
}
private fun handleStandardCase(ifExpression: KtIfExpression, newCondition: KtExpression): KtIfExpression {
val psiFactory = KtPsiFactory(ifExpression)
val thenBranch = ifExpression.getThen()!!
val elseBranch = ifExpression.getElse() ?: psiFactory.createEmptyBody()
val thenBranch = ifExpression.then!!
val elseBranch = ifExpression.`else` ?: psiFactory.createEmptyBody()
val newThen = if (elseBranch is KtIfExpression)
psiFactory.createSingleStatementBlock(elseBranch)
else
elseBranch
val newElse = if (thenBranch is KtBlockExpression && thenBranch.getStatements().isEmpty())
val newElse = if (thenBranch is KtBlockExpression && thenBranch.statements.isEmpty())
null
else
thenBranch
@@ -71,17 +71,17 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
}
private fun handleSpecialCases(ifExpression: KtIfExpression, newCondition: KtExpression): KtIfExpression? {
val elseBranch = ifExpression.getElse()
val elseBranch = ifExpression.`else`
if (elseBranch != null) return null
val factory = KtPsiFactory(ifExpression)
val thenBranch = ifExpression.getThen()!!
val thenBranch = ifExpression.then!!
val lastThenStatement = thenBranch.lastBlockStatementOrThis()
if (lastThenStatement.isExitStatement()) {
val block = ifExpression.getParent() as? KtBlockExpression
val block = ifExpression.parent as? KtBlockExpression
if (block != null) {
val rBrace = block.getRBrace()
val rBrace = block.rBrace
val afterIfInBlock = ifExpression.siblings(withItself = false)
.takeWhile { it != rBrace }
.toList()
@@ -95,12 +95,12 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
val first = afterIfInBlock.first()
val last = afterIfInBlock.last()
// build new then branch text from statements after if (we will add exit statement if necessary later)
var newIfBodyText = ifExpression.getContainingFile().getText().substring(first.startOffset, last.endOffset).trim()
var newIfBodyText = ifExpression.containingFile.text.substring(first.startOffset, last.endOffset).trim()
// remove statements after if as they are moving under if
block.deleteChildRange(first, last)
if (lastThenStatement is KtReturnExpression && lastThenStatement.getReturnedExpression() == null) {
if (lastThenStatement is KtReturnExpression && lastThenStatement.returnedExpression == null) {
lastThenStatement.delete()
}
val updatedIf = copyThenBranchAfter(ifExpression)
@@ -110,7 +110,7 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
// don't insert the exit statement, if the new if statement placement has the same exit statement executed after it
val exitAfterNewIf = exitStatementExecutedAfter(updatedIf)
if (exitAfterNewIf == null || !exitAfterNewIf.matches(exitStatementAfterIf)) {
newIfBodyText += "\n" + exitStatementAfterIf.getText()
newIfBodyText += "\n" + exitStatementAfterIf.text
}
}
@@ -132,15 +132,15 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
private fun copyThenBranchAfter(ifExpression: KtIfExpression): KtIfExpression {
val factory = KtPsiFactory(ifExpression)
val thenBranch = ifExpression.getThen() ?: return ifExpression
val thenBranch = ifExpression.then ?: return ifExpression
val parent = ifExpression.getParent()
val parent = ifExpression.parent
if (parent !is KtBlockExpression) {
assert(parent is KtContainerNode)
val block = factory.createEmptyBody()
block.addAfter(ifExpression, block.getLBrace())
block.addAfter(ifExpression, block.lBrace)
val newBlock = ifExpression.replaced(block)
val newIf = newBlock.getStatements().single() as KtIfExpression
val newIf = newBlock.statements.single() as KtIfExpression
return copyThenBranchAfter(newIf)
}
@@ -159,9 +159,9 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
}
private fun exitStatementExecutedAfter(expression: KtExpression): KtExpression? {
val parent = expression.getParent()
val parent = expression.parent
if (parent is KtBlockExpression) {
val lastStatement = parent.getStatements().last()
val lastStatement = parent.statements.last()
if (expression == lastStatement) {
return exitStatementExecutedAfter(parent)
}
@@ -175,25 +175,25 @@ public class InvertIfConditionIntention : SelfTargetingIntention<KtIfExpression>
when (parent) {
is KtNamedFunction -> {
if (parent.getBodyExpression() == expression) {
if (parent.bodyExpression == expression) {
if (!parent.hasBlockBody()) return null
val returnType = (parent.resolveToDescriptor() as FunctionDescriptor).getReturnType()
val returnType = (parent.resolveToDescriptor() as FunctionDescriptor).returnType
if (returnType == null || !returnType.isUnit()) return null
return KtPsiFactory(expression).createExpression("return")
}
}
is KtContainerNode -> {
val pparent = parent.getParent()
val pparent = parent.parent
when (pparent) {
is KtLoopExpression -> {
if (expression == pparent.getBody()) {
if (expression == pparent.body) {
return KtPsiFactory(expression).createExpression("continue")
}
}
is KtIfExpression -> {
if (expression == pparent.getThen() || expression == pparent.getElse()) {
if (expression == pparent.then || expression == pparent.`else`) {
return exitStatementExecutedAfter(pparent)
}
}
@@ -32,13 +32,13 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
public class IterateExpressionIntention : SelfTargetingIntention<KtExpression>(javaClass(), "Iterate over collection"), HighPriorityAction {
public class IterateExpressionIntention : SelfTargetingIntention<KtExpression>(KtExpression::class.java, "Iterate over collection"), HighPriorityAction {
override fun isApplicableTo(element: KtExpression, caretOffset: Int): Boolean {
if (element.getParent() !is KtBlockExpression) return false
val range = element.getTextRange()
if (caretOffset != range.getStartOffset() && caretOffset != range.getEndOffset()) return false
if (element.parent !is KtBlockExpression) return false
val range = element.textRange
if (caretOffset != range.startOffset && caretOffset != range.endOffset) return false
val data = data(element) ?: return false
setText("Iterate over '${IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(data.collectionType)}'")
text = "Iterate over '${IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(data.collectionType)}'"
return true
}
@@ -65,12 +65,12 @@ public class IterateExpressionIntention : SelfTargetingIntention<KtExpression>(j
var forExpression = KtPsiFactory(element).createExpressionByPattern("for($0 in $1) {\nx\n}", names.first(), element) as KtForExpression
forExpression = element.replaced(forExpression)
PsiDocumentManager.getInstance(forExpression.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument())
PsiDocumentManager.getInstance(forExpression.project).doPostponedOperationsAndUnblockDocument(editor.document)
val bodyPlaceholder = (forExpression.getBody() as KtBlockExpression).getStatements().single()
val bodyPlaceholder = (forExpression.body as KtBlockExpression).statements.single()
val templateBuilder = TemplateBuilderImpl(forExpression)
templateBuilder.replaceElement(forExpression.getLoopParameter()!!, ChooseStringExpression(names))
templateBuilder.replaceElement(forExpression.loopParameter!!, ChooseStringExpression(names))
templateBuilder.replaceElement(bodyPlaceholder, ConstantNode(""), false)
templateBuilder.setEndVariableAfter(bodyPlaceholder)
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
public class MoveAssignmentToInitializerIntention :
SelfTargetingIntention<KtBinaryExpression>(javaClass(), "Move assignment to initializer") {
SelfTargetingIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Move assignment to initializer") {
override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean {
if (element.operationToken != KtTokens.EQ) {
@@ -19,15 +19,14 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
import org.jetbrains.kotlin.idea.core.moveInsideParentheses
import org.jetbrains.kotlin.psi.KtLambdaArgument
import org.jetbrains.kotlin.psi.psiUtil.containsInside
public class MoveLambdaInsideParenthesesIntention : SelfTargetingIntention<KtLambdaArgument>(javaClass(), "Move lambda argument into parentheses"), LowPriorityAction {
public class MoveLambdaInsideParenthesesIntention : SelfTargetingIntention<KtLambdaArgument>(KtLambdaArgument::class.java, "Move lambda argument into parentheses"), LowPriorityAction {
override fun isApplicableTo(element: KtLambdaArgument, caretOffset: Int): Boolean {
val body = element.getLambdaExpression().getBodyExpression() ?: return true
return !body.getTextRange().containsInside(caretOffset)
val body = element.getLambdaExpression().bodyExpression ?: return true
return !body.textRange.containsInside(caretOffset)
}
override fun applyTo(element: KtLambdaArgument, editor: Editor) {
@@ -29,14 +29,14 @@ import org.jetbrains.kotlin.psi.unpackFunctionLiteral
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class MoveLambdaOutsideParenthesesIntention : SelfTargetingIntention<KtCallExpression>(javaClass(), "Move lambda argument out of parentheses") {
public class MoveLambdaOutsideParenthesesIntention : SelfTargetingIntention<KtCallExpression>(KtCallExpression::class.java, "Move lambda argument out of parentheses") {
override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
if (element.getLambdaArguments().isNotEmpty()) return false
val argument = element.getValueArguments().lastOrNull() ?: return false
if (element.lambdaArguments.isNotEmpty()) return false
val argument = element.valueArguments.lastOrNull() ?: return false
val expression = argument.getArgumentExpression() ?: return false
val functionLiteral = expression.unpackFunctionLiteral() ?: return false
val callee = element.getCalleeExpression()
val callee = element.calleeExpression
if (callee is KtNameReferenceExpression) {
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
val targets = bindingContext[BindingContext.REFERENCE_TARGET, callee]?.let { listOf(it) }
@@ -45,15 +45,15 @@ public class MoveLambdaOutsideParenthesesIntention : SelfTargetingIntention<KtCa
val candidates = targets.filterIsInstance<FunctionDescriptor>()
// if there are functions among candidates but none of them have last function parameter then not show the intention
if (candidates.isNotEmpty() && candidates.none {
val lastParameter = it.getValueParameters().lastOrNull()
lastParameter != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(lastParameter.getType())
val lastParameter = it.valueParameters.lastOrNull()
lastParameter != null && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(lastParameter.type)
}) {
return false
}
}
if (caretOffset < argument.asElement().startOffset) return false
val bodyRange = functionLiteral.getBodyExpression()?.getTextRange() ?: return true
val bodyRange = functionLiteral.bodyExpression?.textRange ?: return true
return !bodyRange.containsInside(caretOffset)
}
@@ -27,26 +27,26 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.KotlinType
public class ReconstructTypeInCastOrIsIntention : SelfTargetingOffsetIndependentIntention<KtTypeReference>(javaClass(), "Replace by reconstructed type"), LowPriorityAction {
public class ReconstructTypeInCastOrIsIntention : SelfTargetingOffsetIndependentIntention<KtTypeReference>(KtTypeReference::class.java, "Replace by reconstructed type"), LowPriorityAction {
override fun isApplicableTo(element: KtTypeReference): Boolean {
// Only user types (like Foo) are interesting
val typeElement = element.typeElement as? KtUserType ?: return false
// If there are generic arguments already, there's nothing to reconstruct
if (typeElement.getTypeArguments().isNotEmpty()) return false
if (typeElement.typeArguments.isNotEmpty()) return false
// We must be on the RHS of as/as?/is/!is or inside an is/!is-condition in when()
val expression = element.getParentOfType<KtExpression>(true)
if (expression !is KtBinaryExpressionWithTypeRHS && element.getParentOfType<KtWhenConditionIsPattern>(true) == null) return false
val type = getReconstructedType(element)
if (type == null || type.isError()) return false
if (type == null || type.isError) return false
// No type parameters expected => nothing to reconstruct
if (type.getConstructor().getParameters().isEmpty()) return false
if (type.constructor.parameters.isEmpty()) return false
val typePresentation = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
setText("Replace by '$typePresentation'")
text = "Replace by '$typePresentation'"
return true
}
@@ -29,16 +29,16 @@ import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class RemoveArgumentNameIntention
: SelfTargetingRangeIntention<KtValueArgument>(javaClass(), "Remove argument name") {
: SelfTargetingRangeIntention<KtValueArgument>(KtValueArgument::class.java, "Remove argument name") {
override fun applicabilityRange(element: KtValueArgument): TextRange? {
if (!element.isNamed()) return null
val argumentList = element.getParent() as? KtValueArgumentList ?: return null
val arguments = argumentList.getArguments()
val argumentList = element.parent as? KtValueArgumentList ?: return null
val arguments = argumentList.arguments
if (arguments.takeWhile { it != element }.any { it.isNamed() }) return null
val callExpr = argumentList.getParent() as? KtExpression ?: return null
val callExpr = argumentList.parent as? KtExpression ?: return null
val resolvedCall = callExpr.getResolvedCall(callExpr.analyze(BodyResolveMode.PARTIAL)) ?: return null
val argumentMatch = resolvedCall.getArgumentMapping(element) as? ArgumentMatch ?: return null
if (argumentMatch.valueParameter.index != arguments.indexOf(element)) return null
@@ -20,51 +20,50 @@ import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
public class RemoveBracesIntention : SelfTargetingIntention<KtBlockExpression>(javaClass(), "Remove braces") {
public class RemoveBracesIntention : SelfTargetingIntention<KtBlockExpression>(KtBlockExpression::class.java, "Remove braces") {
override fun isApplicableTo(element: KtBlockExpression, caretOffset: Int): Boolean {
if (element.getStatements().size() != 1) return false
if (element.statements.size != 1) return false
val containerNode = element.getParent() as? KtContainerNode ?: return false
val containerNode = element.parent as? KtContainerNode ?: return false
val lBrace = element.getLBrace() ?: return false
val rBrace = element.getRBrace() ?: return false
if (!lBrace.getTextRange().containsOffset(caretOffset) && !rBrace.getTextRange().containsOffset(caretOffset)) return false
val lBrace = element.lBrace ?: return false
val rBrace = element.rBrace ?: return false
if (!lBrace.textRange.containsOffset(caretOffset) && !rBrace.textRange.containsOffset(caretOffset)) return false
val description = containerNode.description() ?: return false
setText("Remove braces from '$description' statement")
text = "Remove braces from '$description' statement"
return true
}
override fun applyTo(element: KtBlockExpression, editor: Editor) {
val statement = element.getStatements().single()
val statement = element.statements.single()
val containerNode = element.getParent() as KtContainerNode
val construct = containerNode.getParent() as KtExpression
val containerNode = element.parent as KtContainerNode
val construct = containerNode.parent as KtExpression
handleComments(construct, element)
val newElement = element.replace(statement.copy())
if (construct is KtDoWhileExpression) {
newElement.getParent()!!.addAfter(KtPsiFactory(element).createNewLine(), newElement)
newElement.parent!!.addAfter(KtPsiFactory(element).createNewLine(), newElement)
}
}
private fun handleComments(construct: KtExpression, block: KtBlockExpression) {
var sibling = block.getFirstChild()?.getNextSibling()
var sibling = block.firstChild?.nextSibling
while (sibling != null) {
if (sibling is PsiComment) {
//cleans up extra whitespace
val psiFactory = KtPsiFactory(construct)
if (construct.getPrevSibling() is PsiWhiteSpace) {
construct.getPrevSibling()!!.replace(psiFactory.createNewLine())
if (construct.prevSibling is PsiWhiteSpace) {
construct.prevSibling!!.replace(psiFactory.createNewLine())
}
val commentElement = construct.getParent()!!.addBefore(sibling, construct.getPrevSibling())
construct.getParent()!!.addBefore(psiFactory.createNewLine(), commentElement)
val commentElement = construct.parent!!.addBefore(sibling, construct.prevSibling)
construct.parent!!.addBefore(psiFactory.createNewLine(), commentElement)
}
sibling = sibling.getNextSibling()
sibling = sibling.nextSibling
}
}
}
@@ -27,9 +27,9 @@ import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry
public class RemoveCurlyBracesFromTemplateInspection : IntentionBasedInspection<KtBlockStringTemplateEntry>(RemoveCurlyBracesFromTemplateIntention())
public class RemoveCurlyBracesFromTemplateIntention : SelfTargetingOffsetIndependentIntention<KtBlockStringTemplateEntry>(javaClass(), "Remove curly braces") {
public class RemoveCurlyBracesFromTemplateIntention : SelfTargetingOffsetIndependentIntention<KtBlockStringTemplateEntry>(KtBlockStringTemplateEntry::class.java, "Remove curly braces") {
override fun isApplicableTo(element: KtBlockStringTemplateEntry): Boolean {
if (element.getExpression() !is KtNameReferenceExpression) return false
if (element.expression !is KtNameReferenceExpression) return false
return canPlaceAfterSimpleNameEntry(element.nextSibling)
}
@@ -38,7 +38,7 @@ public class RemoveCurlyBracesFromTemplateIntention : SelfTargetingOffsetIndepen
}
public fun applyTo(element: KtBlockStringTemplateEntry): KtStringTemplateEntryWithExpression {
val name = (element.getExpression() as KtNameReferenceExpression).getReferencedName()
val name = (element.expression as KtNameReferenceExpression).getReferencedName()
val newEntry = KtPsiFactory(element).createSimpleNameStringTemplateEntry(name)
return element.replaced(newEntry)
}
@@ -19,20 +19,19 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.psiUtil.endOffset
public class RemoveExplicitLambdaParameterTypesIntention : SelfTargetingIntention<KtLambdaExpression>(javaClass(), "Remove explicit lambda parameter types (may break code)") {
public class RemoveExplicitLambdaParameterTypesIntention : SelfTargetingIntention<KtLambdaExpression>(KtLambdaExpression::class.java, "Remove explicit lambda parameter types (may break code)") {
override fun isApplicableTo(element: KtLambdaExpression, caretOffset: Int): Boolean {
if (element.getValueParameters().none { it.getTypeReference() != null }) return false
val arrow = element.getFunctionLiteral().getArrow() ?: return false
if (element.valueParameters.none { it.typeReference != null }) return false
val arrow = element.functionLiteral.arrow ?: return false
return caretOffset <= arrow.endOffset
}
override fun applyTo(element: KtLambdaExpression, editor: Editor) {
val oldParameterList = element.getFunctionLiteral().getValueParameterList()!!
val oldParameterList = element.functionLiteral.valueParameterList!!
val parameterString = oldParameterList.getParameters().map { it.getName() }.joinToString(", ")
val parameterString = oldParameterList.parameters.map { it.name }.joinToString(", ")
val newParameterList = KtPsiFactory(element).createFunctionLiteralParameterList(parameterString)
oldParameterList.replace(newParameterList)
}
@@ -44,7 +44,7 @@ public class RemoveExplicitSuperQualifierInspection : IntentionBasedInspection<K
get() = ProblemHighlightType.LIKE_UNUSED_SYMBOL
}
public class RemoveExplicitSuperQualifierIntention : SelfTargetingRangeIntention<KtSuperExpression>(javaClass(), "Remove explicit supertype qualification") {
public class RemoveExplicitSuperQualifierIntention : SelfTargetingRangeIntention<KtSuperExpression>(KtSuperExpression::class.java, "Remove explicit supertype qualification") {
override fun applicabilityRange(element: KtSuperExpression): TextRange? {
if (element.superTypeQualifier == null) return null
@@ -39,27 +39,27 @@ public class RemoveExplicitTypeArgumentsInspection : IntentionBasedInspection<Kt
get() = ProblemHighlightType.LIKE_UNUSED_SYMBOL
}
public class RemoveExplicitTypeArgumentsIntention : SelfTargetingOffsetIndependentIntention<KtTypeArgumentList>(javaClass(), "Remove explicit type arguments") {
public class RemoveExplicitTypeArgumentsIntention : SelfTargetingOffsetIndependentIntention<KtTypeArgumentList>(KtTypeArgumentList::class.java, "Remove explicit type arguments") {
companion object {
public fun isApplicableTo(element: KtTypeArgumentList, approximateFlexible: Boolean): Boolean {
val callExpression = element.getParent() as? KtCallExpression ?: return false
if (callExpression.getTypeArguments().isEmpty()) return false
val callExpression = element.parent as? KtCallExpression ?: return false
if (callExpression.typeArguments.isEmpty()) return false
val resolutionFacade = callExpression.getResolutionFacade()
val context = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL)
val calleeExpression = callExpression.getCalleeExpression() ?: return false
val calleeExpression = callExpression.calleeExpression ?: return false
val scope = calleeExpression.getResolutionScope(context, resolutionFacade)
val originalCall = callExpression.getResolvedCall(context) ?: return false
val untypedCall = CallWithoutTypeArgs(originalCall.getCall())
val untypedCall = CallWithoutTypeArgs(originalCall.call)
// todo Check with expected type for other expressions
// If always use expected type from trace there is a problem with nested calls:
// the expression type for them can depend on their explicit type arguments (via outer call),
// therefore we should resolve outer call with erased type arguments for inner call
val parent = callExpression.getParent()
val parent = callExpression.parent
val expectedTypeIsExplicitInCode = when (parent) {
is KtProperty -> parent.getInitializer() == callExpression && parent.getTypeReference() != null
is KtDeclarationWithBody -> parent.getBodyExpression() == callExpression
is KtProperty -> parent.initializer == callExpression && parent.typeReference != null
is KtDeclarationWithBody -> parent.bodyExpression == callExpression
is KtReturnExpression -> true
else -> false
}
@@ -73,12 +73,12 @@ public class RemoveExplicitTypeArgumentsIntention : SelfTargetingOffsetIndepende
val callResolver = resolutionFacade.frontendService<CallResolver>()
val resolutionResults = callResolver.resolveFunctionCall(
BindingTraceContext(), scope, untypedCall, expectedType, dataFlow, false)
if (!resolutionResults.isSingleResult()) {
if (!resolutionResults.isSingleResult) {
return false
}
val args = originalCall.getTypeArguments()
val newArgs = resolutionResults.getResultingCall().getTypeArguments()
val args = originalCall.typeArguments
val newArgs = resolutionResults.resultingCall.typeArguments
fun equalTypes(type1: KotlinType, type2: KotlinType): Boolean {
return if (approximateFlexible) {
@@ -89,7 +89,7 @@ public class RemoveExplicitTypeArgumentsIntention : SelfTargetingOffsetIndepende
}
}
return args.size() == newArgs.size() && args.values().zip(newArgs.values()).all { pair -> equalTypes(pair.first, pair.second) }
return args.size == newArgs.size && args.values.zip(newArgs.values).all { pair -> equalTypes(pair.first, pair.second) }
}
}
@@ -19,18 +19,18 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.psi.*
public class RemoveExplicitTypeIntention : SelfTargetingIntention<KtCallableDeclaration>(javaClass(), "Remove explicit type specification") {
public class RemoveExplicitTypeIntention : SelfTargetingIntention<KtCallableDeclaration>(KtCallableDeclaration::class.java, "Remove explicit type specification") {
override fun isApplicableTo(element: KtCallableDeclaration, caretOffset: Int): Boolean {
if (element.getContainingFile() is KtCodeFragment) return false
if (element.getTypeReference() == null) return false
if (element.containingFile is KtCodeFragment) return false
if (element.typeReference == null) return false
val initializer = (element as? KtWithExpressionInitializer)?.getInitializer()
if (initializer != null && initializer.getTextRange().containsOffset(caretOffset)) return false
val initializer = (element as? KtWithExpressionInitializer)?.initializer
if (initializer != null && initializer.textRange.containsOffset(caretOffset)) return false
return when (element) {
is KtProperty -> initializer != null
is KtNamedFunction -> !element.hasBlockBody() && initializer != null
is KtParameter -> element.isLoopParameter()
is KtParameter -> element.isLoopParameter
else -> false
}
}
@@ -34,20 +34,20 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class RemoveForLoopIndicesInspection : IntentionBasedInspection<KtForExpression>(
listOf(IntentionBasedInspection.IntentionData(RemoveForLoopIndicesIntention())),
"Index is not used in the loop body",
javaClass()
KtForExpression::class.java
) {
override val problemHighlightType: ProblemHighlightType
get() = ProblemHighlightType.LIKE_UNUSED_SYMBOL
}
public class RemoveForLoopIndicesIntention : SelfTargetingRangeIntention<KtForExpression>(javaClass(), "Remove indices in 'for' loop") {
public class RemoveForLoopIndicesIntention : SelfTargetingRangeIntention<KtForExpression>(KtForExpression::class.java, "Remove indices in 'for' loop") {
private val WITH_INDEX_NAME = "withIndex"
private val WITH_INDEX_FQ_NAMES = listOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$WITH_INDEX_NAME" }.toSet()
override fun applicabilityRange(element: KtForExpression): TextRange? {
val loopRange = element.loopRange as? KtDotQualifiedExpression ?: return null
val multiParameter = element.destructuringParameter ?: return null
if (multiParameter.entries.size() != 2) return null
if (multiParameter.entries.size != 2) return null
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
@@ -20,13 +20,12 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.psiUtil.containsInside
public class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention<KtParenthesizedExpression>(KtParenthesizedExpression::class.java, "Remove unnecessary parentheses") {
override fun applicabilityRange(element: KtParenthesizedExpression): TextRange? {
element.getExpression() ?: return null
element.expression ?: return null
if (!KtPsiUtil.areParenthesesUseless(element)) return null
return element.getTextRange()
return element.textRange
}
override fun applyTo(element: KtParenthesizedExpression, editor: Editor) {
@@ -34,6 +33,6 @@ public class RemoveUnnecessaryParenthesesIntention : SelfTargetingRangeIntention
}
fun applyTo(element: KtParenthesizedExpression) {
element.replace(element.getExpression()!!)
element.replace(element.expression!!)
}
}
@@ -39,19 +39,19 @@ public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBa
override fun getFamilyName() = "Replace explicit lambda parameter with 'it'"
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
val functionLiteral = targetFunctionLiteral(element, editor.getCaretModel().getOffset()) ?: return false
val functionLiteral = targetFunctionLiteral(element, editor.caretModel.offset) ?: return false
val parameter = functionLiteral.getValueParameters().singleOrNull() ?: return false
if (parameter.getTypeReference() != null) return false
val parameter = functionLiteral.valueParameters.singleOrNull() ?: return false
if (parameter.typeReference != null) return false
setText("Replace explicit parameter '${parameter.getName()}' with 'it'")
text = "Replace explicit parameter '${parameter.name}' with 'it'"
return true
}
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
val caretOffset = editor.getCaretModel().getOffset()
val functionLiteral = targetFunctionLiteral(element, editor.getCaretModel().getOffset())!!
val cursorInParameterList = functionLiteral.getValueParameterList()!!.getTextRange().containsOffset(caretOffset)
val caretOffset = editor.caretModel.offset
val functionLiteral = targetFunctionLiteral(element, editor.caretModel.offset)!!
val cursorInParameterList = functionLiteral.valueParameterList!!.textRange.containsOffset(caretOffset)
ParamRenamingProcessor(editor, functionLiteral, cursorInParameterList).run()
}
@@ -60,12 +60,12 @@ public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBa
if (expression != null) {
val target = expression.mainReference.resolveToDescriptors(expression.analyze(BodyResolveMode.PARTIAL))
.singleOrNull() as? ParameterDescriptor ?: return null
val functionDescriptor = target.getContainingDeclaration() as? AnonymousFunctionDescriptor ?: return null
val functionDescriptor = target.containingDeclaration as? AnonymousFunctionDescriptor ?: return null
return DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor) as? KtFunctionLiteral
}
val functionLiteral = element.getParentOfType<KtFunctionLiteral>(true) ?: return null
val arrow = functionLiteral.getArrow() ?: return null
val arrow = functionLiteral.arrow ?: return null
if (caretOffset > arrow.endOffset) return null
return functionLiteral
}
@@ -74,8 +74,8 @@ public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBa
val editor: Editor,
val functionLiteral: KtFunctionLiteral,
val cursorWasInParameterList: Boolean
) : RenameProcessor(editor.getProject(),
functionLiteral.getValueParameters().single(),
) : RenameProcessor(editor.project,
functionLiteral.valueParameters.single(),
"it",
false,
false
@@ -83,15 +83,15 @@ public class ReplaceExplicitFunctionLiteralParamWithItIntention() : PsiElementBa
public override fun performRefactoring(usages: Array<out UsageInfo>) {
super.performRefactoring(usages)
functionLiteral.deleteChildRange(functionLiteral.getValueParameterList(), functionLiteral.getArrow()!!)
functionLiteral.deleteChildRange(functionLiteral.valueParameterList, functionLiteral.arrow!!)
if (cursorWasInParameterList) {
editor.getCaretModel().moveToOffset(functionLiteral.getBodyExpression()!!.getTextOffset())
editor.caretModel.moveToOffset(functionLiteral.bodyExpression!!.textOffset)
}
val project = functionLiteral.getProject()
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument())
CodeStyleManager.getInstance(project).adjustLineIndent(functionLiteral.getContainingFile(), functionLiteral.getTextRange())
val project = functionLiteral.project
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
CodeStyleManager.getInstance(project).adjustLineIndent(functionLiteral.containingFile, functionLiteral.textRange)
}
}
@@ -21,13 +21,15 @@ import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiDocumentManager
import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtFunctionLiteral
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
public class ReplaceItWithExplicitFunctionLiteralParamIntention() : SelfTargetingOffsetIndependentIntention<KtNameReferenceExpression> (
javaClass(), "Replace 'it' with explicit parameter"
KtNameReferenceExpression::class.java, "Replace 'it' with explicit parameter"
), LowPriorityAction {
override fun isApplicableTo(element: KtNameReferenceExpression)
= isAutoCreatedItUsage(element)
@@ -35,17 +37,17 @@ public class ReplaceItWithExplicitFunctionLiteralParamIntention() : SelfTargetin
override fun applyTo(element: KtNameReferenceExpression, editor: Editor) {
val target = element.mainReference.resolveToDescriptors(element.analyze()).single()
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.getContainingDeclaration()!!) as KtFunctionLiteral
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(target.containingDeclaration!!) as KtFunctionLiteral
val newExpr = KtPsiFactory(element).createExpression("{ it -> }") as KtLambdaExpression
functionLiteral.addRangeAfter(
newExpr.getFunctionLiteral().getValueParameterList(),
newExpr.getFunctionLiteral().getArrow()!!,
functionLiteral.getLBrace())
PsiDocumentManager.getInstance(element.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument())
newExpr.functionLiteral.valueParameterList,
newExpr.functionLiteral.arrow!!,
functionLiteral.lBrace)
PsiDocumentManager.getInstance(element.project).doPostponedOperationsAndUnblockDocument(editor.document)
val paramToRename = functionLiteral.getValueParameters().single()
editor.getCaretModel().moveToOffset(element.getTextOffset())
val paramToRename = functionLiteral.valueParameters.single()
editor.caretModel.moveToOffset(element.textOffset)
VariableInplaceRenameHandler().doRename(paramToRename, editor, null)
}
}
@@ -31,27 +31,26 @@ import org.jetbrains.kotlin.resolve.BindingContext
public class ReplaceWithOperatorAssignmentInspection : IntentionBasedInspection<KtBinaryExpression>(ReplaceWithOperatorAssignmentIntention())
public class ReplaceWithOperatorAssignmentIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(javaClass(), "Replace with operator-assignment") {
public class ReplaceWithOperatorAssignmentIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Replace with operator-assignment") {
override fun isApplicableTo(element: KtBinaryExpression): Boolean {
if (element.getOperationToken() != KtTokens.EQ) return false
val left = element.getLeft() as? KtNameReferenceExpression ?: return false
val right = element.getRight() as? KtBinaryExpression ?: return false
if (right.getLeft() == null || right.getRight() == null) return false
if (element.operationToken != KtTokens.EQ) return false
val left = element.left as? KtNameReferenceExpression ?: return false
val right = element.right as? KtBinaryExpression ?: return false
if (right.left == null || right.right == null) return false
return checkExpressionRepeat(left, right)
}
private fun checkExpressionRepeat(variableExpression: KtNameReferenceExpression, expression: KtBinaryExpression): Boolean {
val context = expression.analyze()
val descriptor = context[BindingContext.REFERENCE_TARGET, expression.getOperationReference()]?.getContainingDeclaration()
val isPrimitiveOperation = descriptor is ClassDescriptor && KotlinBuiltIns.isPrimitiveType(descriptor.getDefaultType())
val descriptor = context[BindingContext.REFERENCE_TARGET, expression.operationReference]?.containingDeclaration
val isPrimitiveOperation = descriptor is ClassDescriptor && KotlinBuiltIns.isPrimitiveType(descriptor.defaultType)
val operationToken = expression.getOperationToken()
setText("Replace with ${expression.getOperationReference().getText()}= expression")
val operationToken = expression.operationToken
text = "Replace with ${expression.operationReference.text}= expression"
val expressionLeft = expression.getLeft()
val expressionRight = expression.getRight()
val expressionLeft = expression.left
val expressionRight = expression.right
return when {
variableExpression.matches(expressionLeft) -> {
isArithmeticOperation(operationToken)
@@ -62,7 +61,7 @@ public class ReplaceWithOperatorAssignmentIntention : SelfTargetingOffsetIndepen
}
expressionLeft is KtBinaryExpression -> {
val sameCommutativeOperation = expressionLeft.getOperationToken() == operationToken && isCommutative(operationToken)
val sameCommutativeOperation = expressionLeft.operationToken == operationToken && isCommutative(operationToken)
isPrimitiveOperation && sameCommutativeOperation && checkExpressionRepeat(variableExpression, expressionLeft)
}
@@ -81,26 +80,26 @@ public class ReplaceWithOperatorAssignmentIntention : SelfTargetingOffsetIndepen
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
val replacement = buildOperatorAssignmentText(
element.getLeft() as KtNameReferenceExpression,
element.getRight() as KtBinaryExpression,
element.left as KtNameReferenceExpression,
element.right as KtBinaryExpression,
""
)
element.replace(KtPsiFactory(element).createExpression(replacement))
}
tailrec private fun buildOperatorAssignmentText(variableExpression: KtNameReferenceExpression, expression: KtBinaryExpression, tail: String): String {
val operationText = expression.getOperationReference().getText()
val variableName = variableExpression.getText()
val operationText = expression.operationReference.text
val variableName = variableExpression.text
fun String.appendTail() = if (tail.isEmpty()) this else "$this $tail"
return when {
variableExpression.matches(expression.getLeft()) -> "$variableName $operationText= ${expression.getRight()!!.getText()}".appendTail()
variableExpression.matches(expression.left) -> "$variableName $operationText= ${expression.right!!.text}".appendTail()
variableExpression.matches(expression.getRight()) -> "$variableName $operationText= ${expression.getLeft()!!.getText()}".appendTail()
variableExpression.matches(expression.right) -> "$variableName $operationText= ${expression.left!!.text}".appendTail()
expression.getLeft() is KtBinaryExpression ->
buildOperatorAssignmentText(variableExpression, expression.getLeft() as KtBinaryExpression, "$operationText ${expression.getRight()!!.getText()}".appendTail())
expression.left is KtBinaryExpression ->
buildOperatorAssignmentText(variableExpression, expression.left as KtBinaryExpression, "$operationText ${expression.right!!.text}".appendTail())
else -> tail
}
@@ -24,22 +24,22 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
public class ReplaceWithOrdinaryAssignmentIntention : SelfTargetingIntention<KtBinaryExpression>(javaClass(), "Replace with ordinary assignment"), LowPriorityAction {
public class ReplaceWithOrdinaryAssignmentIntention : SelfTargetingIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Replace with ordinary assignment"), LowPriorityAction {
override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean {
if (element.getOperationToken() !in KtTokens.AUGMENTED_ASSIGNMENTS) return false
if (element.getLeft() !is KtNameReferenceExpression) return false
if (element.getRight() == null) return false
return element.getOperationReference().getTextRange().containsOffset(caretOffset)
if (element.operationToken !in KtTokens.AUGMENTED_ASSIGNMENTS) return false
if (element.left !is KtNameReferenceExpression) return false
if (element.right == null) return false
return element.operationReference.textRange.containsOffset(caretOffset)
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
val left = element.getLeft()!!
val right = element.getRight()!!
val left = element.left!!
val right = element.right!!
val factory = KtPsiFactory(element)
val assignOpText = element.getOperationReference().getText()
val assignOpText = element.operationReference.text
assert(assignOpText.endsWith("="))
val operationText = assignOpText.substring(0, assignOpText.length() - 1)
val operationText = assignOpText.substring(0, assignOpText.length - 1)
element.replace(factory.createExpressionByPattern("$0 = $0 $operationText $1", left, right))
}
@@ -30,30 +30,30 @@ import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
public class SimplifyBooleanWithConstantsInspection : IntentionBasedInspection<KtBinaryExpression>(SimplifyBooleanWithConstantsIntention())
public class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(javaClass(), "Simplify boolean expression") {
public class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndependentIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Simplify boolean expression") {
override fun isApplicableTo(element: KtBinaryExpression): Boolean {
val topBinary = PsiTreeUtil.getTopmostParentOfType(element, javaClass<KtBinaryExpression>()) ?: element
val topBinary = PsiTreeUtil.getTopmostParentOfType(element, KtBinaryExpression::class.java) ?: element
return areThereExpressionsToBeSimplified(topBinary)
}
private fun areThereExpressionsToBeSimplified(element: KtExpression?) : Boolean {
if (element == null) return false
when (element) {
is KtParenthesizedExpression -> return areThereExpressionsToBeSimplified(element.getExpression())
is KtParenthesizedExpression -> return areThereExpressionsToBeSimplified(element.expression)
is KtBinaryExpression -> {
val op = element.getOperationToken()
val op = element.operationToken
if ((op == KtTokens.ANDAND || op == KtTokens.OROR) &&
(areThereExpressionsToBeSimplified(element.getLeft()) ||
areThereExpressionsToBeSimplified(element.getRight()))) return true
(areThereExpressionsToBeSimplified(element.left) ||
areThereExpressionsToBeSimplified(element.right))) return true
}
}
return element.canBeReducedToBooleanConstant(null)
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
val topBinary = PsiTreeUtil.getTopmostParentOfType(element, javaClass<KtBinaryExpression>()) ?: element
val topBinary = PsiTreeUtil.getTopmostParentOfType(element, KtBinaryExpression::class.java) ?: element
val simplified = toSimplifiedExpression(topBinary)
topBinary.replace(KtPsiUtil.safeDeparenthesize(simplified))
}
@@ -71,7 +71,7 @@ public class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndepend
}
expression is KtParenthesizedExpression -> {
val expr = expression.getExpression()
val expr = expression.expression
if (expr != null) {
val simplified = toSimplifiedExpression(expr)
return if (simplified is KtBinaryExpression) {
@@ -86,9 +86,9 @@ public class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndepend
}
expression is KtBinaryExpression -> {
val left = expression.getLeft()
val right = expression.getRight()
val op = expression.getOperationToken()
val left = expression.left
val right = expression.right
val op = expression.operationToken
if (left != null && right != null && (op == KtTokens.ANDAND || op == KtTokens.OROR)) {
val simpleLeft = simplifyExpression(left)
val simpleRight = simplifyExpression(right)
@@ -102,7 +102,7 @@ public class SimplifyBooleanWithConstantsIntention : SelfTargetingOffsetIndepend
simpleRight.canBeReducedToFalse() -> toSimplifiedBooleanBinaryExpressionWithConstantOperand(false, simpleLeft, op)
else -> {
val opText = expression.getOperationReference().getText()
val opText = expression.operationReference.text
psiFactory.createExpressionByPattern("$0 $opText $1", simpleLeft, simpleRight)
}
}
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.*
public class SimplifyNegatedBinaryExpressionInspection : IntentionBasedInspection<KtPrefixExpression>(SimplifyNegatedBinaryExpressionIntention())
public class SimplifyNegatedBinaryExpressionIntention : SelfTargetingRangeIntention<KtPrefixExpression>(javaClass(), "Simplify negated binary expression") {
public class SimplifyNegatedBinaryExpressionIntention : SelfTargetingRangeIntention<KtPrefixExpression>(KtPrefixExpression::class.java, "Simplify negated binary expression") {
private fun IElementType.negate(): KtSingleValueToken? = when (this) {
KtTokens.IN_KEYWORD -> KtTokens.NOT_IN
@@ -48,23 +48,23 @@ public class SimplifyNegatedBinaryExpressionIntention : SelfTargetingRangeIntent
}
override fun applicabilityRange(element: KtPrefixExpression): TextRange? {
return if (isApplicableTo(element)) element.getOperationReference().getTextRange() else null
return if (isApplicableTo(element)) element.operationReference.textRange else null
}
public fun isApplicableTo(element: KtPrefixExpression): Boolean {
if (element.getOperationToken() != KtTokens.EXCL) return false
if (element.operationToken != KtTokens.EXCL) return false
val expression = KtPsiUtil.deparenthesize(element.getBaseExpression()) as? KtOperationExpression ?: return false
val expression = KtPsiUtil.deparenthesize(element.baseExpression) as? KtOperationExpression ?: return false
when (expression) {
is KtIsExpression -> { if (expression.getTypeReference() == null) return false }
is KtBinaryExpression -> { if (expression.getLeft() == null || expression.getRight() == null) return false }
is KtIsExpression -> { if (expression.typeReference == null) return false }
is KtBinaryExpression -> { if (expression.left == null || expression.right == null) return false }
else -> return false
}
val operation = expression.getOperationReference().getReferencedNameElementType() as? KtSingleValueToken ?: return false
val operation = expression.operationReference.getReferencedNameElementType() as? KtSingleValueToken ?: return false
val negatedOperation = operation.negate() ?: return false
setText("Simplify negated '${operation.getValue()}' expression to '${negatedOperation.getValue()}'")
text = "Simplify negated '${operation.value}' expression to '${negatedOperation.value}'"
return true
}
@@ -73,13 +73,13 @@ public class SimplifyNegatedBinaryExpressionIntention : SelfTargetingRangeIntent
}
public fun applyTo(element: KtPrefixExpression) {
val expression = KtPsiUtil.deparenthesize(element.getBaseExpression())!!
val operation = (expression as KtOperationExpression).getOperationReference().getReferencedNameElementType().negate()!!.getValue()
val expression = KtPsiUtil.deparenthesize(element.baseExpression)!!
val operation = (expression as KtOperationExpression).operationReference.getReferencedNameElementType().negate()!!.value
val psiFactory = KtPsiFactory(expression)
val newExpression = when (expression) {
is KtIsExpression -> psiFactory.createExpressionByPattern("$0 $1 $2", expression.getLeftHandSide(), operation, expression.getTypeReference()!!)
is KtBinaryExpression -> psiFactory.createExpressionByPattern("$0 $1 $2", expression.getLeft()!!, operation, expression.getRight()!!)
is KtIsExpression -> psiFactory.createExpressionByPattern("$0 $1 $2", expression.leftHandSide, operation, expression.typeReference!!)
is KtBinaryExpression -> psiFactory.createExpressionByPattern("$0 $1 $2", expression.left!!, operation, expression.right!!)
else -> throw IllegalArgumentException()
}
element.replace(newExpression)
@@ -27,40 +27,40 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.resolve.BindingContext
public class SpecifyExplicitLambdaSignatureIntention : SelfTargetingIntention<KtLambdaExpression>(javaClass(), "Specify explicit lambda signature"), LowPriorityAction {
public class SpecifyExplicitLambdaSignatureIntention : SelfTargetingIntention<KtLambdaExpression>(KtLambdaExpression::class.java, "Specify explicit lambda signature"), LowPriorityAction {
override fun isApplicableTo(element: KtLambdaExpression, caretOffset: Int): Boolean {
val arrow = element.getFunctionLiteral().getArrow()
val arrow = element.functionLiteral.arrow
if (arrow != null) {
if (caretOffset > arrow.endOffset) return false
if (element.getValueParameters().all { it.getTypeReference() != null }) return false
if (element.valueParameters.all { it.typeReference != null }) return false
}
else {
if (!element.getLeftCurlyBrace().getTextRange().containsOffset(caretOffset)) return false
if (!element.leftCurlyBrace.textRange.containsOffset(caretOffset)) return false
}
val functionDescriptor = element.analyze()[BindingContext.FUNCTION, element.getFunctionLiteral()] ?: return false
return functionDescriptor.getValueParameters().none { it.getType().isError() }
val functionDescriptor = element.analyze()[BindingContext.FUNCTION, element.functionLiteral] ?: return false
return functionDescriptor.valueParameters.none { it.type.isError }
}
override fun applyTo(element: KtLambdaExpression, editor: Editor) {
val psiFactory = KtPsiFactory(element)
val functionLiteral = element.getFunctionLiteral()
val functionLiteral = element.functionLiteral
val functionDescriptor = element.analyze()[BindingContext.FUNCTION, functionLiteral]!!
val parameterString = functionDescriptor.getValueParameters()
.map { "${it.getName()}: ${IdeDescriptorRenderers.SOURCE_CODE.renderType(it.getType())}" }
val parameterString = functionDescriptor.valueParameters
.map { "${it.name}: ${IdeDescriptorRenderers.SOURCE_CODE.renderType(it.type)}" }
.joinToString(", ")
val newParameterList = psiFactory.createFunctionLiteralParameterList(parameterString)
val oldParameterList = functionLiteral.getValueParameterList()
val oldParameterList = functionLiteral.valueParameterList
if (oldParameterList != null) {
oldParameterList.replace(newParameterList)
}
else {
val openBraceElement = functionLiteral.getLBrace()
val nextSibling = openBraceElement.getNextSibling()
val addNewline = nextSibling is PsiWhiteSpace && nextSibling.getText()?.contains("\n") ?: false
val openBraceElement = functionLiteral.lBrace
val nextSibling = openBraceElement.nextSibling
val addNewline = nextSibling is PsiWhiteSpace && nextSibling.text?.contains("\n") ?: false
val (whitespace, arrow) = psiFactory.createWhitespaceAndArrow()
functionLiteral.addRangeAfter(whitespace, arrow, openBraceElement)
functionLiteral.addAfter(newParameterList, openBraceElement)
@@ -68,6 +68,6 @@ public class SpecifyExplicitLambdaSignatureIntention : SelfTargetingIntention<Kt
functionLiteral.addAfter(psiFactory.createNewLine(), openBraceElement)
}
}
ShortenReferences.DEFAULT.process(element.getValueParameters())
ShortenReferences.DEFAULT.process(element.valueParameters)
}
}
@@ -34,21 +34,21 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import java.util.*
public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention<KtCallableDeclaration>(javaClass(), "Specify type explicitly"), LowPriorityAction {
public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention<KtCallableDeclaration>(KtCallableDeclaration::class.java, "Specify type explicitly"), LowPriorityAction {
override fun isApplicableTo(element: KtCallableDeclaration, caretOffset: Int): Boolean {
if (element.getContainingFile() is KtCodeFragment) return false
if (element.containingFile is KtCodeFragment) return false
if (element is KtFunctionLiteral) return false // TODO: should JetFunctionLiteral be JetCallableDeclaration at all?
if (element is KtConstructor<*>) return false
if (element.getTypeReference() != null) return false
if (element.typeReference != null) return false
if (getTypeForDeclaration(element).isError()) return false
if (getTypeForDeclaration(element).isError) return false
val initializer = (element as? KtWithExpressionInitializer)?.getInitializer()
if (initializer != null && initializer.getTextRange().containsOffset(caretOffset)) return false
val initializer = (element as? KtWithExpressionInitializer)?.initializer
if (initializer != null && initializer.textRange.containsOffset(caretOffset)) return false
if (element is KtNamedFunction && element.hasBlockBody()) return false
setText(if (element is KtFunction) "Specify return type explicitly" else "Specify type explicitly")
text = if (element is KtFunction) "Specify return type explicitly" else "Specify type explicitly"
return true
}
@@ -61,12 +61,12 @@ public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention<KtCallableD
companion object {
public fun getTypeForDeclaration(declaration: KtCallableDeclaration): KotlinType {
val descriptor = declaration.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
val type = (descriptor as? CallableDescriptor)?.getReturnType()
val type = (descriptor as? CallableDescriptor)?.returnType
return type ?: ErrorUtils.createErrorType("null type")
}
public fun createTypeExpressionForTemplate(exprType: KotlinType): Expression {
val descriptor = exprType.getConstructor().getDeclarationDescriptor()
val descriptor = exprType.constructor.declarationDescriptor
val isAnonymous = descriptor != null && DescriptorUtils.isAnonymousObject(descriptor)
val allSupertypes = TypeUtils.getAllSupertypes(exprType)
@@ -91,8 +91,8 @@ public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention<KtCallableD
public fun createTypeReferencePostprocessor(declaration: KtCallableDeclaration): TemplateEditingAdapter {
return object : TemplateEditingAdapter() {
override fun templateFinished(template: Template?, brokenOff: Boolean) {
val typeRef = declaration.getTypeReference()
if (typeRef != null && typeRef.isValid()) {
val typeRef = declaration.typeReference
if (typeRef != null && typeRef.isValid) {
ShortenReferences.DEFAULT.process(typeRef)
}
}
@@ -100,21 +100,21 @@ public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention<KtCallableD
}
private fun addTypeAnnotationWithTemplate(editor: Editor, declaration: KtCallableDeclaration, exprType: KotlinType) {
assert(!exprType.isError()) { "Unexpected error type, should have been checked before: " + declaration.getElementTextWithContext() + ", type = " + exprType }
assert(!exprType.isError) { "Unexpected error type, should have been checked before: " + declaration.getElementTextWithContext() + ", type = " + exprType }
val project = declaration.getProject()
val project = declaration.project
val expression = createTypeExpressionForTemplate(exprType)
declaration.setType(KotlinBuiltIns.FQ_NAMES.any.asString())
PsiDocumentManager.getInstance(project).commitAllDocuments()
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument())
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
val newTypeRef = declaration.getTypeReference()!!
val newTypeRef = declaration.typeReference!!
val builder = TemplateBuilderImpl(newTypeRef)
builder.replaceElement(newTypeRef, expression)
editor.getCaretModel().moveToOffset(newTypeRef.getNode().getStartOffset())
editor.caretModel.moveToOffset(newTypeRef.node.startOffset)
TemplateManager.getInstance(project).startTemplate(editor, builder.buildInlineTemplate(), createTypeReferencePostprocessor(declaration))
}
@@ -29,11 +29,11 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class SplitIfIntention : SelfTargetingIntention<KtExpression>(javaClass(), "Split if into 2 if's") {
public class SplitIfIntention : SelfTargetingIntention<KtExpression>(KtExpression::class.java, "Split if into 2 if's") {
override fun isApplicableTo(element: KtExpression, caretOffset: Int): Boolean {
return when (element) {
is KtOperationReferenceExpression -> isOperatorValid(element)
is KtIfExpression -> getFirstValidOperator(element) != null && element.getIfKeyword().getTextRange().containsOffset(caretOffset)
is KtIfExpression -> getFirstValidOperator(element) != null && element.ifKeyword.textRange.containsOffset(caretOffset)
else -> false
}
}
@@ -48,11 +48,11 @@ public class SplitIfIntention : SelfTargetingIntention<KtExpression>(javaClass()
val commentSaver = CommentSaver(ifExpression!!)
val expression = operator.getParent() as KtBinaryExpression
val rightExpression = KtPsiUtil.safeDeparenthesize(getRight(expression, ifExpression.getCondition()!!, commentSaver))
val leftExpression = KtPsiUtil.safeDeparenthesize(expression.getLeft()!!)
val thenBranch = ifExpression.getThen()!!
val elseBranch = ifExpression.getElse()
val expression = operator.parent as KtBinaryExpression
val rightExpression = KtPsiUtil.safeDeparenthesize(getRight(expression, ifExpression.condition!!, commentSaver))
val leftExpression = KtPsiUtil.safeDeparenthesize(expression.left!!)
val thenBranch = ifExpression.then!!
val elseBranch = ifExpression.`else`
val psiFactory = KtPsiFactory(element)
@@ -62,7 +62,7 @@ public class SplitIfIntention : SelfTargetingIntention<KtExpression>(javaClass()
KtTokens.ANDAND -> psiFactory.createIf(leftExpression, psiFactory.createSingleStatementBlock(innerIf), elseBranch)
KtTokens.OROR -> {
val container = ifExpression.getParent()
val container = ifExpression.parent
if (container is KtBlockExpression && elseBranch == null && thenBranch.lastBlockStatementOrThis().isExitStatement()) { // special case
val secondIf = container.addAfter(innerIf, ifExpression)
@@ -86,9 +86,9 @@ public class SplitIfIntention : SelfTargetingIntention<KtExpression>(javaClass()
private fun getRight(element: KtBinaryExpression, condition: KtExpression, commentSaver: CommentSaver): KtExpression {
//gets the textOffset of the right side of the JetBinaryExpression in context to condition
val conditionRange = condition.range
val startOffset = element.getRight()!!.startOffset - conditionRange.start
val startOffset = element.right!!.startOffset - conditionRange.start
val endOffset = conditionRange.length
val rightString = condition.getText().substring(startOffset, endOffset)
val rightString = condition.text.substring(startOffset, endOffset)
val expression = KtPsiFactory(element).createExpression(rightString)
commentSaver.elementCreatedByText(expression, condition, TextRange(startOffset, endOffset))
@@ -96,8 +96,8 @@ public class SplitIfIntention : SelfTargetingIntention<KtExpression>(javaClass()
}
private fun getFirstValidOperator(element: KtIfExpression): KtOperationReferenceExpression? {
val condition = element.getCondition() ?: return null
return PsiTreeUtil.findChildrenOfType(condition, javaClass<KtOperationReferenceExpression>())
val condition = element.condition ?: return null
return PsiTreeUtil.findChildrenOfType(condition, KtOperationReferenceExpression::class.java)
.firstOrNull { isOperatorValid(it) }
}
@@ -105,21 +105,21 @@ public class SplitIfIntention : SelfTargetingIntention<KtExpression>(javaClass()
val operator = element.getReferencedNameElementType()
if (operator != KtTokens.ANDAND && operator != KtTokens.OROR) return false
var expression = element.getParent() as? KtBinaryExpression ?: return false
var expression = element.parent as? KtBinaryExpression ?: return false
if (expression.getRight() == null || expression.getLeft() == null) return false
if (expression.right == null || expression.left == null) return false
while (true) {
expression = expression.getParent() as? KtBinaryExpression ?: break
if (expression.getOperationToken() != operator) return false
expression = expression.parent as? KtBinaryExpression ?: break
if (expression.operationToken != operator) return false
}
val ifExpression = expression.getParent()?.getParent() as? KtIfExpression ?: return false
val ifExpression = expression.parent?.parent as? KtIfExpression ?: return false
if (ifExpression.getCondition() == null) return false
if (!PsiTreeUtil.isAncestor(ifExpression.getCondition(), element, false)) return false
if (ifExpression.condition == null) return false
if (!PsiTreeUtil.isAncestor(ifExpression.condition, element, false)) return false
if (ifExpression.getThen() == null) return false
if (ifExpression.then == null) return false
return true
}
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.psi.createExpressionByPattern
import org.jetbrains.kotlin.idea.core.copied
import org.jetbrains.kotlin.types.expressions.OperatorConventions
public class SwapBinaryExpressionIntention : SelfTargetingIntention<KtBinaryExpression>(javaClass(), "Flip binary expression"), LowPriorityAction {
public class SwapBinaryExpressionIntention : SelfTargetingIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Flip binary expression"), LowPriorityAction {
companion object {
private val SUPPORTED_OPERATIONS = setOf(PLUS, MUL, OROR, ANDAND, EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ, GT, LT, GTEQ, LTEQ)
@@ -36,18 +36,18 @@ public class SwapBinaryExpressionIntention : SelfTargetingIntention<KtBinaryExpr
}
override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean {
val opRef = element.getOperationReference()
if (!opRef.getTextRange().containsOffset(caretOffset)) return false
val opRef = element.operationReference
if (!opRef.textRange.containsOffset(caretOffset)) return false
if (leftSubject(element) == null || rightSubject(element) == null) {
return false
}
val operationToken = element.getOperationToken()
val operationTokenText = opRef.getText()
val operationToken = element.operationToken
val operationTokenText = opRef.text
if (operationToken in SUPPORTED_OPERATIONS
|| operationToken == IDENTIFIER && operationTokenText in SUPPORTED_OPERATION_NAMES) {
setText("Flip '$operationTokenText'")
text = "Flip '$operationTokenText'"
return true
}
return false
@@ -55,7 +55,7 @@ public class SwapBinaryExpressionIntention : SelfTargetingIntention<KtBinaryExpr
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
// Have to use text here to preserve names like "plus"
val operator = element.getOperationReference().getText()!!
val operator = element.operationReference.text!!
val convertedOperator = when (operator) {
">" -> "<"
"<" -> ">"
@@ -69,15 +69,15 @@ public class SwapBinaryExpressionIntention : SelfTargetingIntention<KtBinaryExpr
val leftCopy = left.copied()
left.replace(rightCopy)
right.replace(leftCopy)
element.replace(KtPsiFactory(element).createExpressionByPattern("$0 $convertedOperator $1" , element.getLeft()!!, element.getRight()!!))
element.replace(KtPsiFactory(element).createExpressionByPattern("$0 $convertedOperator $1", element.left!!, element.right!!))
}
private fun leftSubject(element: KtBinaryExpression): KtExpression? {
return firstDescendantOfTighterPrecedence(element.getLeft(), PsiPrecedences.getPrecedence(element), KtBinaryExpression::getRight)
return firstDescendantOfTighterPrecedence(element.left, PsiPrecedences.getPrecedence(element), KtBinaryExpression::getRight)
}
private fun rightSubject(element: KtBinaryExpression): KtExpression? {
return firstDescendantOfTighterPrecedence(element.getRight(), PsiPrecedences.getPrecedence(element), KtBinaryExpression::getLeft)
return firstDescendantOfTighterPrecedence(element.right, PsiPrecedences.getPrecedence(element), KtBinaryExpression::getLeft)
}
private fun firstDescendantOfTighterPrecedence(expression: KtExpression?, precedence: Int, getChild: KtBinaryExpression.() -> KtExpression?): KtExpression? {
@@ -23,16 +23,16 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
public class ToInfixCallIntention : SelfTargetingIntention<KtCallExpression>(javaClass(), "Replace with infix function call") {
public class ToInfixCallIntention : SelfTargetingIntention<KtCallExpression>(KtCallExpression::class.java, "Replace with infix function call") {
override fun isApplicableTo(element: KtCallExpression, caretOffset: Int): Boolean {
val calleeExpr = element.getCalleeExpression() as? KtNameReferenceExpression ?: return false
if (!calleeExpr.getTextRange().containsOffset(caretOffset)) return false
val calleeExpr = element.calleeExpression as? KtNameReferenceExpression ?: return false
if (!calleeExpr.textRange.containsOffset(caretOffset)) return false
val dotQualified = element.getParent() as? KtDotQualifiedExpression ?: return false
val dotQualified = element.parent as? KtDotQualifiedExpression ?: return false
if (element.getTypeArgumentList() != null) return false
if (element.typeArgumentList != null) return false
val argument = element.getValueArguments().singleOrNull() ?: return false
val argument = element.valueArguments.singleOrNull() ?: return false
if (argument.isNamed()) return false
if (argument.getArgumentExpression() == null) return false
@@ -48,10 +48,10 @@ public class ToInfixCallIntention : SelfTargetingIntention<KtCallExpression>(jav
}
override fun applyTo(element: KtCallExpression, editor: Editor) {
val dotQualified = element.getParent() as KtDotQualifiedExpression
val receiver = dotQualified.getReceiverExpression()
val argument = element.getValueArguments().single().getArgumentExpression()!!
val name = element.getCalleeExpression()!!.getText()
val dotQualified = element.parent as KtDotQualifiedExpression
val receiver = dotQualified.receiverExpression
val argument = element.valueArguments.single().getArgumentExpression()!!
val name = element.calleeExpression!!.text
val newCall = KtPsiFactory(element).createExpressionByPattern("$0 $name $1", receiver, argument)
dotQualified.replace(newCall)
@@ -55,7 +55,7 @@ import org.jetbrains.kotlin.types.TypeUtils
class UsePropertyAccessSyntaxInspection : IntentionBasedInspection<KtCallExpression>(UsePropertyAccessSyntaxIntention()), CleanupLocalInspectionTool
class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention<KtCallExpression>(javaClass(), "Use property access syntax") {
class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention<KtCallExpression>(KtCallExpression::class.java, "Use property access syntax") {
override fun isApplicableTo(element: KtCallExpression): Boolean {
return detectPropertyNameToUse(element) != null
}
@@ -65,8 +65,8 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
}
public fun applyTo(element: KtCallExpression, propertyName: Name): KtExpression {
val arguments = element.getValueArguments()
return when (arguments.size()) {
val arguments = element.valueArguments
return when (arguments.size) {
0 -> replaceWithPropertyGet(element, propertyName)
1 -> replaceWithPropertySet(element, propertyName, arguments.single())
else -> error("More than one argument in call to accessor")
@@ -74,16 +74,16 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
}
public fun detectPropertyNameToUse(callExpression: KtCallExpression): Name? {
if (callExpression.getQualifiedExpressionForSelector()?.getReceiverExpression() is KtSuperExpression) return null // cannot call extensions on "super"
if (callExpression.getQualifiedExpressionForSelector()?.receiverExpression is KtSuperExpression) return null // cannot call extensions on "super"
val callee = callExpression.getCalleeExpression() as? KtNameReferenceExpression ?: return null
val callee = callExpression.calleeExpression as? KtNameReferenceExpression ?: return null
val resolutionFacade = callExpression.getResolutionFacade()
val bindingContext = resolutionFacade.analyze(callExpression, BodyResolveMode.PARTIAL)
val resolvedCall = callExpression.getResolvedCall(bindingContext) ?: return null
if (!resolvedCall.isReallySuccess()) return null
val function = resolvedCall.getResultingDescriptor() as? FunctionDescriptor ?: return null
val function = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return null
val resolutionScope = callExpression.getResolutionScope(bindingContext, resolutionFacade)
val property = findSyntheticProperty(function, resolutionScope) ?: return null
@@ -93,7 +93,7 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
if (!checkWillResolveToProperty(resolvedCall, property, bindingContext, resolutionScope, dataFlowInfo, expectedType, resolutionFacade)) return null
val isSetUsage = callExpression.valueArguments.size() == 1
val isSetUsage = callExpression.valueArguments.size == 1
if (isSetUsage && property.type != function.valueParameters.single().type) {
val qualifiedExpressionCopy = qualifiedExpression.copied()
val callExpressionCopy = ((qualifiedExpressionCopy as? KtQualifiedExpression)?.selectorExpression ?: qualifiedExpressionCopy) as KtCallExpression
@@ -144,7 +144,7 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
private fun findSyntheticProperty(function: FunctionDescriptor, resolutionScope: LexicalScope): SyntheticJavaPropertyDescriptor? {
SyntheticJavaPropertyDescriptor.findByGetterOrSetter(function, resolutionScope)?.let { return it }
for (overridden in function.getOverriddenDescriptors()) {
for (overridden in function.overriddenDescriptors) {
findSyntheticProperty(overridden, resolutionScope)?.let { return it }
}
@@ -167,7 +167,7 @@ class UsePropertyAccessSyntaxIntention : SelfTargetingOffsetIndependentIntention
}
val newExpression = KtPsiFactory(callExpression).createExpressionByPattern(
pattern,
qualifiedExpression.getReceiverExpression(),
qualifiedExpression.receiverExpression,
propertyName,
argument.getArgumentExpression()!!
)
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
fun KtCallableDeclaration.setType(type: KotlinType, shortenReferences: Boolean = true) {
if (type.isError()) return
if (type.isError) return
setType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type), shortenReferences)
}
@@ -49,18 +49,18 @@ fun KtCallableDeclaration.setType(typeString: String, shortenReferences: Boolean
}
fun KtCallableDeclaration.setReceiverType(type: KotlinType) {
if (type.isError()) return
val typeReference = KtPsiFactory(getProject()).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
if (type.isError) return
val typeReference = KtPsiFactory(project).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
setReceiverTypeReference(typeReference)
ShortenReferences.DEFAULT.process(getReceiverTypeReference()!!)
ShortenReferences.DEFAULT.process(receiverTypeReference!!)
}
fun KtContainerNode.description(): String? {
when (getNode().getElementType()) {
when (node.elementType) {
KtNodeTypes.THEN -> return "if"
KtNodeTypes.ELSE -> return "else"
KtNodeTypes.BODY -> {
when (getParent()) {
when (parent) {
is KtWhileExpression -> return "while"
is KtDoWhileExpression -> return "do...while"
is KtForExpression -> return "for"
@@ -79,14 +79,14 @@ fun isAutoCreatedItUsage(expression: KtNameReferenceExpression): Boolean {
// returns assignment which replaces initializer
fun splitPropertyDeclaration(property: KtProperty): KtBinaryExpression {
val parent = property.getParent()!!
val parent = property.parent!!
val initializer = property.getInitializer()!!
val initializer = property.initializer!!
val explicitTypeToSet = if (property.getTypeReference() != null) null else initializer.analyze().getType(initializer)
val explicitTypeToSet = if (property.typeReference != null) null else initializer.analyze().getType(initializer)
val psiFactory = KtPsiFactory(property)
var assignment = psiFactory.createExpressionByPattern("$0 = $1", property.getNameAsName()!!, initializer)
var assignment = psiFactory.createExpressionByPattern("$0 = $1", property.nameAsName!!, initializer)
assignment = parent.addAfter(assignment, property) as KtBinaryExpression
parent.addAfter(psiFactory.createNewLine(), property)
@@ -101,10 +101,10 @@ fun splitPropertyDeclaration(property: KtProperty): KtBinaryExpression {
}
val KtQualifiedExpression.callExpression: KtCallExpression?
get() = getSelectorExpression() as? KtCallExpression
get() = selectorExpression as? KtCallExpression
val KtQualifiedExpression.calleeName: String?
get() = (callExpression?.getCalleeExpression() as? KtNameReferenceExpression)?.getText()
get() = (callExpression?.calleeExpression as? KtNameReferenceExpression)?.text
fun KtQualifiedExpression.toResolvedCall(bodyResolveMode: BodyResolveMode): ResolvedCall<out CallableDescriptor>? {
val callExpression = callExpression ?: return null
@@ -120,7 +120,7 @@ fun KtExpression.isExitStatement(): Boolean {
// returns false for call of super, static method or method from package
fun KtQualifiedExpression.isReceiverExpressionWithValue(): Boolean {
val receiver = getReceiverExpression()
val receiver = receiverExpression
if (receiver is KtSuperExpression) return false
return analyze().getType(receiver) != null
}
@@ -135,8 +135,8 @@ private fun KtExpression.specialNegation(): KtExpression? {
val factory = KtPsiFactory(this)
when (this) {
is KtPrefixExpression -> {
if (getOperationReference().getReferencedName() == "!") {
val baseExpression = getBaseExpression()
if (operationReference.getReferencedName() == "!") {
val baseExpression = baseExpression
if (baseExpression != null) {
val context = baseExpression.analyzeAndGetResult().bindingContext
val type = context.getType(baseExpression)
@@ -148,15 +148,15 @@ private fun KtExpression.specialNegation(): KtExpression? {
}
is KtBinaryExpression -> {
val operator = getOperationToken()
val operator = operationToken
if (operator !in NEGATABLE_OPERATORS) return null
val left = getLeft() ?: return null
val right = getRight() ?: return null
val left = left ?: return null
val right = right ?: return null
return factory.createExpressionByPattern("$0 $1 $2", left, getNegatedOperatorText(operator), right)
}
is KtConstantExpression -> {
return when (getText()) {
return when (text) {
"true" -> factory.createExpression("false")
"false" -> factory.createExpression("true")
else -> null
@@ -172,18 +172,18 @@ private val NEGATABLE_OPERATORS = setOf(KtTokens.EQEQ, KtTokens.EXCLEQ, KtTokens
private fun getNegatedOperatorText(token: IElementType): String {
return when(token) {
KtTokens.EQEQ -> KtTokens.EXCLEQ.getValue()
KtTokens.EXCLEQ -> KtTokens.EQEQ.getValue()
KtTokens.EQEQEQ -> KtTokens.EXCLEQEQEQ.getValue()
KtTokens.EXCLEQEQEQ -> KtTokens.EQEQEQ.getValue()
KtTokens.IS_KEYWORD -> KtTokens.NOT_IS.getValue()
KtTokens.NOT_IS -> KtTokens.IS_KEYWORD.getValue()
KtTokens.IN_KEYWORD -> KtTokens.NOT_IN.getValue()
KtTokens.NOT_IN -> KtTokens.IN_KEYWORD.getValue()
KtTokens.LT -> KtTokens.GTEQ.getValue()
KtTokens.LTEQ -> KtTokens.GT.getValue()
KtTokens.GT -> KtTokens.LTEQ.getValue()
KtTokens.GTEQ -> KtTokens.LT.getValue()
KtTokens.EQEQ -> KtTokens.EXCLEQ.value
KtTokens.EXCLEQ -> KtTokens.EQEQ.value
KtTokens.EQEQEQ -> KtTokens.EXCLEQEQEQ.value
KtTokens.EXCLEQEQEQ -> KtTokens.EQEQEQ.value
KtTokens.IS_KEYWORD -> KtTokens.NOT_IS.value
KtTokens.NOT_IS -> KtTokens.IS_KEYWORD.value
KtTokens.IN_KEYWORD -> KtTokens.NOT_IN.value
KtTokens.NOT_IN -> KtTokens.IN_KEYWORD.value
KtTokens.LT -> KtTokens.GTEQ.value
KtTokens.LTEQ -> KtTokens.GT.value
KtTokens.GT -> KtTokens.LTEQ.value
KtTokens.GTEQ -> KtTokens.LT.value
else -> throw IllegalArgumentException("The token $token does not have a negated equivalent.")
}
}
@@ -24,14 +24,14 @@ import org.jetbrains.kotlin.utils.addToStdlib.check
object BranchedFoldingUtils {
public fun getFoldableBranchedAssignment(branch: KtExpression?): KtBinaryExpression? {
fun checkAssignment(expression: KtBinaryExpression): Boolean {
if (expression.getOperationToken() !in KtTokens.ALL_ASSIGNMENTS) return false
if (expression.operationToken !in KtTokens.ALL_ASSIGNMENTS) return false
val left = expression.getLeft() as? KtNameReferenceExpression ?: return false
if (expression.getRight() == null) return false
val left = expression.left as? KtNameReferenceExpression ?: return false
if (expression.right == null) return false
val parent = expression.getParent()
val parent = expression.parent
if (parent is KtBlockExpression) {
return !KtPsiUtil.checkVariableDeclarationInBlock(parent, left.getText())
return !KtPsiUtil.checkVariableDeclarationInBlock(parent, left.text)
}
return true
@@ -40,10 +40,10 @@ object BranchedFoldingUtils {
}
public fun getFoldableBranchedReturn(branch: KtExpression?): KtReturnExpression? {
return (branch?.lastBlockStatementOrThis() as? KtReturnExpression)?.check { it.getReturnedExpression() != null }
return (branch?.lastBlockStatementOrThis() as? KtReturnExpression)?.check { it.returnedExpression != null }
}
public fun checkAssignmentsMatch(a1: KtBinaryExpression, a2: KtBinaryExpression): Boolean {
return a1.getLeft()?.getText() == a2.getLeft()?.getText() && a1.getOperationToken() == a2.getOperationToken()
return a1.left?.text == a2.left?.text && a1.operationToken == a2.operationToken
}
}
@@ -23,14 +23,14 @@ import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
public object BranchedUnfoldingUtils {
public fun unfoldAssignmentToIf(assignment: KtBinaryExpression, editor: Editor) {
val op = assignment.getOperationReference().getText()
val left = assignment.getLeft()!!
val ifExpression = assignment.getRight() as KtIfExpression
val op = assignment.operationReference.text
val left = assignment.left!!
val ifExpression = assignment.right as KtIfExpression
val newIfExpression = ifExpression.copied()
val thenExpr = newIfExpression.getThen()!!.lastBlockStatementOrThis()
val elseExpr = newIfExpression.getElse()!!.lastBlockStatementOrThis()
val thenExpr = newIfExpression.then!!.lastBlockStatementOrThis()
val elseExpr = newIfExpression.`else`!!.lastBlockStatementOrThis()
val psiFactory = KtPsiFactory(assignment)
thenExpr.replace(psiFactory.createExpressionByPattern("$0 $1 $2", left, op, thenExpr))
@@ -38,23 +38,23 @@ public object BranchedUnfoldingUtils {
val resultIf = assignment.replace(newIfExpression)
editor.getCaretModel().moveToOffset(resultIf.getTextOffset())
editor.caretModel.moveToOffset(resultIf.textOffset)
}
public fun unfoldAssignmentToWhen(assignment: KtBinaryExpression, editor: Editor) {
val op = assignment.getOperationReference().getText()
val left = assignment.getLeft()!!
val whenExpression = assignment.getRight() as KtWhenExpression
val op = assignment.operationReference.text
val left = assignment.left!!
val whenExpression = assignment.right as KtWhenExpression
val newWhenExpression = whenExpression.copied()
for (entry in newWhenExpression.getEntries()) {
val expr = entry.getExpression()!!.lastBlockStatementOrThis()
for (entry in newWhenExpression.entries) {
val expr = entry.expression!!.lastBlockStatementOrThis()
expr.replace(KtPsiFactory(assignment).createExpressionByPattern("$0 $1 $2", left, op, expr))
}
val resultWhen = assignment.replace(newWhenExpression)
editor.getCaretModel().moveToOffset(resultWhen.getTextOffset())
editor.caretModel.moveToOffset(resultWhen.textOffset)
}
}
@@ -38,11 +38,11 @@ val NULL_PTR_EXCEPTION_FQ = "java.lang.NullPointerException"
val KOTLIN_NULL_PTR_EXCEPTION_FQ = "kotlin.KotlinNullPointerException"
fun KtBinaryExpression.expressionComparedToNull(): KtExpression? {
val operationToken = this.getOperationToken()
val operationToken = this.operationToken
if (operationToken != KtTokens.EQEQ && operationToken != KtTokens.EXCLEQ) return null
val right = this.getRight() ?: return null
val left = this.getLeft() ?: return null
val right = this.right ?: return null
val left = this.left ?: return null
val rightIsNull = right.isNullExpression()
val leftIsNull = left.isNullExpression()
@@ -53,31 +53,31 @@ fun KtBinaryExpression.expressionComparedToNull(): KtExpression? {
fun KtExpression.unwrapBlockOrParenthesis(): KtExpression {
val innerExpression = KtPsiUtil.safeDeparenthesize(this)
if (innerExpression is KtBlockExpression) {
val statement = innerExpression.getStatements().singleOrNull() ?: return this
val statement = innerExpression.statements.singleOrNull() ?: return this
return KtPsiUtil.safeDeparenthesize(statement)
}
return innerExpression
}
fun KtExpression?.isNullExpression(): Boolean = this?.unwrapBlockOrParenthesis()?.getNode()?.getElementType() == KtNodeTypes.NULL
fun KtExpression?.isNullExpression(): Boolean = this?.unwrapBlockOrParenthesis()?.node?.elementType == KtNodeTypes.NULL
fun KtExpression?.isNullExpressionOrEmptyBlock(): Boolean = this.isNullExpression() || this is KtBlockExpression && this.getStatements().isEmpty()
fun KtExpression?.isNullExpressionOrEmptyBlock(): Boolean = this.isNullExpression() || this is KtBlockExpression && this.statements.isEmpty()
fun KtThrowExpression.throwsNullPointerExceptionWithNoArguments(): Boolean {
val thrownExpression = this.getThrownExpression()
val thrownExpression = this.thrownExpression
if (thrownExpression !is KtCallExpression) return false
val context = this.analyze(BodyResolveMode.PARTIAL)
val nameExpression = thrownExpression.calleeExpression as? KtNameReferenceExpression ?: return false
val descriptor = context[BindingContext.REFERENCE_TARGET, nameExpression]
val declDescriptor = descriptor?.getContainingDeclaration() ?: return false
val declDescriptor = descriptor?.containingDeclaration ?: return false
val exceptionName = DescriptorUtils.getFqName(declDescriptor).asString()
return (exceptionName == NULL_PTR_EXCEPTION_FQ || exceptionName == KOTLIN_NULL_PTR_EXCEPTION_FQ) && thrownExpression.getValueArguments().isEmpty()
return (exceptionName == NULL_PTR_EXCEPTION_FQ || exceptionName == KOTLIN_NULL_PTR_EXCEPTION_FQ) && thrownExpression.valueArguments.isEmpty()
}
fun KtExpression.evaluatesTo(other: KtExpression): Boolean {
return this.unwrapBlockOrParenthesis().getText() == other.getText()
return this.unwrapBlockOrParenthesis().text == other.text
}
fun KtExpression.convertToIfNotNullExpression(conditionLhs: KtExpression, thenClause: KtExpression, elseClause: KtExpression?): KtIfExpression {
@@ -95,8 +95,8 @@ fun KtExpression.convertToIfStatement(condition: KtExpression, thenClause: KtExp
}
fun KtIfExpression.introduceValueForCondition(occurrenceInThenClause: KtExpression, editor: Editor) {
val project = this.getProject()
val occurrenceInConditional = (this.getCondition() as KtBinaryExpression).getLeft()!!
val project = this.project
val occurrenceInConditional = (this.condition as KtBinaryExpression).left!!
KotlinIntroduceVariableHandler.doRefactoring(project,
editor,
occurrenceInConditional,
@@ -114,21 +114,21 @@ fun KtNameReferenceExpression.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(e
val scope = LocalSearchScope(enclosingElement!!)
val references = ReferencesSearch.search(declaration, scope).findAll()
if (references.size() == 1) {
KotlinInlineValHandler().inlineElement(this.getProject(), editor, declaration)
if (references.size == 1) {
KotlinInlineValHandler().inlineElement(this.project, editor, declaration)
}
}
fun KtSafeQualifiedExpression.inlineReceiverIfApplicableWithPrompt(editor: Editor) {
(this.getReceiverExpression() as? KtNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
(this.receiverExpression as? KtNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
}
fun KtBinaryExpression.inlineLeftSideIfApplicableWithPrompt(editor: Editor) {
(this.getLeft() as? KtNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
(this.left as? KtNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
}
fun KtPostfixExpression.inlineBaseExpressionIfApplicableWithPrompt(editor: Editor) {
(this.getBaseExpression() as? KtNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
(this.baseExpression as? KtNameReferenceExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
}
fun KtExpression.isStableVariable(): Boolean {
@@ -25,21 +25,21 @@ fun KtWhenCondition.toExpression(subject: KtExpression?): KtExpression {
val factory = KtPsiFactory(this)
when (this) {
is KtWhenConditionIsPattern -> {
val op = if (isNegated()) "!is" else "is"
return factory.createExpressionByPattern("$0 $op $1", subject ?: "_", getTypeReference() ?: "")
val op = if (isNegated) "!is" else "is"
return factory.createExpressionByPattern("$0 $op $1", subject ?: "_", typeReference ?: "")
}
is KtWhenConditionInRange -> {
val op = getOperationReference().getText()
return factory.createExpressionByPattern("$0 $op $1", subject ?: "_", getRangeExpression() ?: "")
val op = operationReference.text
return factory.createExpressionByPattern("$0 $op $1", subject ?: "_", rangeExpression ?: "")
}
is KtWhenConditionWithExpression -> {
return if (subject != null) {
factory.createExpressionByPattern("$0 == $1", subject, getExpression() ?: "")
factory.createExpressionByPattern("$0 == $1", subject, expression ?: "")
}
else {
getExpression()!!
expression!!
}
}
@@ -48,17 +48,17 @@ fun KtWhenCondition.toExpression(subject: KtExpression?): KtExpression {
}
public fun KtWhenExpression.getSubjectToIntroduce(): KtExpression? {
if (getSubjectExpression() != null) return null
if (subjectExpression != null) return null
var lastCandidate: KtExpression? = null
for (entry in getEntries()) {
val conditions = entry.getConditions()
if (!entry.isElse() && conditions.isEmpty()) return null
for (entry in entries) {
val conditions = entry.conditions
if (!entry.isElse && conditions.isEmpty()) return null
for (condition in conditions) {
if (condition !is KtWhenConditionWithExpression) return null
val candidate = condition.getExpression()?.getWhenConditionSubjectCandidate() as? KtNameReferenceExpression ?: return null
val candidate = condition.expression?.getWhenConditionSubjectCandidate() as? KtNameReferenceExpression ?: return null
if (lastCandidate == null) {
lastCandidate = candidate
@@ -75,14 +75,14 @@ public fun KtWhenExpression.getSubjectToIntroduce(): KtExpression? {
private fun KtExpression?.getWhenConditionSubjectCandidate(): KtExpression? {
return when(this) {
is KtIsExpression -> getLeftHandSide()
is KtIsExpression -> leftHandSide
is KtBinaryExpression -> {
val lhs = getLeft()
val op = getOperationToken()
val lhs = left
val op = operationToken
when (op) {
KtTokens.IN_KEYWORD, KtTokens.NOT_IN -> lhs
KtTokens.EQEQ -> lhs as? KtNameReferenceExpression ?: getRight()
KtTokens.EQEQ -> lhs as? KtNameReferenceExpression ?: right
KtTokens.OROR -> {
val leftCandidate = lhs.getWhenConditionSubjectCandidate()
val rightCandidate = right.getWhenConditionSubjectCandidate()
@@ -103,17 +103,17 @@ public fun KtWhenExpression.introduceSubject(): KtWhenExpression {
val whenExpression = KtPsiFactory(this).buildExpression {
appendFixedText("when(").appendExpression(subject).appendFixedText("){\n")
for (entry in getEntries()) {
val branchExpression = entry.getExpression()
for (entry in entries) {
val branchExpression = entry.expression
if (entry.isElse()) {
if (entry.isElse) {
appendFixedText("else")
}
else {
for ((i, condition) in entry.getConditions().withIndex()) {
for ((i, condition) in entry.conditions.withIndex()) {
if (i > 0) appendFixedText(",")
val conditionExpression = (condition as KtWhenConditionWithExpression).getExpression()
val conditionExpression = (condition as KtWhenConditionWithExpression).expression
appendConditionWithSubjectRemoved(conditionExpression, subject)
}
}
@@ -132,17 +132,17 @@ public fun KtWhenExpression.introduceSubject(): KtWhenExpression {
private fun BuilderByPattern<KtExpression>.appendConditionWithSubjectRemoved(conditionExpression: KtExpression?, subject: KtExpression) {
when (conditionExpression) {
is KtIsExpression -> {
if (conditionExpression.isNegated()) {
if (conditionExpression.isNegated) {
appendFixedText("!")
}
appendFixedText("is ")
appendNonFormattedText(conditionExpression.getTypeReference()?.getText() ?: "")
appendNonFormattedText(conditionExpression.typeReference?.text ?: "")
}
is KtBinaryExpression -> {
val lhs = conditionExpression.getLeft()
val rhs = conditionExpression.getRight()
val op = conditionExpression.getOperationToken()
val lhs = conditionExpression.left
val rhs = conditionExpression.right
val op = conditionExpression.operationToken
when (op) {
KtTokens.IN_KEYWORD -> appendFixedText("in ").appendExpression(rhs)
KtTokens.NOT_IN -> appendFixedText("!in ").appendExpression(rhs)
@@ -39,17 +39,17 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtThrowExpression
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
public class DoubleBangToIfThenIntention : SelfTargetingRangeIntention<KtPostfixExpression>(javaClass(), "Replace '!!' expression with 'if' expression"), LowPriorityAction {
public class DoubleBangToIfThenIntention : SelfTargetingRangeIntention<KtPostfixExpression>(KtPostfixExpression::class.java, "Replace '!!' expression with 'if' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtPostfixExpression): TextRange? {
return if (element.getOperationToken() == KtTokens.EXCLEXCL && element.getBaseExpression() != null)
element.getOperationReference().getTextRange()
return if (element.operationToken == KtTokens.EXCLEXCL && element.baseExpression != null)
element.operationReference.textRange
else
null
}
override fun applyTo(element: KtPostfixExpression, editor: Editor) {
val base = KtPsiUtil.safeDeparenthesize(element.getBaseExpression()!!)
val expressionText = formatForUseInExceptionArgument(base.getText()!!)
val base = KtPsiUtil.safeDeparenthesize(element.baseExpression!!)
val expressionText = formatForUseInExceptionArgument(base.text!!)
val defaultException = KtPsiFactory(element).createExpression("throw NullPointerException()")
@@ -62,25 +62,25 @@ public class DoubleBangToIfThenIntention : SelfTargetingRangeIntention<KtPostfix
element.convertToIfNotNullExpression(base, base, defaultException)
val thrownExpression =
((if (isStatement) ifStatement.getThen() else ifStatement.getElse()) as KtThrowExpression).getThrownExpression()!!
((if (isStatement) ifStatement.then else ifStatement.`else`) as KtThrowExpression).thrownExpression!!
val message = escapeJava("Expression '$expressionText' must not be null")
val nullPtrExceptionText = "NullPointerException(\"$message\")"
val kotlinNullPtrExceptionText = "KotlinNullPointerException()"
val exceptionLookupExpression = ChooseStringExpression(listOf(nullPtrExceptionText, kotlinNullPtrExceptionText))
val project = element.getProject()
val project = element.project
val builder = TemplateBuilderImpl(thrownExpression)
builder.replaceElement(thrownExpression, exceptionLookupExpression);
PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
editor.getCaretModel().moveToOffset(thrownExpression.getNode()!!.getStartOffset());
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document);
editor.caretModel.moveToOffset(thrownExpression.node!!.startOffset);
TemplateManager.getInstance(project).startTemplate(editor, builder.buildInlineTemplate(), object: TemplateEditingAdapter() {
override fun templateFinished(template: Template?, brokenOff: Boolean) {
if (!isStable && !isStatement) {
ifStatement.introduceValueForCondition(ifStatement.getThen()!!, editor)
ifStatement.introduceValueForCondition(ifStatement.then!!, editor)
}
}
})
@@ -88,7 +88,7 @@ public class DoubleBangToIfThenIntention : SelfTargetingRangeIntention<KtPostfix
private fun formatForUseInExceptionArgument(expressionText: String): String {
val lines = expressionText.split('\n')
return if (lines.size() > 1)
return if (lines.size > 1)
lines.first().trim() + " ..."
else
expressionText.trim()
@@ -26,23 +26,23 @@ import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.kotlin.psi.buildExpression
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class EliminateWhenSubjectIntention : SelfTargetingIntention<KtWhenExpression>(javaClass(), "Eliminate argument of 'when'"), LowPriorityAction {
public class EliminateWhenSubjectIntention : SelfTargetingIntention<KtWhenExpression>(KtWhenExpression::class.java, "Eliminate argument of 'when'"), LowPriorityAction {
override fun isApplicableTo(element: KtWhenExpression, caretOffset: Int): Boolean {
if (element.getSubjectExpression() !is KtNameReferenceExpression) return false
val lBrace = element.getOpenBrace() ?: return false
if (element.subjectExpression !is KtNameReferenceExpression) return false
val lBrace = element.openBrace ?: return false
return caretOffset <= lBrace.startOffset
}
override fun applyTo(element: KtWhenExpression, editor: Editor) {
val subject = element.getSubjectExpression()!!
val subject = element.subjectExpression!!
val whenExpression = KtPsiFactory(element).buildExpression {
appendFixedText("when {\n")
for (entry in element.getEntries()) {
val branchExpression = entry.getExpression()
for (entry in element.entries) {
val branchExpression = entry.expression
if (entry.isElse()) {
if (entry.isElse) {
appendFixedText("else")
}
else {
@@ -27,24 +27,24 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
public class ElvisToIfThenIntention : SelfTargetingRangeIntention<KtBinaryExpression>(javaClass(), "Replace elvis expression with 'if' expression"), LowPriorityAction {
public class ElvisToIfThenIntention : SelfTargetingRangeIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Replace elvis expression with 'if' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtBinaryExpression): TextRange? {
return if (element.getOperationToken() == KtTokens.ELVIS && element.getLeft() != null && element.getRight() != null)
element.getOperationReference().getTextRange()
return if (element.operationToken == KtTokens.ELVIS && element.left != null && element.right != null)
element.operationReference.textRange
else
null
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
val left = KtPsiUtil.safeDeparenthesize(element.getLeft()!!)
val right = KtPsiUtil.safeDeparenthesize(element.getRight()!!)
val left = KtPsiUtil.safeDeparenthesize(element.left!!)
val right = KtPsiUtil.safeDeparenthesize(element.right!!)
val leftIsStable = left.isStableVariable()
val ifStatement = element.convertToIfNotNullExpression(left, left, right)
if (!leftIsStable) {
ifStatement.introduceValueForCondition(ifStatement.getThen()!!, editor)
ifStatement.introduceValueForCondition(ifStatement.then!!, editor)
}
}
@@ -25,29 +25,29 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class FlattenWhenIntention : SelfTargetingIntention<KtWhenExpression>(javaClass(), "Flatten 'when' expression") {
public class FlattenWhenIntention : SelfTargetingIntention<KtWhenExpression>(KtWhenExpression::class.java, "Flatten 'when' expression") {
override fun isApplicableTo(element: KtWhenExpression, caretOffset: Int): Boolean {
val subject = element.getSubjectExpression()
val subject = element.subjectExpression
if (subject != null && subject !is KtNameReferenceExpression) return false
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(element)) return false
val elseEntry = element.getEntries().singleOrNull { it.isElse() } ?: return false
val elseEntry = element.entries.singleOrNull { it.isElse } ?: return false
val innerWhen = elseEntry.getExpression() as? KtWhenExpression ?: return false
val innerWhen = elseEntry.expression as? KtWhenExpression ?: return false
if (!subject.matches(innerWhen.getSubjectExpression())) return false
if (!subject.matches(innerWhen.subjectExpression)) return false
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(innerWhen)) return false
return elseEntry.startOffset <= caretOffset && caretOffset <= innerWhen.getWhenKeyword().endOffset
return elseEntry.startOffset <= caretOffset && caretOffset <= innerWhen.whenKeyword.endOffset
}
override fun applyTo(element: KtWhenExpression, editor: Editor) {
val subjectExpression = element.getSubjectExpression()
val nestedWhen = element.getElseExpression() as KtWhenExpression
val subjectExpression = element.subjectExpression
val nestedWhen = element.elseExpression as KtWhenExpression
val outerEntries = element.getEntries()
val innerEntries = nestedWhen.getEntries()
val outerEntries = element.entries
val innerEntries = nestedWhen.entries
val whenExpression = KtPsiFactory(element).buildExpression {
appendFixedText("when")
@@ -57,12 +57,12 @@ public class FlattenWhenIntention : SelfTargetingIntention<KtWhenExpression>(jav
appendFixedText("{\n")
for (entry in outerEntries) {
if (entry.isElse()) continue
appendNonFormattedText(entry.getText())
if (entry.isElse) continue
appendNonFormattedText(entry.text)
appendFixedText("\n")
}
for (entry in innerEntries) {
appendNonFormattedText(entry.getText())
appendNonFormattedText(entry.text)
appendFixedText("\n")
}
@@ -71,7 +71,7 @@ public class FlattenWhenIntention : SelfTargetingIntention<KtWhenExpression>(jav
val newWhen = element.replaced(whenExpression)
val firstNewEntry = newWhen.getEntries()[outerEntries.size() - 1]
editor.moveCaret(firstNewEntry.getTextOffset())
val firstNewEntry = newWhen.entries[outerEntries.size - 1]
editor.moveCaret(firstNewEntry.textOffset)
}
}
@@ -24,23 +24,23 @@ import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
public class FoldIfToAssignmentIntention : SelfTargetingRangeIntention<KtIfExpression>(javaClass(), "Replace 'if' expression with assignment") {
public class FoldIfToAssignmentIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' expression with assignment") {
override fun applicabilityRange(element: KtIfExpression): TextRange? {
val thenAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getThen()) ?: return null
val elseAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getElse()) ?: return null
val thenAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.then) ?: return null
val elseAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.`else`) ?: return null
if (!BranchedFoldingUtils.checkAssignmentsMatch(thenAssignment, elseAssignment)) return null
return element.getIfKeyword().getTextRange()
return element.ifKeyword.textRange
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
var thenAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getThen()!!)!!
val elseAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getElse()!!)!!
var thenAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.then!!)!!
val elseAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.`else`!!)!!
val op = thenAssignment.getOperationReference().getText()
val leftText = thenAssignment.getLeft()!!.getText()
val op = thenAssignment.operationReference.text
val leftText = thenAssignment.left!!.text
thenAssignment.replace(thenAssignment.getRight()!!)
elseAssignment.replace(elseAssignment.getRight()!!)
thenAssignment.replace(thenAssignment.right!!)
elseAssignment.replace(elseAssignment.right!!)
element.replace(KtPsiFactory(element).createExpressionByPattern("$0 $1 $2", leftText, op, element))
}
@@ -22,30 +22,30 @@ import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils
import org.jetbrains.kotlin.psi.*
public class FoldIfToReturnAsymmetricallyIntention : SelfTargetingRangeIntention<KtIfExpression>(javaClass(), "Replace 'if' expression with return") {
public class FoldIfToReturnAsymmetricallyIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' expression with return") {
override fun applicabilityRange(element: KtIfExpression): TextRange? {
if (BranchedFoldingUtils.getFoldableBranchedReturn(element.getThen()) == null || element.getElse() != null) {
if (BranchedFoldingUtils.getFoldableBranchedReturn(element.then) == null || element.`else` != null) {
return null
}
val nextElement = KtPsiUtil.skipTrailingWhitespacesAndComments(element) as? KtReturnExpression
if (nextElement?.getReturnedExpression() == null) return null
return element.getIfKeyword().getTextRange()
if (nextElement?.returnedExpression == null) return null
return element.ifKeyword.textRange
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
val condition = element.getCondition()!!
val thenBranch = element.getThen()!!
val condition = element.condition!!
val thenBranch = element.then!!
val elseBranch = KtPsiUtil.skipTrailingWhitespacesAndComments(element) as KtReturnExpression
val psiFactory = KtPsiFactory(element)
var newIfExpression = psiFactory.createIf(condition, thenBranch, elseBranch)
val thenReturn = BranchedFoldingUtils.getFoldableBranchedReturn(newIfExpression.getThen()!!)!!
val elseReturn = BranchedFoldingUtils.getFoldableBranchedReturn(newIfExpression.getElse()!!)!!
val thenReturn = BranchedFoldingUtils.getFoldableBranchedReturn(newIfExpression.then!!)!!
val elseReturn = BranchedFoldingUtils.getFoldableBranchedReturn(newIfExpression.`else`!!)!!
thenReturn.replace(thenReturn.getReturnedExpression()!!)
elseReturn.replace(elseReturn.getReturnedExpression()!!)
thenReturn.replace(thenReturn.returnedExpression!!)
elseReturn.replace(elseReturn.returnedExpression!!)
element.replace(psiFactory.createExpressionByPattern("return $0", newIfExpression))
elseBranch.delete()
@@ -24,19 +24,19 @@ import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
public class FoldIfToReturnIntention : SelfTargetingRangeIntention<KtIfExpression>(javaClass(), "Replace 'if' expression with return") {
public class FoldIfToReturnIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' expression with return") {
override fun applicabilityRange(element: KtIfExpression): TextRange? {
if (BranchedFoldingUtils.getFoldableBranchedReturn(element.getThen()) == null) return null
if (BranchedFoldingUtils.getFoldableBranchedReturn(element.getElse()) == null) return null
return element.getIfKeyword().getTextRange()
if (BranchedFoldingUtils.getFoldableBranchedReturn(element.then) == null) return null
if (BranchedFoldingUtils.getFoldableBranchedReturn(element.`else`) == null) return null
return element.ifKeyword.textRange
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
val thenReturn = BranchedFoldingUtils.getFoldableBranchedReturn(element.getThen()!!)!!
val elseReturn = BranchedFoldingUtils.getFoldableBranchedReturn(element.getElse()!!)!!
val thenReturn = BranchedFoldingUtils.getFoldableBranchedReturn(element.then!!)!!
val elseReturn = BranchedFoldingUtils.getFoldableBranchedReturn(element.`else`!!)!!
thenReturn.replace(thenReturn.getReturnedExpression()!!)
elseReturn.replace(elseReturn.getReturnedExpression()!!)
thenReturn.replace(thenReturn.returnedExpression!!)
elseReturn.replace(elseReturn.returnedExpression!!)
element.replace(KtPsiFactory(element).createExpressionByPattern("return $0", element))
}
@@ -23,44 +23,44 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFold
import org.jetbrains.kotlin.psi.*
import java.util.*
public class FoldWhenToAssignmentIntention : SelfTargetingRangeIntention<KtWhenExpression>(javaClass(), "Replace 'when' expression with assignment") {
public class FoldWhenToAssignmentIntention : SelfTargetingRangeIntention<KtWhenExpression>(KtWhenExpression::class.java, "Replace 'when' expression with assignment") {
override fun applicabilityRange(element: KtWhenExpression): TextRange? {
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(element)) return null
val entries = element.getEntries()
val entries = element.entries
if (entries.isEmpty()) return null
val assignments = ArrayList<KtBinaryExpression>()
for (entry in entries) {
val assignment = BranchedFoldingUtils.getFoldableBranchedAssignment(entry.getExpression()) ?: return null
val assignment = BranchedFoldingUtils.getFoldableBranchedAssignment(entry.expression) ?: return null
assignments.add(assignment)
}
assert(!assignments.isEmpty())
val firstAssignment = assignments.get(0)
val firstAssignment = assignments.first()
for (assignment in assignments) {
if (!BranchedFoldingUtils.checkAssignmentsMatch(assignment, firstAssignment)) return null
}
return element.getWhenKeyword().getTextRange()
return element.whenKeyword.textRange
}
override fun applyTo(element: KtWhenExpression, editor: Editor) {
assert(!element.getEntries().isEmpty())
assert(!element.entries.isEmpty())
val firstAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.getEntries().get(0).getExpression()!!)!!
val firstAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.entries.first().expression!!)!!
val op = firstAssignment.getOperationReference().getText()
val lhs = firstAssignment.getLeft() as KtNameReferenceExpression
val op = firstAssignment.operationReference.text
val lhs = firstAssignment.left as KtNameReferenceExpression
val assignment = KtPsiFactory(element).createExpressionByPattern("$0 $1 $2", lhs, op, element)
val newWhenExpression = (assignment as KtBinaryExpression).getRight() as KtWhenExpression
val newWhenExpression = (assignment as KtBinaryExpression).right as KtWhenExpression
for (entry in newWhenExpression.getEntries()) {
val currAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(entry.getExpression()!!)!!
val currRhs = currAssignment.getRight()!!
for (entry in newWhenExpression.entries) {
val currAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(entry.expression!!)!!
val currRhs = currAssignment.right!!
currAssignment.replace(currRhs)
}
@@ -22,30 +22,30 @@ import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils
import org.jetbrains.kotlin.psi.*
public class FoldWhenToReturnIntention : SelfTargetingRangeIntention<KtWhenExpression>(javaClass(), "Replace 'when' expression with return") {
public class FoldWhenToReturnIntention : SelfTargetingRangeIntention<KtWhenExpression>(KtWhenExpression::class.java, "Replace 'when' expression with return") {
override fun applicabilityRange(element: KtWhenExpression): TextRange? {
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(element)) return null
val entries = element.getEntries()
val entries = element.entries
if (entries.isEmpty()) return null
for (entry in entries) {
if (BranchedFoldingUtils.getFoldableBranchedReturn(entry.getExpression()) == null) return null
if (BranchedFoldingUtils.getFoldableBranchedReturn(entry.expression) == null) return null
}
return element.getWhenKeyword().getTextRange()
return element.whenKeyword.textRange
}
override fun applyTo(element: KtWhenExpression, editor: Editor) {
assert(!element.getEntries().isEmpty())
assert(!element.entries.isEmpty())
val newReturnExpression = KtPsiFactory(element).createExpressionByPattern("return $0", element) as KtReturnExpression
val newWhenExpression = newReturnExpression.getReturnedExpression() as KtWhenExpression
val newWhenExpression = newReturnExpression.returnedExpression as KtWhenExpression
for (entry in newWhenExpression.getEntries()) {
val currReturn = BranchedFoldingUtils.getFoldableBranchedReturn(entry.getExpression()!!)!!
val currExpr = currReturn.getReturnedExpression()!!
for (entry in newWhenExpression.entries) {
val currReturn = BranchedFoldingUtils.getFoldableBranchedReturn(entry.expression!!)!!
val currExpr = currReturn.returnedExpression!!
currReturn.replace(currExpr)
}
@@ -27,15 +27,15 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
public class IfThenToDoubleBangIntention : SelfTargetingRangeIntention<KtIfExpression>(javaClass(), "Replace 'if' expression with '!!' expression") {
public class IfThenToDoubleBangIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' expression with '!!' expression") {
override fun applicabilityRange(element: KtIfExpression): TextRange? {
val condition = element.getCondition() as? KtBinaryExpression ?: return null
val thenClause = element.getThen() ?: return null
val elseClause = element.getElse()
val condition = element.condition as? KtBinaryExpression ?: return null
val thenClause = element.then ?: return null
val elseClause = element.`else`
val expression = condition.expressionComparedToNull() ?: return null
val token = condition.getOperationToken()
val token = condition.operationToken
val throwExpression: KtThrowExpression
val matchingClause: KtExpression?
@@ -62,12 +62,12 @@ public class IfThenToDoubleBangIntention : SelfTargetingRangeIntention<KtIfExpre
}
setText(text)
val rParen = element.getRightParenthesis() ?: return null
val rParen = element.rightParenthesis ?: return null
return TextRange(element.startOffset, rParen.endOffset)
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
val condition = element.getCondition() as KtBinaryExpression
val condition = element.condition as KtBinaryExpression
val expression = condition.expressionComparedToNull()!!
val result = element.replace(KtPsiFactory(element).createExpressionByPattern("$0!!", expression)) as KtPostfixExpression
@@ -27,17 +27,17 @@ import org.jetbrains.kotlin.idea.core.replaced
public class IfThenToElvisInspection : IntentionBasedInspection<KtIfExpression>(IfThenToElvisIntention())
public class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(javaClass(), "Replace 'if' expression with elvis expression") {
public class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' expression with elvis expression") {
override fun isApplicableTo(element: KtIfExpression): Boolean {
val condition = element.getCondition() as? KtBinaryExpression ?: return false
val thenClause = element.getThen() ?: return false
val elseClause = element.getElse() ?: return false
val condition = element.condition as? KtBinaryExpression ?: return false
val thenClause = element.then ?: return false
val elseClause = element.`else` ?: return false
val expression = condition.expressionComparedToNull() ?: return false
if (!expression.isStableVariable()) return false
return when (condition.getOperationToken()) {
return when (condition.operationToken) {
KtTokens.EQEQ ->
thenClause.isNotNullExpression() && elseClause.evaluatesTo(expression) &&
!(thenClause is KtThrowExpression && thenClause.throwsNullPointerExceptionWithNoArguments())
@@ -53,7 +53,7 @@ public class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<Kt
private fun KtExpression.isNotNullExpression(): Boolean {
val innerExpression = this.unwrapBlockOrParenthesis()
return innerExpression !is KtBlockExpression && innerExpression.getNode().getElementType() != KtNodeTypes.NULL
return innerExpression !is KtBlockExpression && innerExpression.node.elementType != KtNodeTypes.NULL
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
@@ -62,15 +62,15 @@ public class IfThenToElvisIntention : SelfTargetingOffsetIndependentIntention<Kt
}
public fun applyTo(element: KtIfExpression): KtBinaryExpression {
val condition = element.getCondition() as KtBinaryExpression
val condition = element.condition as KtBinaryExpression
val thenClause = element.getThen()!!
val elseClause = element.getElse()!!
val thenClause = element.then!!
val elseClause = element.`else`!!
val thenExpression = thenClause.unwrapBlockOrParenthesis()
val elseExpression = elseClause.unwrapBlockOrParenthesis()
val (left, right) =
when(condition.getOperationToken()) {
when(condition.operationToken) {
KtTokens.EQEQ -> Pair(elseExpression, thenExpression)
KtTokens.EXCLEQ -> Pair(thenExpression, elseExpression)
else -> throw IllegalArgumentException()
@@ -26,17 +26,17 @@ import org.jetbrains.kotlin.idea.core.replaced
public class IfThenToSafeAccessInspection : IntentionBasedInspection<KtIfExpression>(IfThenToSafeAccessIntention())
public class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(javaClass(), "Replace 'if' expression with safe access expression") {
public class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' expression with safe access expression") {
override fun isApplicableTo(element: KtIfExpression): Boolean {
val condition = element.getCondition() as? KtBinaryExpression ?: return false
val thenClause = element.getThen()
val elseClause = element.getElse()
val condition = element.condition as? KtBinaryExpression ?: return false
val thenClause = element.then
val elseClause = element.`else`
val receiverExpression = condition.expressionComparedToNull() ?: return false
if (!receiverExpression.isStableVariable()) return false
return when (condition.getOperationToken()) {
return when (condition.operationToken) {
KtTokens.EQEQ ->
thenClause?.isNullExpressionOrEmptyBlock() ?: true &&
elseClause != null && clauseContainsAppropriateDotQualifiedExpression(elseClause, receiverExpression)
@@ -56,14 +56,14 @@ public class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntenti
}
public fun applyTo(element: KtIfExpression): KtSafeQualifiedExpression {
val condition = element.getCondition() as KtBinaryExpression
val condition = element.condition as KtBinaryExpression
val receiverExpression = condition.expressionComparedToNull()!!
val selectorExpression =
when(condition.getOperationToken()) {
KtTokens.EQEQ -> findSelectorExpressionInClause(element.getElse()!!, receiverExpression)!!
when(condition.operationToken) {
KtTokens.EQEQ -> findSelectorExpressionInClause(element.`else`!!, receiverExpression)!!
KtTokens.EXCLEQ -> findSelectorExpressionInClause(element.getThen()!!, receiverExpression)!!
KtTokens.EXCLEQ -> findSelectorExpressionInClause(element.then!!, receiverExpression)!!
else -> throw IllegalArgumentException()
}
@@ -78,8 +78,8 @@ public class IfThenToSafeAccessIntention : SelfTargetingOffsetIndependentIntenti
private fun findSelectorExpressionInClause(clause: KtExpression, receiverExpression: KtExpression): KtExpression? {
val expression = clause.unwrapBlockOrParenthesis() as? KtDotQualifiedExpression ?: return null
if (expression.getReceiverExpression().getText() != receiverExpression.getText()) return null
if (expression.receiverExpression.text != receiverExpression.text) return null
return expression.getSelectorExpression()
return expression.selectorExpression
}
}
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import java.util.*
public class IfToWhenIntention : SelfTargetingRangeIntention<KtIfExpression>(javaClass(), "Replace 'if' with 'when'") {
public class IfToWhenIntention : SelfTargetingRangeIntention<KtIfExpression>(KtIfExpression::class.java, "Replace 'if' with 'when'") {
override fun applicabilityRange(element: KtIfExpression): TextRange? {
if (element.getThen() == null) return null
return element.getIfKeyword().getTextRange()
if (element.then == null) return null
return element.ifKeyword.textRange
}
override fun applyTo(element: KtIfExpression, editor: Editor) {
@@ -37,7 +37,7 @@ public class IfToWhenIntention : SelfTargetingRangeIntention<KtIfExpression>(jav
var ifExpression = element
while (true) {
val condition = ifExpression.getCondition()
val condition = ifExpression.condition
val orBranches = ArrayList<KtExpression>()
if (condition != null) {
orBranches.addOrBranches(condition)
@@ -47,11 +47,11 @@ public class IfToWhenIntention : SelfTargetingRangeIntention<KtIfExpression>(jav
appendFixedText("->")
val thenBranch = ifExpression.getThen()
val thenBranch = ifExpression.then
appendExpression(thenBranch)
appendFixedText("\n")
val elseBranch = ifExpression.getElse() ?: break
val elseBranch = ifExpression.`else` ?: break
if (elseBranch is KtIfExpression) {
ifExpression = elseBranch
}
@@ -75,9 +75,9 @@ public class IfToWhenIntention : SelfTargetingRangeIntention<KtIfExpression>(jav
}
private fun MutableList<KtExpression>.addOrBranches(expression: KtExpression): List<KtExpression> {
if (expression is KtBinaryExpression && expression.getOperationToken() == KtTokens.OROR) {
val left = expression.getLeft()
val right = expression.getRight()
if (expression is KtBinaryExpression && expression.operationToken == KtTokens.OROR) {
val left = expression.left
val right = expression.right
if (left != null && right != null) {
addOrBranches(left)
addOrBranches(right)
@@ -26,11 +26,11 @@ import org.jetbrains.kotlin.psi.KtWhenExpression
public class IntroduceWhenSubjectInspection : IntentionBasedInspection<KtWhenExpression>(IntroduceWhenSubjectIntention())
public class IntroduceWhenSubjectIntention : SelfTargetingRangeIntention<KtWhenExpression>(javaClass(), "Introduce argument to 'when'") {
public class IntroduceWhenSubjectIntention : SelfTargetingRangeIntention<KtWhenExpression>(KtWhenExpression::class.java, "Introduce argument to 'when'") {
override fun applicabilityRange(element: KtWhenExpression): TextRange? {
val subject = element.getSubjectToIntroduce() ?: return null
setText("Introduce '${subject.getText()}' as argument to 'when'")
return element.getWhenKeyword().getTextRange()
text = "Introduce '${subject.text}' as argument to 'when'"
return element.whenKeyword.textRange
}
override fun applyTo(element: KtWhenExpression, editor: Editor) {
@@ -29,52 +29,52 @@ import org.jetbrains.kotlin.idea.util.psi.patternMatching.toRange
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
public class MergeWhenIntention : SelfTargetingRangeIntention<KtWhenExpression>(javaClass(), "Merge with next 'when'", "Merge 'when' expressions") {
public class MergeWhenIntention : SelfTargetingRangeIntention<KtWhenExpression>(KtWhenExpression::class.java, "Merge with next 'when'", "Merge 'when' expressions") {
override fun applicabilityRange(element: KtWhenExpression): TextRange? {
val next = PsiTreeUtil.skipSiblingsForward(element, javaClass<PsiWhiteSpace>()) as? KtWhenExpression ?: return null
val next = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace::class.java) as? KtWhenExpression ?: return null
val subject1 = element.getSubjectExpression()
val subject2 = next.getSubjectExpression()
val subject1 = element.subjectExpression
val subject2 = next.subjectExpression
if (!subject1.matches(subject2)) return null
if (subject1 != null && !subject1.isStableVariable()) return null
val entries1 = element.getEntries()
val entries2 = next.getEntries()
if (entries1.size() != entries2.size()) return null
val entries1 = element.entries
val entries2 = next.entries
if (entries1.size != entries2.size) return null
if (!entries1.zip(entries2).all { pair ->
conditionsMatch(pair.first, pair.second) && checkBodies(pair.first, pair.second)
}) return null
return element.getWhenKeyword().getTextRange()
return element.whenKeyword.textRange
}
private fun conditionsMatch(e1: KtWhenEntry, e2: KtWhenEntry): Boolean =
e1.getConditions().toList().toRange().matches(e2.getConditions().toList().toRange())
e1.conditions.toList().toRange().matches(e2.conditions.toList().toRange())
private fun checkBodies(e1: KtWhenEntry, e2: KtWhenEntry): Boolean {
val names1 = e1.declarationNames()
val names2 = e2.declarationNames()
if (names1.any { it in names2 }) return false
return when (e1.getExpression()?.lastBlockStatementOrThis()) {
return when (e1.expression?.lastBlockStatementOrThis()) {
is KtReturnExpression, is KtThrowExpression, is KtBreakExpression, is KtContinueExpression -> false
else -> true
}
}
private fun KtWhenEntry.declarationNames(): Set<String> =
getExpression()?.blockExpressionsOrSingle()
expression?.blockExpressionsOrSingle()
?.filter { it is KtNamedDeclaration }
?.mapNotNull { it.getName() }
?.mapNotNull { it.name }
?.toSet() ?: emptySet()
override fun applyTo(element: KtWhenExpression, editor: Editor) {
val nextWhen = PsiTreeUtil.skipSiblingsForward(element, javaClass<PsiWhiteSpace>()) as KtWhenExpression
for ((entry1, entry2) in element.getEntries().zip(nextWhen.getEntries())) {
entry1.getExpression().mergeWith(entry2.getExpression())
val nextWhen = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace::class.java) as KtWhenExpression
for ((entry1, entry2) in element.entries.zip(nextWhen.entries)) {
entry1.expression.mergeWith(entry2.expression)
}
element.getParent().deleteChildRange(element.getNextSibling(), nextWhen)
element.parent.deleteChildRange(element.nextSibling, nextWhen)
}
private fun KtExpression?.mergeWith(that: KtExpression?): KtExpression? = when {
@@ -27,15 +27,15 @@ import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isStableVari
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
public class SafeAccessToIfThenIntention : SelfTargetingRangeIntention<KtSafeQualifiedExpression>(javaClass(), "Replace safe access expression with 'if' expression"), LowPriorityAction {
public class SafeAccessToIfThenIntention : SelfTargetingRangeIntention<KtSafeQualifiedExpression>(KtSafeQualifiedExpression::class.java, "Replace safe access expression with 'if' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtSafeQualifiedExpression): TextRange? {
if (element.getSelectorExpression() == null) return null
return element.getOperationTokenNode().getTextRange()
if (element.selectorExpression == null) return null
return element.operationTokenNode.textRange
}
override fun applyTo(element: KtSafeQualifiedExpression, editor: Editor) {
val receiver = KtPsiUtil.safeDeparenthesize(element.getReceiverExpression())
val selector = element.getSelectorExpression()!!
val receiver = KtPsiUtil.safeDeparenthesize(element.receiverExpression)
val selector = element.selectorExpression!!
val receiverIsStable = receiver.isStableVariable()
@@ -46,7 +46,7 @@ public class SafeAccessToIfThenIntention : SelfTargetingRangeIntention<KtSafeQua
val ifExpression = element.convertToIfNotNullExpression(receiver, dotQualified, elseClause)
if (!receiverIsStable) {
val valueToExtract = (ifExpression.getThen() as KtDotQualifiedExpression).getReceiverExpression()
val valueToExtract = (ifExpression.then as KtDotQualifiedExpression).receiverExpression
ifExpression.introduceValueForCondition(valueToExtract, editor)
}
}
@@ -27,12 +27,12 @@ import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class UnfoldAssignmentToIfIntention : SelfTargetingRangeIntention<KtBinaryExpression>(javaClass(), "Replace assignment with 'if' expression"), LowPriorityAction {
public class UnfoldAssignmentToIfIntention : SelfTargetingRangeIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Replace assignment with 'if' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtBinaryExpression): TextRange? {
if (element.getOperationToken() !in KtTokens.ALL_ASSIGNMENTS) return null
if (element.getLeft() == null) return null
val right = element.getRight() as? KtIfExpression ?: return null
return TextRange(element.startOffset, right.getIfKeyword().endOffset)
if (element.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null
if (element.left == null) return null
val right = element.right as? KtIfExpression ?: return null
return TextRange(element.startOffset, right.ifKeyword.endOffset)
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
@@ -28,14 +28,14 @@ import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class UnfoldAssignmentToWhenIntention : SelfTargetingRangeIntention<KtBinaryExpression>(javaClass(), "Replace assignment with 'when' expression" ), LowPriorityAction {
public class UnfoldAssignmentToWhenIntention : SelfTargetingRangeIntention<KtBinaryExpression>(KtBinaryExpression::class.java, "Replace assignment with 'when' expression" ), LowPriorityAction {
override fun applicabilityRange(element: KtBinaryExpression): TextRange? {
if (element.getOperationToken() !in KtTokens.ALL_ASSIGNMENTS) return null
if (element.getLeft() == null) return null
val right = element.getRight() as? KtWhenExpression ?: return null
if (element.operationToken !in KtTokens.ALL_ASSIGNMENTS) return null
if (element.left == null) return null
val right = element.right as? KtWhenExpression ?: return null
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(right)) return null
if (right.getEntries().any { it.getExpression() == null }) return null
return TextRange(element.startOffset, right.getWhenKeyword().endOffset)
if (right.entries.any { it.expression == null }) return null
return TextRange(element.startOffset, right.whenKeyword.endOffset)
}
override fun applyTo(element: KtBinaryExpression, editor: Editor) {
@@ -27,11 +27,11 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class UnfoldPropertyToIfIntention : SelfTargetingRangeIntention<KtProperty>(javaClass(), "Replace property initializer with 'if' expression"), LowPriorityAction {
public class UnfoldPropertyToIfIntention : SelfTargetingRangeIntention<KtProperty>(KtProperty::class.java, "Replace property initializer with 'if' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtProperty): TextRange? {
if (!element.isLocal()) return null
val initializer = element.getInitializer() as? KtIfExpression ?: return null
return TextRange(element.startOffset, initializer.getIfKeyword().endOffset)
if (!element.isLocal) return null
val initializer = element.initializer as? KtIfExpression ?: return null
return TextRange(element.startOffset, initializer.ifKeyword.endOffset)
}
override fun applyTo(element: KtProperty, editor: Editor) {
@@ -28,13 +28,13 @@ import org.jetbrains.kotlin.psi.KtWhenExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class UnfoldPropertyToWhenIntention : SelfTargetingRangeIntention<KtProperty>(javaClass(), "Replace property initializer with 'when' expression"), LowPriorityAction {
public class UnfoldPropertyToWhenIntention : SelfTargetingRangeIntention<KtProperty>(KtProperty::class.java, "Replace property initializer with 'when' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtProperty): TextRange? {
if (!element.isLocal()) return null
val initializer = element.getInitializer() as? KtWhenExpression ?: return null
if (!element.isLocal) return null
val initializer = element.initializer as? KtWhenExpression ?: return null
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(initializer)) return null
if (initializer.getEntries().any { it.getExpression() == null }) return null
return TextRange(element.startOffset, initializer.getWhenKeyword().endOffset)
if (initializer.entries.any { it.expression == null }) return null
return TextRange(element.startOffset, initializer.whenKeyword.endOffset)
}
override fun applyTo(element: KtProperty, editor: Editor) {
@@ -29,17 +29,17 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class UnfoldReturnToIfIntention : SelfTargetingRangeIntention<KtReturnExpression>(javaClass(), "Replace return with 'if' expression"), LowPriorityAction {
public class UnfoldReturnToIfIntention : SelfTargetingRangeIntention<KtReturnExpression>(KtReturnExpression::class.java, "Replace return with 'if' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtReturnExpression): TextRange? {
val ifExpression = element.getReturnedExpression() as? KtIfExpression ?: return null
return TextRange(element.startOffset, ifExpression.getIfKeyword().endOffset)
val ifExpression = element.returnedExpression as? KtIfExpression ?: return null
return TextRange(element.startOffset, ifExpression.ifKeyword.endOffset)
}
override fun applyTo(element: KtReturnExpression, editor: Editor) {
val ifExpression = element.getReturnedExpression() as KtIfExpression
val ifExpression = element.returnedExpression as KtIfExpression
val newIfExpression = ifExpression.copied()
val thenExpr = newIfExpression.getThen()!!.lastBlockStatementOrThis()
val elseExpr = newIfExpression.getElse()!!.lastBlockStatementOrThis()
val thenExpr = newIfExpression.then!!.lastBlockStatementOrThis()
val elseExpr = newIfExpression.`else`!!.lastBlockStatementOrThis()
val psiFactory = KtPsiFactory(element)
thenExpr.replace(psiFactory.createExpressionByPattern("return $0", thenExpr))
@@ -26,20 +26,20 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class UnfoldReturnToWhenIntention : SelfTargetingRangeIntention<KtReturnExpression>(javaClass(), "Replace return with 'when' expression"), LowPriorityAction {
public class UnfoldReturnToWhenIntention : SelfTargetingRangeIntention<KtReturnExpression>(KtReturnExpression::class.java, "Replace return with 'when' expression"), LowPriorityAction {
override fun applicabilityRange(element: KtReturnExpression): TextRange? {
val whenExpr = element.getReturnedExpression() as? KtWhenExpression ?: return null
val whenExpr = element.returnedExpression as? KtWhenExpression ?: return null
if (!KtPsiUtil.checkWhenExpressionHasSingleElse(whenExpr)) return null
if (whenExpr.getEntries().any { it.getExpression() == null }) return null
return TextRange(element.startOffset, whenExpr.getWhenKeyword().endOffset)
if (whenExpr.entries.any { it.expression == null }) return null
return TextRange(element.startOffset, whenExpr.whenKeyword.endOffset)
}
override fun applyTo(element: KtReturnExpression, editor: Editor) {
val whenExpression = element.getReturnedExpression() as KtWhenExpression
val whenExpression = element.returnedExpression as KtWhenExpression
val newWhenExpression = whenExpression.copied()
for (entry in newWhenExpression.getEntries()) {
val expr = entry.getExpression()!!.lastBlockStatementOrThis()
for (entry in newWhenExpression.entries) {
val expr = entry.expression!!.lastBlockStatementOrThis()
expr.replace(KtPsiFactory(element).createExpressionByPattern("return $0", expr))
}
@@ -23,29 +23,29 @@ import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.combineWhenConditions
import org.jetbrains.kotlin.psi.*
public class WhenToIfIntention : SelfTargetingRangeIntention<KtWhenExpression>(javaClass(), "Replace 'when' with 'if'"), LowPriorityAction {
public class WhenToIfIntention : SelfTargetingRangeIntention<KtWhenExpression>(KtWhenExpression::class.java, "Replace 'when' with 'if'"), LowPriorityAction {
override fun applicabilityRange(element: KtWhenExpression): TextRange? {
val entries = element.getEntries()
val entries = element.entries
if (entries.isEmpty()) return null
val lastEntry = entries.last()
if (entries.any { it != lastEntry && it.isElse() }) return null
return element.getWhenKeyword().getTextRange()
if (entries.any { it != lastEntry && it.isElse }) return null
return element.whenKeyword.textRange
}
override fun applyTo(element: KtWhenExpression, editor: Editor) {
val factory = KtPsiFactory(element)
val ifExpression = factory.buildExpression {
val entries = element.getEntries()
val entries = element.entries
for ((i, entry) in entries.withIndex()) {
if (i > 0) {
appendFixedText("else ")
}
val branch = entry.getExpression()
if (entry.isElse()) {
val branch = entry.expression
if (entry.isElse) {
appendExpression(branch)
}
else {
val condition = factory.combineWhenConditions(entry.getConditions(), element.getSubjectExpression())
val condition = factory.combineWhenConditions(entry.conditions, element.subjectExpression)
appendFixedText("if (")
appendExpression(condition)
appendFixedText(")")
@@ -29,32 +29,32 @@ import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.expressions.OperatorConventions
public class ReplaceCallWithBinaryOperatorIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(javaClass(), "Replace call with binary operator"), HighPriorityAction {
public class ReplaceCallWithBinaryOperatorIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, "Replace call with binary operator"), HighPriorityAction {
override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? {
val operation = operation(element.calleeName) ?: return null
val resolvedCall = element.toResolvedCall(BodyResolveMode.PARTIAL) ?: return null
if (!resolvedCall.isReallySuccess()) return null
if (resolvedCall.getCall().getTypeArgumentList() != null) return null
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
if (resolvedCall.call.typeArgumentList != null) return null
val argument = resolvedCall.call.valueArguments.singleOrNull() ?: return null
if ((resolvedCall.getArgumentMapping(argument) as ArgumentMatch).valueParameter.index != 0) return null
if (!element.isReceiverExpressionWithValue()) return null
setText("Replace with '$operation' operator")
return element.callExpression!!.getCalleeExpression()!!.getTextRange()
text = "Replace with '$operation' operator"
return element.callExpression!!.calleeExpression!!.textRange
}
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor) {
val operation = operation(element.calleeName)!!
val argument = element.callExpression!!.getValueArguments().single().getArgumentExpression()!!
val receiver = element.getReceiverExpression()
val argument = element.callExpression!!.valueArguments.single().getArgumentExpression()!!
val receiver = element.receiverExpression
element.replace(KtPsiFactory(element).createExpressionByPattern("$0 $operation $1", receiver, argument))
}
private fun operation(functionName: String?): String? {
if (functionName == null) return null
return OperatorConventions.BINARY_OPERATION_NAMES.inverse()[Name.identifier(functionName)]?.getValue()
return OperatorConventions.BINARY_OPERATION_NAMES.inverse()[Name.identifier(functionName)]?.value
}
}
@@ -29,28 +29,28 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createExpressionByPattern
import org.jetbrains.kotlin.types.expressions.OperatorConventions
public class ReplaceCallWithUnaryOperatorIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(javaClass(), "Replace call with unary operator"), HighPriorityAction {
public class ReplaceCallWithUnaryOperatorIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, "Replace call with unary operator"), HighPriorityAction {
override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? {
val operation = operation(element.calleeName) ?: return null
val call = element.callExpression ?: return null
if (call.getTypeArgumentList() != null) return null
if (!call.getValueArguments().isEmpty()) return null
if (call.typeArgumentList != null) return null
if (!call.valueArguments.isEmpty()) return null
if (!element.isReceiverExpressionWithValue()) return null
setText("Replace with '$operation' operator")
return call.getCalleeExpression()!!.getTextRange()
text = "Replace with '$operation' operator"
return call.calleeExpression!!.textRange
}
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor) {
val operation = operation(element.calleeName)!!
val receiver = element.getReceiverExpression()
val receiver = element.receiverExpression
element.replace(KtPsiFactory(element).createExpressionByPattern("$0$1", operation, receiver))
}
private fun operation(functionName: String?) : String? {
if (functionName == null) return null
return OperatorConventions.UNARY_OPERATION_NAMES.inverse()[Name.identifier(functionName)]?.getValue()
return OperatorConventions.UNARY_OPERATION_NAMES.inverse()[Name.identifier(functionName)]?.value
}
}
@@ -28,32 +28,32 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.util.OperatorNameConventions
public class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(javaClass(), "Replace 'contains' call with 'in' operator"), HighPriorityAction {
public class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, "Replace 'contains' call with 'in' operator"), HighPriorityAction {
override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? {
if (element.calleeName != OperatorNameConventions.CONTAINS.asString()) return null
val resolvedCall = element.toResolvedCall(BodyResolveMode.PARTIAL) ?: return null
if (!resolvedCall.isReallySuccess()) return null
val argument = resolvedCall.getCall().getValueArguments().singleOrNull() ?: return null
val argument = resolvedCall.call.valueArguments.singleOrNull() ?: return null
if ((resolvedCall.getArgumentMapping(argument) as ArgumentMatch).valueParameter.index != 0) return null
val target = resolvedCall.getResultingDescriptor()
val returnType = target.getReturnType() ?: return null
val target = resolvedCall.resultingDescriptor
val returnType = target.returnType ?: return null
if (!target.builtIns.isBooleanOrSubtype(returnType)) return null
if (!element.isReceiverExpressionWithValue()) return null
return element.callExpression!!.getCalleeExpression()!!.getTextRange()
return element.callExpression!!.calleeExpression!!.textRange
}
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor) {
val argument = element.callExpression!!.getValueArguments().single().getArgumentExpression()!!
val receiver = element.getReceiverExpression()
val argument = element.callExpression!!.valueArguments.single().getArgumentExpression()!!
val receiver = element.receiverExpression
val psiFactory = KtPsiFactory(element)
val prefixExpression = element.getParent() as? KtPrefixExpression
val expression = if (prefixExpression != null && prefixExpression.getOperationToken() == KtTokens.EXCL) {
val prefixExpression = element.parent as? KtPrefixExpression
val expression = if (prefixExpression != null && prefixExpression.operationToken == KtTokens.EXCL) {
prefixExpression.replace(psiFactory.createExpressionByPattern("$0 !in $1", argument, receiver))
}
else {
@@ -63,10 +63,10 @@ public class ReplaceContainsIntention : SelfTargetingRangeIntention<KtDotQualifi
// Append semicolon to previous statement if needed
if (argument is KtLambdaExpression) {
val previousElement = KtPsiUtil.skipSiblingsBackwardByPredicate(expression) {
it.getNode().getElementType() in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET
it.node.elementType in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET
}
if (previousElement != null && previousElement is KtExpression) {
previousElement.getParent()!!.addAfter(psiFactory.createSemicolon(), previousElement)
previousElement.parent!!.addAfter(psiFactory.createSemicolon(), previousElement)
}
}
}
@@ -71,9 +71,9 @@ class ReplaceGetOrSetIntention : SelfTargetingRangeIntention<KtDotQualifiedExpre
val target = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return null
if (!target.isValidOperator() || target.name !in operatorNames) return null
if (callExpression.getTypeArgumentList() != null) return null
if (callExpression.typeArgumentList != null) return null
val arguments = callExpression.getValueArguments()
val arguments = callExpression.valueArguments
if (arguments.isEmpty()) return null
if (arguments.any { it.isNamed() }) return null
@@ -83,7 +83,7 @@ class ReplaceGetOrSetIntention : SelfTargetingRangeIntention<KtDotQualifiedExpre
text = "Replace '${target.name.asString()}' call with indexing operator"
return callExpression.getCalleeExpression()!!.getTextRange()
return callExpression.calleeExpression!!.textRange
}
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor) {
@@ -96,7 +96,7 @@ class ReplaceGetOrSetIntention : SelfTargetingRangeIntention<KtDotQualifiedExpre
assert(allArguments.isNotEmpty())
val expression = KtPsiFactory(element).buildExpression {
appendExpression(element.getReceiverExpression())
appendExpression(element.receiverExpression)
appendFixedText("[")
@@ -26,16 +26,16 @@ import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.util.OperatorNameConventions
public class ReplaceInvokeIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(javaClass(), "Replace 'invoke' with direct call"), HighPriorityAction {
public class ReplaceInvokeIntention : SelfTargetingRangeIntention<KtDotQualifiedExpression>(KtDotQualifiedExpression::class.java, "Replace 'invoke' with direct call"), HighPriorityAction {
override fun applicabilityRange(element: KtDotQualifiedExpression): TextRange? {
if (element.calleeName != OperatorNameConventions.INVOKE.asString()) return null
return element.callExpression!!.getCalleeExpression()!!.getTextRange()
return element.callExpression!!.calleeExpression!!.textRange
}
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor) {
val receiver = element.getReceiverExpression()
val receiver = element.receiverExpression
val callExpression = element.callExpression!!.copy() as KtCallExpression
callExpression.getCalleeExpression()!!.replace(receiver)
callExpression.calleeExpression!!.replace(receiver)
element.replace(callExpression)
}
}
@@ -29,31 +29,31 @@ import org.jetbrains.kotlin.idea.quickfix.moveCaret
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallableDeclaration>(javaClass(), "Convert member to extension"), LowPriorityAction {
public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallableDeclaration>(KtCallableDeclaration::class.java, "Convert member to extension"), LowPriorityAction {
override fun applicabilityRange(element: KtCallableDeclaration): TextRange? {
val classBody = element.getParent() as? KtClassBody ?: return null
if (classBody.getParent() !is KtClass) return null
if (element.getReceiverTypeReference() != null) return null
val classBody = element.parent as? KtClassBody ?: return null
if (classBody.parent !is KtClass) return null
if (element.receiverTypeReference != null) return null
if (element.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return null
when (element) {
is KtProperty -> if (element.hasInitializer()) return null
is KtSecondaryConstructor -> return null
}
return (element.getNameIdentifier() ?: return null).getTextRange()
return (element.nameIdentifier ?: return null).textRange
}
//TODO: local class
override fun applyTo(element: KtCallableDeclaration, editor: Editor) {
val descriptor = element.resolveToDescriptor()
val containingClass = descriptor.getContainingDeclaration() as ClassDescriptor
val containingClass = descriptor.containingDeclaration as ClassDescriptor
val file = element.getContainingKtFile()
val outermostParent = KtPsiUtil.getOutermostParent(element, file, false)
val typeParameterList = newTypeParameterList(element)
val project = element.getProject()
val project = element.project
val psiFactory = KtPsiFactory(element)
val extension = file.addAfter(element, outermostParent) as KtCallableDeclaration
@@ -61,27 +61,27 @@ public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtC
file.addAfter(psiFactory.createNewLine(), outermostParent)
element.delete()
extension.setReceiverType(containingClass.getDefaultType())
extension.setReceiverType(containingClass.defaultType)
if (typeParameterList != null) {
if (extension.getTypeParameterList() != null) {
extension.getTypeParameterList()!!.replace(typeParameterList)
if (extension.typeParameterList != null) {
extension.typeParameterList!!.replace(typeParameterList)
}
else {
extension.addBefore(typeParameterList, extension.getReceiverTypeReference())
extension.addBefore(psiFactory.createWhiteSpace(), extension.getReceiverTypeReference())
extension.addBefore(typeParameterList, extension.receiverTypeReference)
extension.addBefore(psiFactory.createWhiteSpace(), extension.receiverTypeReference)
}
}
extension.getModifierList()?.getModifier(KtTokens.PROTECTED_KEYWORD)?.delete()
extension.getModifierList()?.getModifier(KtTokens.ABSTRACT_KEYWORD)?.delete()
extension.modifierList?.getModifier(KtTokens.PROTECTED_KEYWORD)?.delete()
extension.modifierList?.getModifier(KtTokens.ABSTRACT_KEYWORD)?.delete()
var bodyToSelect: KtExpression? = null
fun selectBody(declaration: KtDeclarationWithBody) {
if (bodyToSelect == null) {
val body = declaration.getBodyExpression()
bodyToSelect = if (body is KtBlockExpression) body.getStatements().single() else body
val body = declaration.bodyExpression
bodyToSelect = if (body is KtBlockExpression) body.statements.single() else body
}
}
@@ -96,12 +96,12 @@ public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtC
is KtProperty -> {
val templateProperty = psiFactory.createDeclaration<KtProperty>("var v: Any\nget()=$THROW_UNSUPPORTED_OPERATION_EXCEPTION\nset(value){$THROW_UNSUPPORTED_OPERATION_EXCEPTION}")
val templateGetter = templateProperty.getGetter()!!
val templateSetter = templateProperty.getSetter()!!
val templateGetter = templateProperty.getter!!
val templateSetter = templateProperty.setter!!
var getter = extension.getGetter()
var getter = extension.getter
if (getter == null) {
getter = extension.addAfter(templateGetter, extension.getTypeReference()) as KtPropertyAccessor
getter = extension.addAfter(templateGetter, extension.typeReference) as KtPropertyAccessor
extension.addBefore(psiFactory.createNewLine(), getter)
selectBody(getter)
}
@@ -110,8 +110,8 @@ public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtC
selectBody(getter)
}
if (extension.isVar()) {
var setter = extension.getSetter()
if (extension.isVar) {
var setter = extension.setter
if (setter == null) {
setter = extension.addAfter(templateSetter, getter) as KtPropertyAccessor
extension.addBefore(psiFactory.createNewLine(), setter)
@@ -125,15 +125,15 @@ public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtC
}
}
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument())
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
if (bodyToSelect != null) {
val range = bodyToSelect!!.getTextRange()
editor.moveCaret(range.getStartOffset(), ScrollType.CENTER)
editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset())
val range = bodyToSelect!!.textRange
editor.moveCaret(range.startOffset, ScrollType.CENTER)
editor.selectionModel.setSelection(range.startOffset, range.endOffset)
}
else {
editor.moveCaret(extension.getTextOffset(), ScrollType.CENTER)
editor.moveCaret(extension.textOffset, ScrollType.CENTER)
}
}
@@ -141,11 +141,11 @@ public class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtC
private val THROW_UNSUPPORTED_OPERATION_EXCEPTION = "throw UnsupportedOperationException()"
private fun newTypeParameterList(member: KtCallableDeclaration): KtTypeParameterList? {
val classElement = member.getParent().getParent() as KtClass
val classParams = classElement.getTypeParameters()
val classElement = member.parent.parent as KtClass
val classParams = classElement.typeParameters
if (classParams.isEmpty()) return null
val allTypeParameters = classParams + member.getTypeParameters()
val text = allTypeParameters.map { it.getText() }.joinToString(",", "<", ">")
return KtPsiFactory(member).createDeclaration<KtFunction>("fun $text foo()").getTypeParameterList()
val allTypeParameters = classParams + member.typeParameters
val text = allTypeParameters.map { it.text }.joinToString(",", "<", ">")
return KtPsiFactory(member).createDeclaration<KtFunction>("fun $text foo()").typeParameterList
}
}
@@ -24,10 +24,10 @@ import org.jetbrains.kotlin.idea.intentions.splitPropertyDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.startOffset
public class SplitPropertyDeclarationIntention : SelfTargetingRangeIntention<KtProperty>(javaClass(), "Split property declaration"), LowPriorityAction {
public class SplitPropertyDeclarationIntention : SelfTargetingRangeIntention<KtProperty>(KtProperty::class.java, "Split property declaration"), LowPriorityAction {
override fun applicabilityRange(element: KtProperty): TextRange? {
if (!element.isLocal()) return null
val initializer = element.getInitializer() ?: return null
if (!element.isLocal) return null
val initializer = element.initializer ?: return null
return TextRange(element.startOffset, initializer.startOffset)
}