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