Quick Fixes: Replace strong references to PSI elements with smart pointers

#KT-14552 Fixed
This commit is contained in:
Alexey Sedunov
2016-11-01 20:09:12 +03:00
parent 8ceeff0211
commit df38c70278
87 changed files with 255 additions and 107 deletions
@@ -135,6 +135,7 @@ abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixAction<K
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val module = ProjectRootManager.getInstance(project).fileIndex.getModuleForFile(element.containingFile.virtualFile)
if (module != null) {
if (KotlinPluginUtil.isMavenModule(module)) {
@@ -190,7 +190,7 @@ class ConflictingExtensionPropertyInspection : AbstractKotlinInspection(), Clean
override fun startInWriteAction() = false
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val declaration = element
val declaration = element ?: return
val fqName = declaration.resolveToDescriptor(BodyResolveMode.PARTIAL).importableFqName
if (fqName != null) {
ProgressManager.getInstance().run(
@@ -231,6 +231,7 @@ class ConflictingExtensionPropertyInspection : AbstractKotlinInspection(), Clean
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val factory = KtPsiFactory(project)
val name = element.nameAsName!!.render()
element.addAnnotationWithLineBreak(factory.createAnnotationEntry("@Deprecated(\"Is replaced with automatic synthetic extension\", ReplaceWith(\"$name\"), level = DeprecationLevel.HIDDEN)"))
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.psi.KtOperationReferenceExpression
class InfixCallFix(expression: KtBinaryExpression) : KotlinQuickFixAction<KtBinaryExpression>(expression), CleanupFix {
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
InfixCallToOrdinaryIntention.convert(element)
InfixCallToOrdinaryIntention.convert(element ?: return)
}
override fun getFamilyName(): String = text
@@ -133,7 +133,7 @@ class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspectionTo
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.delete()
element?.delete()
}
}
}
@@ -80,11 +80,13 @@ interface AddValVarToConstructorParameterAction {
class QuickFix(parameter: KtParameter) :
KotlinQuickFixAction<KtParameter>(parameter),
AddValVarToConstructorParameterAction {
override fun getText() = getActionText(element)
override fun getText() = element?.let { getActionText(it) } ?: ""
override fun getFamilyName() = actionFamily
override fun invoke(project: Project, editor: Editor?, file: KtFile) = invoke(element, editor)
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
invoke(element ?: return, editor)
}
}
object QuickFixFactory : KotlinSingleIntentionActionFactory() {
@@ -41,6 +41,7 @@ class AddArrayOfTypeFix(expression: KtExpression, expectedType: KotlinType) : Ko
override fun getFamilyName() = "Add arrayOf wrapper"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val arrayOfExpression = KtPsiFactory(project).createExpressionByPattern("$0($1)", prefix, element)
element.replace(arrayOfExpression)
}
@@ -30,10 +30,11 @@ class AddInlineModifierFix(
element: KtNameReferenceExpression,
private val modifier: KtModifierKeywordToken
) : KotlinQuickFixAction<KtNameReferenceExpression>(element) {
override fun getText() = "Add '${modifier.value}' to parameter '${element.getReferencedName()}'"
override fun getText() = element?.let { "Add '${modifier.value}' to parameter '${it.getReferencedName()}'" } ?: ""
override fun getFamilyName() = "Add '${modifier.value}' to parameter"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val parameter = element.findParameterWithName(element.getReferencedName()) ?: return
if (!parameter.hasModifier(modifier)) {
parameter.addModifier(modifier)
@@ -30,10 +30,12 @@ class AddFunctionBodyFix(element: KtFunction) : KotlinQuickFixAction<KtFunction>
override fun getText() = familyName
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && !element.hasBody()
}
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
if (!element.hasBody()) {
element.add(KtPsiFactory(project).createEmptyBody())
}
@@ -37,12 +37,17 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.util.*
class AddFunctionParametersFix(
private val callElement: KtCallElement,
callElement: KtCallElement,
functionDescriptor: FunctionDescriptor,
private val hasTypeMismatches: Boolean) : ChangeFunctionSignatureFix(callElement, functionDescriptor) {
private val callElement: KtCallElement?
get() = element as? KtCallElement
private val typesToShorten = ArrayList<KotlinType>()
override fun getText(): String {
val callElement = callElement ?: return ""
val parameters = functionDescriptor.valueParameters
val arguments = callElement.valueArguments
val newParametersCnt = arguments.size - parameters.size
@@ -66,6 +71,7 @@ class AddFunctionParametersFix(
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val callElement = callElement ?: return false
if (!super.isAvailable(project, editor, file)) return false
// newParametersCnt <= 0: psi for this quickfix is no longer valid
@@ -74,6 +80,7 @@ class AddFunctionParametersFix(
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val callElement = callElement ?: return
runChangeSignature(project, functionDescriptor, addParameterConfiguration(), callElement, text)
}
@@ -81,6 +88,7 @@ class AddFunctionParametersFix(
return object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify {
val callElement = callElement ?: return@modify
val parameters = functionDescriptor.valueParameters
val arguments = callElement.valueArguments
val validator = CollectingNameValidator()
@@ -43,16 +43,18 @@ class AddGenericUpperBoundFix(
) : KotlinQuickFixAction<KtTypeParameter>(typeParameter) {
private val renderedUpperBound: String = IdeDescriptorRenderers.SOURCE_CODE.renderType(upperBound)
override fun getText() = "Add '$renderedUpperBound' as upper bound for ${element.name}"
override fun getText() = element?.let { "Add '$renderedUpperBound' as upper bound for ${it.name}" } ?: ""
override fun getFamilyName() = "Add generic upper bound"
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
if (!super.isAvailable(project, editor, file)) return false
// TODO: replacing existing upper bounds
return (element.name != null && element.extendsBound == null)
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
assert(element.extendsBound == null) { "Don't know what to do with existing bounds" }
val typeReference = KtPsiFactory(project).createType(renderedUpperBound)
@@ -34,6 +34,7 @@ class AddLoopLabelFix(loop: KtLoopExpression, val jumpExpression: KtElement): Ko
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val usedLabels = collectUsedLabels(element)
val labelName = getUniqueLabelName(usedLabels)
@@ -41,6 +41,7 @@ open class AddModifierFix(
) : KotlinQuickFixAction<KtModifierListOwner>(element) {
override fun getText(): String {
val element = element ?: return ""
if (modifier in modalityModifiers) {
return "Make ${getElementName(element)} ${modifier.value}"
}
@@ -50,10 +51,11 @@ open class AddModifierFix(
override fun getFamilyName() = "Add modifier"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.addModifier(modifier)
element?.addModifier(modifier)
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.canRefactor()
}
@@ -39,14 +39,15 @@ import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class AddNameToArgumentFix(argument: KtValueArgument) : KotlinQuickFixAction<KtValueArgument>(argument) {
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
if (!super.isAvailable(project, editor, file)) return false
if (element.getArgumentExpression() == null) return false
return calculatePossibleArgumentNames().isNotEmpty()
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val possibleNames = calculatePossibleArgumentNames()
assert(possibleNames.isNotEmpty()) { "isAvailable() should be checked before invoke()" }
if (possibleNames.size == 1 || editor == null || !editor.component.isShowing) {
@@ -67,12 +68,12 @@ class AddNameToArgumentFix(argument: KtValueArgument) : KotlinQuickFixAction<KtV
override fun getFamilyName() = "Add name to argument"
private fun calculatePossibleArgumentNames(): List<Name> {
val callElement = element.getParentOfType<KtCallElement>(true) ?: return emptyList()
val callElement = element!!.getParentOfType<KtCallElement>(true) ?: return emptyList()
val context = element.analyze(BodyResolveMode.PARTIAL)
val context = element!!.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = callElement.getResolvedCall(context) ?: return emptyList()
val argumentType = element.getArgumentExpression()?.let { context.getType(it) }
val argumentType = element!!.getArgumentExpression()?.let { context.getType(it) }
val usedParameters = resolvedCall.call.valueArguments
.map { resolvedCall.getArgumentMapping(it) }
@@ -93,8 +94,8 @@ class AddNameToArgumentFix(argument: KtValueArgument) : KotlinQuickFixAction<KtV
}
private fun createArgumentWithName(name: Name): KtValueArgument {
val argumentExpression = element.getArgumentExpression()!!
val newArgument = KtPsiFactory(element).createArgument(argumentExpression, name, element.getSpreadElement() != null)
val argumentExpression = element!!.getArgumentExpression()!!
val newArgument = KtPsiFactory(element!!).createArgument(argumentExpression, name, element!!.getSpreadElement() != null)
return newArgument
}
@@ -105,7 +106,7 @@ class AddNameToArgumentFix(argument: KtValueArgument) : KotlinQuickFixAction<KtV
private fun getNamePopup(project: Project, names: List<Name>): ListPopupStep<Name> {
return object : BaseListPopupStep<Name>("Choose parameter name", names) {
override fun onChosen(selectedValue: Name, finalChoice: Boolean): PopupStep<*>? {
addName(project, element, selectedValue)
addName(project, element!!, selectedValue)
return PopupStep.FINAL_CHOICE
}
@@ -29,6 +29,7 @@ class AddNewLineAfterAnnotationsFix(element: KtAnnotatedExpression) : KotlinQuic
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val baseExpression = element.baseExpression ?: return
val annotationsText = element.text.substring(0, baseExpression.startOffsetInParent)
val newExpression = KtPsiFactory(project).createBlock(annotationsText + "\n" + baseExpression.text).statements[0]
@@ -50,7 +50,7 @@ class AddReifiedToTypeParameterOfFunctionFix(
val inlineFix = AddInlineToFunctionWithReifiedFix(function)
override fun getText() = "Make ${getElementName(element)} reified and ${getElementName(function)} inline"
override fun getText() = element?.let { "Make ${getElementName(it)} reified and ${getElementName(function)} inline" } ?: ""
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
super.invoke(project, editor, file)
@@ -30,6 +30,7 @@ class AddRunToLambdaFix(element: KtLambdaExpression) : KotlinQuickFixAction<KtLa
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val factory = KtPsiFactory(project)
element.replace(factory.createExpression("run ${element.text}"))
}
@@ -31,6 +31,7 @@ open class AddStarProjectionsFix private constructor(element: KtUserType,
override fun getText() = "Add '${TypeReconstructionUtil.getTypeNameAndStarProjectionsString("", argumentCount)}'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
assert(element.typeArguments.isEmpty())
val typeString = TypeReconstructionUtil.getTypeNameAndStarProjectionsString(element.text, argumentCount)
@@ -31,6 +31,7 @@ class AddToStringFix(element: KtExpression, private val nullable: Boolean) : Kot
override fun getText() = if (nullable) "Add safe '?.toString()' call" else "Add 'toString()' call"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val pattern = if (nullable) "$0?.toString()" else "$0.toString()"
val expressionToInsert = KtPsiFactory(file).createExpressionByPattern(pattern, element)
val newExpression = element.replaced(expressionToInsert)
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getType
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class AddTypeAnnotationToValueParameterFix(element: KtParameter) : KotlinQuickFixAction<KtParameter>(element) {
val typeNameShort : String?
val typeName: String?
@@ -44,13 +43,15 @@ class AddTypeAnnotationToValueParameterFix(element: KtParameter) : KotlinQuickFi
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return element.typeReference == null && typeNameShort != null
}
override fun getFamilyName() = "Add type annotation"
override fun getText() = "Add type '$typeNameShort' to parameter '${element.name}'"
override fun getText() = element?.let { "Add type '$typeNameShort' to parameter '${it.name}'" } ?: ""
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
if (typeName != null) {
element.typeReference = KtPsiFactory(element).createType(typeName)
ShortenReferences.DEFAULT.process(element)
@@ -36,6 +36,7 @@ class AddTypeToLHSOfCallableReferenceFix(
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val resolvedCall = element.callableReference.getResolvedCall(element.analyze(BodyResolveMode.PARTIAL)) ?: return
val receiver = with(resolvedCall) {
dispatchReceiver ?: extensionReceiver ?: return
@@ -30,10 +30,12 @@ class AddWhenElseBranchFix(element: KtWhenExpression) : KotlinQuickFixAction<KtW
override fun getText() = familyName
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.closeBrace != null
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val psiFactory = KtPsiFactory(file)
val entry = psiFactory.createWhenEntry("else -> {}")
val whenCloseBrace = element.closeBrace ?: error("isAvailable should check if close brace exist")
@@ -35,13 +35,14 @@ class AddWhenRemainingBranchesFix(expression: KtWhenExpression) : KotlinQuickFix
override fun getText() = "Add remaining branches"
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean =
super.isAvailable(project, editor, file) && element.closeBrace != null &&
with(WhenChecker.getMissingCases(element, element.analyze())) {
isNotEmpty() && !hasUnknown
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.closeBrace != null &&
with(WhenChecker.getMissingCases(element, element.analyze())) { isNotEmpty() && !hasUnknown }
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val missingCases = WhenChecker.getMissingCases(element, element.analyze())
val whenCloseBrace = element.closeBrace ?: throw AssertionError("isAvailable should check if close brace exist")
@@ -42,12 +42,13 @@ class CastExpressionFix(element: KtExpression, type: KotlinType) : KotlinQuickFi
}
override fun getFamilyName() = "Cast expression"
override fun getText() = "Cast expression '${element.text}' to '$typePresentation'"
override fun getText() = element?.let { "Cast expression '${it.text}' to '$typePresentation'" } ?: ""
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile)
= upOrDownCast && super.isAvailable(project, editor, file)
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val expressionToInsert = KtPsiFactory(file).createExpressionByPattern("$0 as $1", element, typeSourceCode)
val newExpression = element.replaced(expressionToInsert)
ShortenReferences.DEFAULT.process((KtPsiUtil.safeDeparenthesize(newExpression) as KtBinaryExpressionWithTypeRHS).right!!)
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.types.KotlinType
class ChangeAccessorTypeFix(element: KtPropertyAccessor) : KotlinQuickFixAction<KtPropertyAccessor>(element) {
private fun getType(): KotlinType? {
val type = (element.property.resolveToDescriptor() as VariableDescriptor).type
val type = (element!!.property.resolveToDescriptor() as VariableDescriptor).type
if (type.isError) return null
return type
}
@@ -43,6 +43,7 @@ class ChangeAccessorTypeFix(element: KtPropertyAccessor) : KotlinQuickFixAction<
override fun getFamilyName() = "Change accessor type"
override fun getText(): String {
val element = element ?: return ""
val type = getType() ?: return familyName
val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
val target = if (element.isGetter) "getter" else "setter parameter"
@@ -50,6 +51,7 @@ class ChangeAccessorTypeFix(element: KtPropertyAccessor) : KotlinQuickFixAction<
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val type = getType()!!
val newTypeReference = KtPsiFactory(file).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type))
@@ -44,7 +44,8 @@ class ChangeFunctionLiteralReturnTypeFix(
private val typePresentation = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
private val typeSourceCode = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
private val functionLiteralReturnTypeRef = functionLiteralExpression.functionLiteral.typeReference
private val functionLiteralReturnTypeRef: KtTypeReference?
get() = element?.functionLiteral?.typeReference
private val appropriateQuickFix = createAppropriateQuickFix(functionLiteralExpression, type)
private fun createAppropriateQuickFix(functionLiteralExpression: KtLambdaExpression, type: KotlinType): IntentionAction? {
@@ -113,8 +114,8 @@ class ChangeFunctionLiteralReturnTypeFix(
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
if (functionLiteralReturnTypeRef != null) {
val newTypeRef = functionLiteralReturnTypeRef.replace(KtPsiFactory(file).createType(typeSourceCode)) as KtTypeReference
functionLiteralReturnTypeRef?.let {
val newTypeRef = it.replace(KtPsiFactory(file).createType(typeSourceCode)) as KtTypeReference
ShortenReferences.DEFAULT.process(newTypeRef)
}
if (appropriateQuickFix != null && appropriateQuickFix.isAvailable(project, editor!!, file)) {
@@ -40,6 +40,7 @@ class ChangeFunctionLiteralSignatureFix private constructor(
override fun getText() = "Change the signature of lambda expression"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
runChangeSignature(
project,
functionDescriptor,
@@ -58,7 +59,7 @@ class ChangeFunctionLiteralSignatureFix private constructor(
override fun performSilently(affectedFunctions: Collection<PsiElement>) = false
override fun forcePerformForSelectedFunctionOnly() = false
},
context,
element,
text)
}
@@ -68,6 +68,7 @@ abstract class ChangeFunctionReturnTypeFix(element: KtFunction, type: KotlinType
}
open fun functionPresentation(): String? {
val element = element!!
val name = element.name
if (name != null) {
val container = element.resolveToDescriptor().containingDeclaration as? ClassDescriptor
@@ -105,6 +106,8 @@ abstract class ChangeFunctionReturnTypeFix(element: KtFunction, type: KotlinType
}
override fun getText(): String {
val element = element ?: return ""
if (changeFunctionLiteralReturnTypeFix != null) {
return changeFunctionLiteralReturnTypeFix.text
}
@@ -133,6 +136,8 @@ abstract class ChangeFunctionReturnTypeFix(element: KtFunction, type: KotlinType
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
if (changeFunctionLiteralReturnTypeFix != null) {
changeFunctionLiteralReturnTypeFix.invoke(project, editor!!, file)
}
@@ -45,10 +45,9 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
abstract class ChangeFunctionSignatureFix(
protected val context: PsiElement,
element: PsiElement,
protected val functionDescriptor: FunctionDescriptor
) : KotlinQuickFixAction<PsiElement>(context) {
) : KotlinQuickFixAction<PsiElement>(element) {
override fun getFamilyName() = FAMILY_NAME
override fun startInWriteAction() = false
@@ -116,15 +115,15 @@ abstract class ChangeFunctionSignatureFix(
}
private class RemoveParameterFix(
context: PsiElement,
element: PsiElement,
functionDescriptor: FunctionDescriptor,
private val parameterToRemove: ValueParameterDescriptor
) : ChangeFunctionSignatureFix(context, functionDescriptor) {
) : ChangeFunctionSignatureFix(element, functionDescriptor) {
override fun getText() = "Remove parameter '${parameterToRemove.name.asString()}'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
runRemoveParameter(parameterToRemove, context)
runRemoveParameter(parameterToRemove, element ?: return)
}
}
@@ -235,6 +235,7 @@ class ChangeMemberFunctionSignatureFix private constructor(
override fun getFamilyName() = "Change function signature"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
CommandProcessor.getInstance().runUndoTransparentAction {
MyAction(project, editor, element, signatures).execute()
}
@@ -54,6 +54,7 @@ class ChangeParameterTypeFix(element: KtParameter, type: KotlinType) : KotlinQui
}
override fun getText(): String {
val element = element ?: return ""
return if (isPrimaryConstructorParameter)
"Change parameter '${element.name}' type of primary constructor of class '$containingDeclarationName' to '$typePresentation'"
else
@@ -63,6 +64,7 @@ class ChangeParameterTypeFix(element: KtParameter, type: KotlinType) : KotlinQui
override fun getFamilyName() = KotlinBundle.message("change.type.family")
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val function = element.getStrictParentOfType<KtFunction>() ?: return
val parameterIndex = function.valueParameters.indexOf(element)
val context = function.analyze()
@@ -30,6 +30,7 @@ class ChangeToFunctionInvocationFix(element: KtExpression) : KotlinQuickFixActio
override fun getText() = familyName
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.replace(KtPsiFactory(file).createExpressionByPattern("$0()", element))
}
@@ -29,6 +29,7 @@ class ChangeToPropertyAccessFix(element: KtCallExpression) : KotlinQuickFixActio
override fun getText() = familyName
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.replace(element.calleeExpression as KtExpression)
}
@@ -26,9 +26,10 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
class ChangeToStarProjectionFix(element: KtTypeElement) : KotlinQuickFixAction<KtTypeElement>(element) {
override fun getFamilyName() = "Change to star projection"
override fun getText() = "Change type arguments to <${element.typeArgumentsAsTypes.joinToString { "*" }}>"
override fun getText() = element?.let { "Change type arguments to <${it.typeArgumentsAsTypes.joinToString { "*" }}>" } ?: ""
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val star = KtPsiFactory(file).createStar()
element.typeArgumentsAsTypes.forEach { it?.replace(star) }
}
@@ -33,11 +33,12 @@ class ChangeTypeFix(element: KtTypeReference, private val type: KotlinType) : Ko
override fun getFamilyName() = "Change type"
override fun getText(): String {
val currentTypeText = element.text
val currentTypeText = element?.text ?: return ""
return "Change type from '$currentTypeText' to '${QuickFixUtil.renderTypeWithFqNameOnClash(type, currentTypeText)}'"
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val newTypeRef = element.replaced(KtPsiFactory(file).createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)))
ShortenReferences.DEFAULT.process(newTypeRef)
}
@@ -36,11 +36,13 @@ class ChangeVariableMutabilityFix(element: KtValVarKeywordOwner, private val mak
override fun getFamilyName(): String = text
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
val valOrVar = element.valOrVarKeyword?.node?.elementType ?: return false
return (valOrVar == KtTokens.VAR_KEYWORD) != makeVar
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val factory = KtPsiFactory(project)
val newKeyword = if (makeVar) factory.createVarKeyword() else factory.createValKeyword()
element.valOrVarKeyword!!.replace(newKeyword)
@@ -45,6 +45,7 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
private val typeSourceCode = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
open fun variablePresentation(): String? {
val element = element!!
val name = element.name
if (name != null) {
val container = element.resolveToDescriptor().containingDeclaration as? ClassDescriptor
@@ -57,6 +58,8 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
}
override fun getText(): String {
if (element == null) return ""
val variablePresentation = variablePresentation()
if (variablePresentation != null) {
return "Change type of $variablePresentation to '$typePresentation'"
@@ -84,6 +87,7 @@ open class ChangeVariableTypeFix(element: KtVariableDeclaration, type: KotlinTyp
= !typeContainsError && super.isAvailable(project, editor, file)
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val psiFactory = KtPsiFactory(file)
assert(element.nameIdentifier != null) { "ChangeVariableTypeFix applied to variable without name" }
@@ -43,7 +43,7 @@ open class ChangeVisibilityFix(
override fun getFamilyName() = "Make $visibilityModifier"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.setVisibility(visibilityModifier)
element?.setVisibility(visibilityModifier)
}
protected class ChangeToPublicFix(element: KtModifierListOwner, elementName: String) :
@@ -52,8 +52,10 @@ open class ChangeVisibilityFix(
protected class ChangeToProtectedFix(element: KtModifierListOwner, elementName: String) :
ChangeVisibilityFix(element, elementName, KtTokens.PROTECTED_KEYWORD) {
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile) =
super.isAvailable(project, editor, file) && element.canBeProtected()
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.canBeProtected()
}
}
protected class ChangeToInternalFix(element: KtModifierListOwner, elementName: String) :
@@ -62,8 +64,10 @@ open class ChangeVisibilityFix(
protected class ChangeToPrivateFix(element: KtModifierListOwner, elementName: String) :
ChangeVisibilityFix(element, elementName, KtTokens.PRIVATE_KEYWORD), HighPriorityAction {
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile) =
super.isAvailable(project, editor, file) && element.canBePrivate()
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.canBePrivate()
}
}
companion object {
@@ -29,6 +29,7 @@ class ChangeVisibilityModifierFix(element: KtDeclaration) : KotlinQuickFixAction
override fun getText() = familyName
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.removeModifier(element.visibilityModifierType()!!)
}
@@ -56,13 +56,14 @@ class ConvertClassToKClassFix(element: KtDotQualifiedExpression, type: KotlinTyp
return@run firstChildType.isSubtypeOf(type)
}
override fun getText() = "Remove '.${element.children.lastOrNull()?.text}'"
override fun getText() = element?.let { "Remove '.${it.children.lastOrNull()?.text}'" } ?: ""
override fun getFamilyName() = "Remove conversion from 'KClass' to 'Class'"
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile)
= isApplicable && super.isAvailable(project, editor, file)
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.replace(element.firstChild)
}
@@ -32,6 +32,7 @@ class ConvertExtensionPropertyInitializerToGetterFix(element: KtExpression) : Ko
override fun getFamilyName(): String = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val property = element.getParentOfType<KtProperty>(true) ?: return
ConvertPropertyInitializerToGetterIntention.convertPropertyInitializerToGetter(property, editor)
}
@@ -44,6 +44,7 @@ class ConvertExtensionToFunctionTypeFix(element: KtTypeReference, type: KotlinTy
override fun getFamilyName() = "Convert extension function type to regular function type"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val replaced = element.replaced(KtPsiFactory(project).createType(targetTypeStringLong))
ShortenReferences.DEFAULT.process(replaced)
}
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.isValidOperator
abstract class ExclExclCallFix : IntentionAction {
abstract class ExclExclCallFix(psiElement: PsiElement) : KotlinQuickFixAction<PsiElement>(psiElement) {
override fun getFamilyName(): String = text
override fun startInWriteAction(): Boolean = true
@@ -47,13 +47,13 @@ abstract class ExclExclCallFix : IntentionAction {
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile) = file is KtFile
}
class RemoveExclExclCallFix(val psiElement: PsiElement) : ExclExclCallFix(), CleanupFix {
class RemoveExclExclCallFix(psiElement: PsiElement) : ExclExclCallFix(psiElement), CleanupFix {
override fun getText(): String = KotlinBundle.message("remove.unnecessary.non.null.assertion")
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean
= super.isAvailable(project, editor, file) && getExclExclPostfixExpression() != null
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return
val postfixExpression = getExclExclPostfixExpression() ?: return
@@ -62,7 +62,7 @@ class RemoveExclExclCallFix(val psiElement: PsiElement) : ExclExclCallFix(), Cle
}
private fun getExclExclPostfixExpression(): KtPostfixExpression? {
val operationParent = psiElement.parent
val operationParent = element?.parent
if (operationParent is KtPostfixExpression && operationParent.baseExpression != null) {
return operationParent
}
@@ -75,14 +75,14 @@ class RemoveExclExclCallFix(val psiElement: PsiElement) : ExclExclCallFix(), Cle
}
}
class AddExclExclCallFix(val psiElement: PsiElement) : ExclExclCallFix() {
class AddExclExclCallFix(psiElement: PsiElement) : ExclExclCallFix(psiElement) {
override fun getText() = KotlinBundle.message("introduce.non.null.assertion")
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean
= super.isAvailable(project, editor, file) &&
getExpressionForIntroduceCall() != null
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return
val modifiedExpression = getExpressionForIntroduceCall() ?: return
@@ -91,6 +91,7 @@ class AddExclExclCallFix(val psiElement: PsiElement) : ExclExclCallFix() {
}
private fun getExpressionForIntroduceCall(): KtExpression? {
val psiElement = element ?: return null
if (psiElement is LeafPsiElement && psiElement.elementType == KtTokens.DOT) {
val sibling = psiElement.prevSibling
if (sibling is KtExpression) {
@@ -86,27 +86,30 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
expression: T,
private val factory: Factory
) : KotlinQuickFixAction<T>(expression), HighPriorityAction, HintAction {
private val project = expression.project
private val modificationCountOnCreate = PsiModificationTracker.SERVICE.getInstance(element.project).modificationCount
private val modificationCountOnCreate = PsiModificationTracker.SERVICE.getInstance(project).modificationCount
private val suggestionCount: Int by CachedValueProperty(
calculator = { computeSuggestions().size },
timestampCalculator = { PsiModificationTracker.SERVICE.getInstance(element.project).modificationCount }
timestampCalculator = { PsiModificationTracker.SERVICE.getInstance(project).modificationCount }
)
protected open fun getSupportedErrors() = factory.supportedErrors
protected abstract val importNames: Collection<Name>
protected abstract fun getCallTypeAndReceiver(): CallTypeAndReceiver<*, *>
protected abstract fun getCallTypeAndReceiver(): CallTypeAndReceiver<*, *>?
override fun showHint(editor: Editor): Boolean {
val element = element ?: return false
if (!element.isValid || isOutdated()) return false
if (ApplicationManager.getApplication().isUnitTestMode && HintManager.getInstance().hasShownHintsThatWillHideByOtherHint(true)) return false
if (suggestionCount == 0) return false
return createAction(element.project, editor).showHint()
return createAction(project, editor, element).showHint()
}
override fun getText() = KotlinBundle.message("import.fix")
@@ -114,27 +117,29 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
override fun getFamilyName() = KotlinBundle.message("import.fix")
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile)
= super.isAvailable(project, editor, file) && suggestionCount > 0
= element != null && super.isAvailable(project, editor, file) && suggestionCount > 0
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
CommandProcessor.getInstance().runUndoTransparentAction {
createAction(project, editor!!).execute()
createAction(project, editor!!, element).execute()
}
}
override fun startInWriteAction() = true
private fun isOutdated() = modificationCountOnCreate != PsiModificationTracker.SERVICE.getInstance(element.project).modificationCount
private fun isOutdated() = modificationCountOnCreate != PsiModificationTracker.SERVICE.getInstance(project).modificationCount
protected open fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
protected open fun createAction(project: Project, editor: Editor, element: KtExpression): KotlinAddImportAction {
return createSingleImportAction(project, editor, element, computeSuggestions())
}
fun computeSuggestions(): Collection<DeclarationDescriptor> {
if (!element.isValid) return listOf()
val element = element ?: return emptyList()
if (!element.isValid) return emptyList()
if (element.containingFile !is KtFile) return emptyList()
val callTypeAndReceiver = getCallTypeAndReceiver()
val callTypeAndReceiver = getCallTypeAndReceiver() ?: return emptyList()
if (callTypeAndReceiver is CallTypeAndReceiver.UNKNOWN) return emptyList()
@@ -146,6 +151,7 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
}
private fun computeSuggestionsForName(name: Name, callTypeAndReceiver: CallTypeAndReceiver<*, *>): Collection<DeclarationDescriptor> {
val element = element ?: return emptyList()
val nameStr = name.asString()
if (nameStr.isEmpty()) return emptyList()
@@ -192,7 +198,7 @@ internal abstract class ImportFixBase<T : KtExpression> protected constructor(
.any { diagnostic -> diagnostic.factory in getSupportedErrors() }
}
protected open fun elementsToCheckDiagnostics(): Collection<PsiElement> = listOf(element)
protected open fun elementsToCheckDiagnostics(): Collection<PsiElement> = element.singletonOrEmptyList()
abstract fun fillCandidates(
name: String,
@@ -225,9 +231,9 @@ internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T, f
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val result = ArrayList<DeclarationDescriptor>()
val expression = element ?: return emptyList()
val expression = element
val result = ArrayList<DeclarationDescriptor>()
if (expression is KtSimpleNameExpression) {
if (!expression.isImportDirectiveExpression() && !isSelectorInQualified(expression)) {
@@ -252,9 +258,9 @@ internal abstract class OrdinaryImportFixBase<T : KtExpression>(expression: T, f
}
internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.detect(element)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) }
override val importNames = element.mainReference.resolvesByNames
override val importNames = element?.mainReference?.resolvesByNames ?: emptyList()
companion object MyFactory : Factory() {
override fun createAction(diagnostic: Diagnostic) =
@@ -265,7 +271,7 @@ internal class ImportFix(expression: KtSimpleNameExpression) : OrdinaryImportFix
internal class InvokeImportFix(expression: KtExpression) : OrdinaryImportFixBase<KtExpression>(expression, MyFactory) {
override val importNames = OperatorNameConventions.INVOKE.singletonList()
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.OPERATOR(element)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.OPERATOR(it) }
companion object MyFactory : Factory() {
override fun createAction(diagnostic: Diagnostic) =
@@ -279,8 +285,7 @@ internal open class ArrayAccessorImportFix(
private val showHint: Boolean
) : OrdinaryImportFixBase<KtArrayAccessExpression>(element, MyFactory) {
override fun getCallTypeAndReceiver() =
CallTypeAndReceiver.OPERATOR(element.arrayExpression!!)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.OPERATOR(it.arrayExpression!!) }
override fun showHint(editor: Editor) = showHint && super.showHint(editor)
@@ -315,12 +320,12 @@ internal class DelegateAccessorsImportFix(
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.DELEGATE(element)
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
override fun createAction(project: Project, editor: Editor, element: KtExpression): KotlinAddImportAction {
if (solveSeveralProblems) {
return createGroupedImportsAction(project, editor, element, "Delegate accessors", computeSuggestions())
}
return super.createAction(project, editor)
return super.createAction(project, editor, element)
}
companion object MyFactory : Factory() {
@@ -354,14 +359,14 @@ internal class ComponentsImportFix(
private val solveSeveralProblems: Boolean
) : OrdinaryImportFixBase<KtExpression>(element, MyFactory) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.OPERATOR(element)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.OPERATOR(it) }
override fun createAction(project: Project, editor: Editor): KotlinAddImportAction {
override fun createAction(project: Project, editor: Editor, element: KtExpression): KotlinAddImportAction {
if (solveSeveralProblems) {
return createGroupedImportsAction(project, editor, element, "Component functions", computeSuggestions())
}
return super.createAction(project, editor)
return super.createAction(project, editor, element)
}
companion object MyFactory : Factory() {
@@ -393,6 +398,8 @@ internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBa
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val element = element ?: return emptyList()
val result = ArrayList<DeclarationDescriptor>()
if (!element.isImportDirectiveExpression() && !isSelectorInQualified(element)) {
val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) }
@@ -420,9 +427,11 @@ internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBa
return result
}
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.detect(element)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) }
override val importNames: Collection<Name> = run {
val element = element ?: return@run emptyList()
if (element.getIdentifier() != null) {
val name = element.getReferencedName()
if (Name.isValidIdentifier(name)) {
@@ -440,11 +449,12 @@ internal class ImportMemberFix(expression: KtSimpleNameExpression) : ImportFixBa
internal class ImportForMismatchingArgumentsFix(
expression: KtSimpleNameExpression
) : ImportFixBase<KtSimpleNameExpression>(expression, MyFactory) {
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.detect(element)
override fun getCallTypeAndReceiver() = element?.let { CallTypeAndReceiver.detect(it) }
override val importNames = element.mainReference.resolvesByNames
override val importNames = element?.mainReference?.resolvesByNames ?: emptyList()
override fun elementsToCheckDiagnostics(): Collection<PsiElement> {
val element = element ?: return emptyList()
val callExpression = element.parent as? KtCallExpression ?: return emptyList()
return callExpression.valueArguments +
callExpression.valueArguments.mapNotNull { it.getArgumentExpression() } +
@@ -458,6 +468,8 @@ internal class ImportForMismatchingArgumentsFix(
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val element = element ?: return emptyList()
if (!Name.isValidIdentifier(name)) return emptyList()
val identifier = Name.identifier(name)
@@ -55,6 +55,7 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val descriptor = element.resolveToDescriptorIfAny() as? PropertyDescriptor ?: return
val initializerText = CodeInsightUtils.defaultInitializer(descriptor.type) ?: "null"
val initializer = element.setInitializer(KtPsiFactory(project).createExpression(initializerText))!!
@@ -72,7 +73,7 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
override fun startInWriteAction(): Boolean = false
private fun configureChangeSignature(propertyDescriptor: PropertyDescriptor): KotlinChangeSignatureConfiguration {
private fun configureChangeSignature(property: KtProperty, propertyDescriptor: PropertyDescriptor): KotlinChangeSignatureConfiguration {
return object : KotlinChangeSignatureConfiguration {
override fun configure(originalDescriptor: KotlinMethodDescriptor): KotlinMethodDescriptor {
return originalDescriptor.modify {
@@ -81,9 +82,9 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
callableDescriptor = originalDescriptor.baseDescriptor,
name = propertyDescriptor.name.asString(),
originalTypeInfo = KotlinTypeInfo(false, propertyDescriptor.type),
valOrVar = element.valOrVarKeyword.toValVar(),
modifierList = element.modifierList,
defaultValueForCall = KtPsiFactory(element.project).createExpression(initializerText)
valOrVar = property.valOrVarKeyword.toValVar(),
modifierList = property.modifierList,
defaultValueForCall = KtPsiFactory(property.project).createExpression(initializerText)
)
it.addParameter(newParam)
}
@@ -94,6 +95,7 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val klass = element.containingClassOrObject ?: return
val propertyDescriptor = element.resolveToDescriptorIfAny() as? PropertyDescriptor ?: return
@@ -108,7 +110,7 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
val constructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor ?: return
val contextElement = constructorDescriptor.source.getPsi() ?: return
val constructorPointer = contextElement.createSmartPointer()
val config = configureChangeSignature(propertyDescriptor)
val config = configureChangeSignature(element, propertyDescriptor)
val changeSignature = { runChangeSignature(project, constructorDescriptor, config, contextElement, text) }
changeSignature.runRefactoringWithPostprocessing(project, "refactoring.changeSignature") {
val constructorOrClass = constructorPointer.element
@@ -142,7 +144,7 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
callableDescriptor = originalDescriptor.baseDescriptor,
name = KotlinNameSuggester.suggestNameByName(propertyDescriptor.name.asString(), validator),
originalTypeInfo = KotlinTypeInfo(false, propertyDescriptor.type),
defaultValueForCall = KtPsiFactory(element.project).createExpression(initializerText)
defaultValueForCall = KtPsiFactory(element!!.project).createExpression(initializerText)
)
it.addParameter(newParam)
}
@@ -159,6 +161,8 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
descriptorsToProcess: Iterator<ConstructorDescriptor>,
visitedElements: MutableSet<PsiElement> = HashSet()
) {
val element = element!!
if (!descriptorsToProcess.hasNext()) return
val descriptor = descriptorsToProcess.next()
val constructorPointer = descriptor.source.getPsi()?.createSmartPointer()
@@ -180,6 +184,7 @@ object InitializePropertyQuickFixFactory : KotlinIntentionActionsFactory() {
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val propertyDescriptor = element.resolveToDescriptorIfAny() as? PropertyDescriptor ?: return
val classDescriptor = propertyDescriptor.containingDeclaration as? ClassDescriptorWithResolutionScopes ?: return
val klass = element.containingClassOrObject ?: return
@@ -44,6 +44,7 @@ class InsertDelegationCallQuickfix(val isThis: Boolean, element: KtSecondaryCons
private val keywordToUse = if (isThis) "this" else "super"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val newDelegationCall = element.replaceImplicitDelegationCallWithExplicit(isThis)
val resolvedCall = newDelegationCall.getResolvedCall(newDelegationCall.analyze())
@@ -58,6 +59,7 @@ class InsertDelegationCallQuickfix(val isThis: Boolean, element: KtSecondaryCons
}
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.hasImplicitDelegationCall()
}
@@ -24,10 +24,16 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
abstract class KotlinQuickFixAction<out T : PsiElement>(protected val element: T) : IntentionAction {
abstract class KotlinQuickFixAction<out T : PsiElement>(element: T) : IntentionAction {
private val elementPointer = element.createSmartPointer()
protected val element: T?
get() = elementPointer.element
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return element.isValid &&
!element.project.isDisposed &&
(file.manager.isInProject(file) || file is KtCodeFragment) &&
@@ -35,6 +41,7 @@ abstract class KotlinQuickFixAction<out T : PsiElement>(protected val element: T
}
override final fun invoke(project: Project, editor: Editor?, file: PsiFile) {
val element = element ?: return
if (file is KtFile && FileModificationService.getInstance().prepareFileForWrite(element.containingFile)) {
invoke(project, editor, file)
}
@@ -72,6 +72,7 @@ class LetImplementInterfaceFix(
super.isAvailable(project, editor, file) && validExpectedType
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val superTypeEntry = KtPsiFactory(element).createSuperTypeEntry(expectedTypeNameSourceCode)
val entryElement = element.addSuperTypeListEntry(superTypeEntry)
ShortenReferences.DEFAULT.process(entryElement)
@@ -29,6 +29,7 @@ class LiftAssignmentOutOfTryFix(element: KtTryExpression): KotlinQuickFixAction<
override fun getText() = "Lift assignment out of 'try' expression"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val tryAssignment = BranchedFoldingUtils.getFoldableBranchedAssignment(element.tryBlock) ?: return
val op = tryAssignment.operationReference.text
@@ -35,9 +35,10 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class MakeClassAnAnnotationClassFix(annotationClass: KtClass) : KotlinQuickFixAction<KtClass>(annotationClass) {
override fun getFamilyName() = "Make class an annotation class"
override fun getText() = "Make '${element.name}' an annotation class"
override fun getText() = element?.let { "Make '${it.name}' an annotation class" } ?: ""
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.addModifier(KtTokens.ANNOTATION_KEYWORD)
}
@@ -41,10 +41,12 @@ class MakeConstructorParameterPropertyFix(
"Make constructor parameter a property$suffix"
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && !element.hasValOrVar()
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.addBefore(kotlinValVar.createKeyword(KtPsiFactory(project))!!, element.firstChild)
element.addModifier(KtTokens.PRIVATE_KEYWORD)
element.visibilityModifier()?.let { private ->
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.psi.SmartPsiElementPointer
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*
import org.jetbrains.kotlin.descriptors.isOverridable
@@ -30,15 +31,18 @@ import org.jetbrains.kotlin.lexer.KtTokens.OPEN_KEYWORD
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import java.util.*
class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAction<KtDeclaration>(declaration) {
private val overriddenNonOverridableMembers = ArrayList<KtCallableDeclaration>()
private val overriddenNonOverridableMembers = ArrayList<SmartPsiElementPointer<KtCallableDeclaration>>()
private val containingDeclarationsNames = ArrayList<String>()
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
if (!super.isAvailable(project, editor, file) || file !is KtFile) {
return false
}
@@ -58,13 +62,15 @@ class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAc
return false
}
val containingDeclarationName = overriddenDescriptor.containingDeclaration.name.asString()
overriddenNonOverridableMembers.add(overriddenMember)
overriddenNonOverridableMembers.add(overriddenMember.createSmartPointer())
containingDeclarationsNames.add(containingDeclarationName)
}
return overriddenNonOverridableMembers.size > 0
}
override fun getText(): String {
val element = element ?: return ""
if (overriddenNonOverridableMembers.size == 1) {
val name = containingDeclarationsNames[0] + "." + element.name
return "Make $name $OPEN_KEYWORD"
@@ -80,7 +86,7 @@ class MakeOverriddenMemberOpenFix(declaration: KtDeclaration) : KotlinQuickFixAc
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
for (overriddenMember in overriddenNonOverridableMembers) {
overriddenMember.addModifier(OPEN_KEYWORD)
overriddenMember.element?.addModifier(OPEN_KEYWORD)
}
}
@@ -31,7 +31,7 @@ class MissingConstructorKeywordFix(element: KtPrimaryConstructor) : KotlinQuickF
override fun getText(): String = "Add 'constructor' keyword"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.addConstructorKeyword()
element?.addConstructorKeyword()
}
companion object : KotlinSingleIntentionActionFactory() {
@@ -29,6 +29,7 @@ class MoveTypeParameterConstraintFix(element: KtTypeParameter) : KotlinQuickFixA
override fun getFamilyName(): String = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val typeParameterName = element.nameAsName ?: return
val psiFactory = KtPsiFactory(file)
val templateClass = psiFactory.buildDeclaration {
@@ -33,10 +33,12 @@ class MoveWhenElseBranchFix(element: KtWhenExpression) : KotlinQuickFixAction<Kt
override fun getText() = familyName
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && KtPsiUtil.checkWhenExpressionHasSingleElse(element)
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val entries = element.entries
val lastEntry = entries.lastOrNull() ?: return
val elseEntry = entries.singleOrNull { it.isElse } ?: return
@@ -52,6 +52,7 @@ class NumberConversionFix(
override fun getText() = "Convert expression to '$typePresentation'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val expressionToInsert = KtPsiFactory(file).createExpressionByPattern("$0.to$1()", element, typePresentation)
val newExpression = element.replaced(expressionToInsert)
editor?.caretModel?.moveToOffset(newExpression.endOffset)
@@ -32,10 +32,12 @@ class RemoveFunctionBodyFix(element: KtFunction) : KotlinQuickFixAction<KtFuncti
override fun getText() = familyName
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.hasBody()
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val bodyExpression = element.bodyExpression!!
val equalsToken = element.equalsToken
if (equalsToken != null) {
@@ -53,13 +53,14 @@ class RemoveModifierFix(
override fun getText() = text
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile)
= super.isAvailable(project, editor, file) && element.hasModifier(modifier)
= super.isAvailable(project, editor, file) && (element?.hasModifier(modifier) ?: false)
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
invoke()
}
fun invoke() {
val element = element ?: return
//TODO: without this copy&replace we get bad formatting on removing last modifier
val newElement = element.copy() as KtModifierListOwner
newElement.removeModifier(modifier)
@@ -29,7 +29,9 @@ class RemoveNameFromFunctionExpressionFix(element: KtNamedFunction) : KotlinQuic
override fun getText(): String = "Remove identifier from anonymous function"
override fun getFamilyName(): String = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) = removeNameFromFunction(element)
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
removeNameFromFunction(element ?: return)
}
companion object : KotlinSingleIntentionActionFactory() {
@@ -40,6 +40,7 @@ class RemoveNullableFix(element: KtNullableType,
override fun getText() = typeOfError.message
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val type = element.innerType ?: error("No inner type " + element.text + ", should have been rejected in createFactory()")
element.replace(type)
}
@@ -33,7 +33,7 @@ open class RemovePsiElementSimpleFix(element: PsiElement, private val text: Stri
override fun getText() = text
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.delete()
element?.delete()
}
object RemoveImportFactory : KotlinSingleIntentionActionFactory() {
@@ -31,6 +31,7 @@ class RemoveSingleLambdaParameterFix(element: KtParameter) : KotlinQuickFixActio
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val parameterList = element.parent as? KtParameterList ?: return
val ownerFunction = parameterList.ownerFunction ?: return
val arrow = ownerFunction.node.findChildByType(KtTokens.ARROW) ?: return
@@ -31,6 +31,7 @@ class RemoveSupertypeFix(superClass: KtSuperTypeListEntry) : KotlinQuickFixActio
override fun getText() = familyName
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
element.getStrictParentOfType<KtClassOrObject>()?.removeSuperTypeListEntry(element)
}
@@ -30,11 +30,12 @@ import org.jetbrains.kotlin.psi.KtParameter
class RemoveUnusedFunctionParameterFix(parameter: KtParameter) : KotlinQuickFixAction<KtParameter>(parameter) {
override fun getFamilyName() = ChangeFunctionSignatureFix.FAMILY_NAME
override fun getText() = "Remove parameter '${element.name}'"
override fun getText() = element?.let { "Remove parameter '${it.name}'" } ?: ""
override fun startInWriteAction(): Boolean = false
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val parameterDescriptor = element.resolveToDescriptor() as ValueParameterDescriptor
ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, element)
}
@@ -65,6 +65,7 @@ class RemoveUnusedValueFix(expression: KtBinaryExpression) : KotlinQuickFixActio
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val lhs = element.left as? KtSimpleNameExpression ?: return
val rhs = element.right ?: return
val variable = lhs.mainReference.resolve() as? KtProperty ?: return
@@ -31,7 +31,7 @@ class RemoveUselessCastFix(element: KtBinaryExpressionWithTypeRHS) : KotlinQuick
override fun getText(): String = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
invoke(element)
invoke(element ?: return)
}
companion object : KotlinSingleIntentionActionFactory() {
@@ -30,6 +30,7 @@ class RemoveUselessElvisFix(element: KtBinaryExpression) : KotlinQuickFixAction<
override fun getText(): String = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
dropEnclosingParenthesesIfPossible(element.replaced(element.left!!))
}
@@ -35,12 +35,13 @@ class RemoveValVarFromParameterFix(element: KtValVarKeywordOwner) : KotlinQuickF
override fun getFamilyName() = "Remove 'val/var' from parameter"
override fun getText(): String {
val element = element ?: return ""
val varOrVal = element.valOrVarKeyword?.text ?: return familyName
return "Remove '$varOrVal' from parameter"
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.valOrVarKeyword?.delete()
element?.valOrVarKeyword?.delete()
}
companion object : KotlinSingleIntentionActionFactory() {
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
class RenameParameterToMatchOverriddenMethodFix(
private val parameter: KtParameter,
parameter: KtParameter,
private val newName: String
) : KotlinQuickFixAction<KtParameter>(parameter) {
override fun getFamilyName() = "Rename"
@@ -38,7 +38,7 @@ class RenameParameterToMatchOverriddenMethodFix(
override fun startInWriteAction(): Boolean = false
public override fun invoke(project: Project, editor: Editor?, file: KtFile) {
RenameProcessor(project, parameter, newName, false, false).run()
RenameProcessor(project, element ?: return, newName, false, false).run()
}
companion object : KotlinSingleIntentionActionFactory() {
@@ -28,7 +28,7 @@ class RenameToUnderscoreFix(element: KtCallableDeclaration) : KotlinQuickFixActi
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.nameIdentifier?.replace(KtPsiFactory(project).createIdentifier("_"))
element?.nameIdentifier?.replace(KtPsiFactory(project).createIdentifier("_"))
}
companion object Factory : KotlinSingleIntentionActionFactory() {
@@ -75,6 +75,7 @@ class RenameUnresolvedReferenceFix(element: KtNameReferenceExpression): KotlinQu
override fun getFamilyName() = QuickFixBundle.message("rename.wrong.reference.family")
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file)
&& editor != null
&& element.getStrictParentOfType<KtTypeReference>() == null
@@ -83,6 +84,7 @@ class RenameUnresolvedReferenceFix(element: KtNameReferenceExpression): KotlinQu
private fun KtExpression.isCallee() = getParentOfTypeAndBranch<KtCallElement> { calleeExpression } != null
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
if (editor == null) return
val patternExpression = element.getQualifiedElement() as? KtExpression ?: return
@@ -32,10 +32,12 @@ abstract class ReplaceCallFix(
override fun getFamilyName() = text
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
return super.isAvailable(project, editor, file) && element.selectorExpression != null
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val newExpression = KtPsiFactory(element).createExpressionByPattern("$0$operation$1",
element.receiverExpression, element.selectorExpression!!)
element.replace(newExpression)
@@ -36,6 +36,7 @@ class ReplaceInfixOrOperatorCallFix(element: KtExpression) : KotlinQuickFixActio
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val psiFactory = KtPsiFactory(file)
when (element) {
is KtArrayAccessExpression -> {
@@ -34,6 +34,7 @@ class ReplaceJavaAnnotationPositionedArgumentsFix(element: KtAnnotationEntry)
override fun getFamilyName(): String = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return
val psiFactory = KtPsiFactory(project)
@@ -31,9 +31,11 @@ import org.jetbrains.kotlin.resolve.BindingContext
class ReplaceObsoleteLabelSyntaxFix(element: KtAnnotationEntry) : KotlinQuickFixAction<KtAnnotationEntry>(element), CleanupFix {
override fun getFamilyName(): String = "Update obsolete label syntax"
override fun getText(): String = "Replace with label ${element.calleeExpression?.text ?: ""}@"
override fun getText(): String = element?.let { "Replace with label ${it.calleeExpression?.text ?: ""}@" } ?: ""
override fun invoke(project: Project, editor: Editor?, file: KtFile) = replaceWithLabel(element)
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
replaceWithLabel(element ?: return)
}
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
@@ -34,6 +34,7 @@ class SimplifyComparisonFix(element: KtExpression, val value: Boolean) : KotlinQ
override fun getText() = "Simplify comparison"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val parent = element.parent
val replacement = KtPsiFactory(element).createExpression("$value")
element.replace(replacement)
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.render
@@ -111,6 +112,7 @@ object SuperClassNotInitialized : KotlinIntentionActionsFactory() {
override fun getText() = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val newSpecifier = element.replaced(KtPsiFactory(project).createSuperTypeCallEntry(element.text + "()"))
if (putCaretIntoParenthesis) {
@@ -127,11 +129,13 @@ object SuperClassNotInitialized : KotlinIntentionActionsFactory() {
private class AddParametersFix(
element: KtSuperTypeEntry,
private val classDeclaration: KtClass,
private val parametersToAdd: Collection<KtParameter>,
classDeclaration: KtClass,
parametersToAdd: Collection<KtParameter>,
private val argumentText: String,
private val text: String
) : KotlinQuickFixAction<KtSuperTypeEntry>(element) {
private val classDeclarationPointer = classDeclaration.createSmartPointer()
private val parametersToAddPointers = parametersToAdd.map { it.createSmartPointer() }
companion object {
fun create(
@@ -180,6 +184,9 @@ object SuperClassNotInitialized : KotlinIntentionActionsFactory() {
override fun getText() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val classDeclaration = classDeclarationPointer.element ?: return
val parametersToAdd = parametersToAddPointers.map { it.element ?: return }
val factory = KtPsiFactory(project)
val typeRefsToShorten = ArrayList<KtTypeReference>()
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
@@ -38,14 +39,17 @@ import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
class SurroundWithNullCheckFix(
expression: KtExpression,
val nullableExpression: KtExpression
nullableExpression: KtExpression
) : KotlinQuickFixAction<KtExpression>(expression), HighPriorityAction {
private val nullableExpressionPointer = nullableExpression.createSmartPointer()
override fun getFamilyName() = text
override fun getText() = "Surround with null check"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val nullableExpression = nullableExpressionPointer.element ?: return
val factory = KtPsiFactory(element)
val surrounded = factory.createExpressionByPattern("if ($0 != null) { $1 }", nullableExpression, element)
element.replace(surrounded)
@@ -15,6 +15,7 @@ class TooLongCharLiteralToStringFix(
override fun getText(): String = "Convert too long character literal to string"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val text = element.text
if (!(text.startsWith("'") && text.endsWith("'") && text.length >= 2)) {
return
@@ -24,20 +24,24 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
class WrapWithSafeLetCallFix(
expression: KtExpression,
val nullableExpression: KtExpression
nullableExpression: KtExpression
) : KotlinQuickFixAction<KtExpression>(expression) {
private val nullableExpressionPointer = nullableExpression.createSmartPointer()
override fun getFamilyName() = text
override fun getText() = "Wrap with '?.let { ... }' call"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val nullableExpression = nullableExpressionPointer.element ?: return
val factory = KtPsiFactory(element)
val nullableText = nullableExpression.text
val validator = NewDeclarationNameValidator(element, nullableExpression, NewDeclarationNameValidator.Target.VARIABLES)
@@ -26,14 +26,13 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
class WrongLongSuffixFix(element: KtConstantExpression) : KotlinQuickFixAction<KtConstantExpression>(element) {
private val corrected = element.text.trimEnd('l') + 'L'
override fun getText() = "Change to '$corrected'"
override fun getFamilyName() = "Change to correct long suffix 'L'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
element.replace(KtPsiFactory(project).createExpression(corrected))
element?.replace(KtPsiFactory(project).createExpression(corrected))
}
companion object Factory: KotlinSingleIntentionActionFactory() {
@@ -89,6 +89,7 @@ class WrongPrimitiveLiteralFix(element: KtConstantExpression, type: KotlinType)
override fun getText() = "Change to '$fixedExpression'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val expressionToInsert = KtPsiFactory(file).createExpression(fixedExpression)
val newExpression = element.replaced(expressionToInsert)
editor?.caretModel?.moveToOffset(newExpression.endOffset)
@@ -65,7 +65,7 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
if (descriptor is FunctionClassDescriptor) {
val psiFactory = KtPsiFactory(project)
val syntheticClass = psiFactory.createClass(IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(descriptor))
return psiFactory.createAnalyzableFile("${descriptor.name.asString()}.kt", "", element).add(syntheticClass)
return psiFactory.createAnalyzableFile("${descriptor.name.asString()}.kt", "", element!!).add(syntheticClass)
}
return DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor)
}
@@ -78,6 +78,7 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
}
override fun getText(): String {
val element = element ?: return ""
val renderedCallables = callableInfos.map {
buildString {
if (it.isAbstract) {
@@ -138,6 +139,7 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
if (!super.isAvailable(project, editor, file)) return false
if (file !is KtFile) return false
val element = element ?: return false
val receiverInfo = callableInfos.first().receiverTypeInfo
@@ -169,6 +171,7 @@ abstract class CreateCallableFromUsageFixBase<E : KtElement>(
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val callableInfo = callableInfos.first()
val callableBuilder =
@@ -46,6 +46,7 @@ class CreateTypeAliasFromUsageFix<E : KtElement>(
override fun getText() = "Create type alias '${aliasInfo.name}'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
if (editor == null) return
val typeAliasProto = KtPsiFactory(project).createTypeAlias(aliasInfo.name, aliasInfo.typeParameterNames, "Dummy")
@@ -35,6 +35,7 @@ class MigrateTypeParameterListFix(typeParameterList: KtTypeParameterList)
override fun getText(): String = familyName
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val function = element.getStrictParentOfType<KtNamedFunction>() ?: return
function.addBefore(element, function.receiverTypeReference ?: function.nameIdentifier)
element.delete()
@@ -39,6 +39,7 @@ class DeprecatedSymbolUsageFix(
override fun getText() = "Replace with '${replaceWith.pattern}'" //TODO: substitute?
override fun invoke(replacementStrategy: UsageReplacementStrategy, project: Project, editor: Editor?) {
val element = element ?: return
val result = replacementStrategy.createReplacer(element)!!.invoke()
val offset = (result.getCalleeExpressionIfAny() ?: result).textOffset
editor?.moveCaret(offset)
@@ -44,12 +44,14 @@ abstract class DeprecatedSymbolUsageFixBase(
) : KotlinQuickFixAction<KtSimpleNameExpression>(element) {
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
val element = element ?: return false
if (!super.isAvailable(project, editor, file)) return false
val strategy = UsageReplacementStrategy.build(element, replaceWith, recheckAnnotation = true)
return strategy != null && strategy.createReplacer(element) != null
}
final override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val strategy = UsageReplacementStrategy.build(element, replaceWith, recheckAnnotation = false)!!
invoke(strategy, project, editor)
}
@@ -78,7 +78,7 @@ class DeprecatedSymbolUsageInWholeProjectFix(
}
private fun targetPsiElement(): KtDeclaration? {
val referenceTarget = element.mainReference.resolve()
val referenceTarget = element?.mainReference?.resolve()
return when (referenceTarget) {
is KtNamedFunction -> referenceTarget
is KtProperty -> referenceTarget