Refactored change signature fixes to not hold DeclarationDescriptor's
This commit is contained in:
@@ -20,6 +20,9 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
|
||||
@@ -57,4 +60,26 @@ class ChangeFunctionLiteralSignatureFix(
|
||||
context,
|
||||
text)
|
||||
}
|
||||
|
||||
companion object : KotlinIntentionActionFactoryWithDelegate<JetFunctionLiteral, Data>() {
|
||||
data class Data(val functionLiteral: JetFunctionLiteral, val descriptor: FunctionDescriptor, val parameterTypes: List<JetType>)
|
||||
|
||||
override fun getElementOfInterest(diagnostic: Diagnostic): JetFunctionLiteral? {
|
||||
val diagnosticWithParameters = Errors.EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic)
|
||||
return diagnosticWithParameters.psiElement as? JetFunctionLiteral
|
||||
}
|
||||
|
||||
override fun createQuickFixData(element: JetFunctionLiteral, diagnostic: Diagnostic): Data? {
|
||||
val descriptor = element.resolveToDescriptor() as? FunctionDescriptor ?: return null
|
||||
val parameterTypes = Errors.EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic).b
|
||||
return Data(element, descriptor, parameterTypes)
|
||||
}
|
||||
|
||||
override fun createQuickFix(diagnostic: Diagnostic, quickFixDataFactory: () -> Data?): QuickFixWithDelegateFactory? {
|
||||
return QuickFixWithDelegateFactory {
|
||||
val (functionLiteral, descriptor, parameterTypes) = quickFixDataFactory() ?: return@QuickFixWithDelegateFactory null
|
||||
ChangeFunctionLiteralSignatureFix(functionLiteral, descriptor, parameterTypes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -28,17 +27,19 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_PARAMETERS_NUMBER_MISMATCH
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.UNUSED_PARAMETER
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.mapArgumentsToParameters
|
||||
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.modify
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature
|
||||
import org.jetbrains.kotlin.psi.JetCallElement
|
||||
import org.jetbrains.kotlin.psi.JetFunctionLiteral
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
@@ -48,7 +49,7 @@ abstract class ChangeFunctionSignatureFix(
|
||||
protected val functionDescriptor: FunctionDescriptor
|
||||
) : KotlinQuickFixAction<PsiElement>(context) {
|
||||
|
||||
override fun getFamilyName() = "Change signature of function/constructor"
|
||||
override fun getFamilyName() = FAMILY_NAME
|
||||
|
||||
override fun startInWriteAction() = false
|
||||
|
||||
@@ -75,61 +76,94 @@ abstract class ChangeFunctionSignatureFix(
|
||||
}
|
||||
}
|
||||
|
||||
object Factory : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
||||
val callElement = PsiTreeUtil.getParentOfType(diagnostic.psiElement, JetCallElement::class.java) ?: return null
|
||||
companion object : KotlinIntentionActionFactoryWithDelegate<JetCallElement, Data>() {
|
||||
data class Data(val callElement: JetCallElement, val descriptor: CallableDescriptor)
|
||||
|
||||
override fun getElementOfInterest(diagnostic: Diagnostic): JetCallElement? {
|
||||
return diagnostic.psiElement.getNonStrictParentOfType<JetCallElement>()
|
||||
}
|
||||
|
||||
override fun createQuickFixData(element: JetCallElement, diagnostic: Diagnostic): Data? {
|
||||
val descriptor = DiagnosticFactory.cast(diagnostic, Errors.TOO_MANY_ARGUMENTS, Errors.NO_VALUE_FOR_PARAMETER).a
|
||||
return createFix(callElement, callElement, descriptor)
|
||||
return Data(element, descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
object FactoryForParametersNumberMismatch: JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
||||
val diagnosticWithParameters = EXPECTED_PARAMETERS_NUMBER_MISMATCH.cast(diagnostic)
|
||||
val functionLiteral = diagnosticWithParameters.psiElement as? JetFunctionLiteral ?: return null
|
||||
val descriptor = functionLiteral.resolveToDescriptor() as? FunctionDescriptor ?: return null
|
||||
return ChangeFunctionLiteralSignatureFix(functionLiteral, descriptor, diagnosticWithParameters.b)
|
||||
}
|
||||
}
|
||||
|
||||
object FactoryForUnusedParameter : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): ChangeFunctionSignatureFix? {
|
||||
val descriptor = UNUSED_PARAMETER.cast(diagnostic).a as? ValueParameterDescriptor ?: return null
|
||||
return createFix(null, diagnostic.psiElement, descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFix(callElement: JetCallElement?, context: PsiElement, descriptor: CallableDescriptor): ChangeFunctionSignatureFix? {
|
||||
val functionDescriptor = when (descriptor) {
|
||||
is FunctionDescriptor -> descriptor as FunctionDescriptor
|
||||
else -> if (descriptor is ValueParameterDescriptor) descriptor.containingDeclaration as? FunctionDescriptor
|
||||
else null
|
||||
} ?: return null
|
||||
|
||||
if (functionDescriptor.kind == SYNTHESIZED) return null
|
||||
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
return RemoveFunctionParametersFix(context, functionDescriptor, descriptor)
|
||||
}
|
||||
else {
|
||||
val parameters = functionDescriptor.valueParameters
|
||||
val arguments = callElement!!.valueArguments
|
||||
|
||||
if (arguments.size > parameters.size) {
|
||||
val bindingContext = callElement.analyze()
|
||||
val call = callElement.getCall(bindingContext) ?: return null
|
||||
val argumentToParameter = call.mapArgumentsToParameters(functionDescriptor)
|
||||
val hasTypeMismatches = argumentToParameter.any {
|
||||
val argument = it.key
|
||||
val parameter = it.value
|
||||
val argumentType = argument.getArgumentExpression()?.let { bindingContext.getType(it) }
|
||||
argumentType == null || !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameter.type)
|
||||
override fun createQuickFix(diagnostic: Diagnostic, quickFixDataFactory: () -> Data?): QuickFixWithDelegateFactory {
|
||||
return QuickFixWithDelegateFactory {
|
||||
val (callElement, descriptor) = quickFixDataFactory() ?: return@QuickFixWithDelegateFactory null
|
||||
createFix(callElement, callElement, descriptor)
|
||||
}
|
||||
return AddFunctionParametersFix(callElement, functionDescriptor, hasTypeMismatches)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
private fun createFix(callElement: JetCallElement, context: PsiElement, descriptor: CallableDescriptor): ChangeFunctionSignatureFix? {
|
||||
val functionDescriptor = when (descriptor) {
|
||||
is FunctionDescriptor -> descriptor as FunctionDescriptor
|
||||
else -> if (descriptor is ValueParameterDescriptor) descriptor.containingDeclaration as? FunctionDescriptor
|
||||
else null
|
||||
} ?: return null
|
||||
|
||||
if (functionDescriptor.kind == SYNTHESIZED) return null
|
||||
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
return RemoveParameterFix(context, functionDescriptor, descriptor)
|
||||
}
|
||||
else {
|
||||
val parameters = functionDescriptor.valueParameters
|
||||
val arguments = callElement.valueArguments
|
||||
|
||||
if (arguments.size > parameters.size) {
|
||||
val bindingContext = callElement.analyze()
|
||||
val call = callElement.getCall(bindingContext) ?: return null
|
||||
val argumentToParameter = call.mapArgumentsToParameters(functionDescriptor)
|
||||
val hasTypeMismatches = argumentToParameter.any {
|
||||
val argument = it.key
|
||||
val parameter = it.value
|
||||
val argumentType = argument.getArgumentExpression()?.let { bindingContext.getType(it) }
|
||||
argumentType == null || !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameter.type)
|
||||
}
|
||||
return AddFunctionParametersFix(callElement, functionDescriptor, hasTypeMismatches)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private class RemoveParameterFix(
|
||||
context: PsiElement,
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
private val parameterToRemove: ValueParameterDescriptor
|
||||
) : ChangeFunctionSignatureFix(context, functionDescriptor) {
|
||||
|
||||
override fun getText() = "Remove parameter '${parameterToRemove.name.asString()}'"
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||
runRemoveParameter(parameterToRemove, context)
|
||||
}
|
||||
}
|
||||
|
||||
val FAMILY_NAME = "Change signature of function/constructor"
|
||||
|
||||
fun runRemoveParameter(parameterDescriptor: ValueParameterDescriptor, context: PsiElement) {
|
||||
val functionDescriptor = parameterDescriptor.containingDeclaration as FunctionDescriptor
|
||||
runChangeSignature(
|
||||
context.project,
|
||||
functionDescriptor,
|
||||
object : JetChangeSignatureConfiguration {
|
||||
override fun configure(originalDescriptor: JetMethodDescriptor): JetMethodDescriptor {
|
||||
return originalDescriptor.modify { descriptor ->
|
||||
val index = if (descriptor.receiver != null) parameterDescriptor.index + 1 else parameterDescriptor.index
|
||||
descriptor.removeParameter(index)
|
||||
}
|
||||
}
|
||||
|
||||
override fun performSilently(affectedFunctions: Collection<PsiElement>) = false
|
||||
override fun forcePerformForSelectedFunctionOnly() = false
|
||||
},
|
||||
context,
|
||||
"Remove parameter '${parameterDescriptor.name.asString()}'")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -222,10 +222,10 @@ public class QuickFixRegistrar : QuickFixContributor {
|
||||
COMPARE_TO_TYPE_MISMATCH.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForCompareToTypeMismatch())
|
||||
IMPLICIT_NOTHING_RETURN_TYPE.registerFactory(ChangeFunctionReturnTypeFix.createFactoryForChangingReturnTypeToNothing())
|
||||
|
||||
TOO_MANY_ARGUMENTS.registerFactory(ChangeFunctionSignatureFix.Factory)
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix.Factory)
|
||||
UNUSED_PARAMETER.registerFactory(ChangeFunctionSignatureFix.FactoryForUnusedParameter)
|
||||
EXPECTED_PARAMETERS_NUMBER_MISMATCH.registerFactory(ChangeFunctionSignatureFix.FactoryForParametersNumberMismatch)
|
||||
TOO_MANY_ARGUMENTS.registerFactory(ChangeFunctionSignatureFix)
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix)
|
||||
UNUSED_PARAMETER.registerFactory(RemoveUnusedFunctionParameterFix)
|
||||
EXPECTED_PARAMETERS_NUMBER_MISMATCH.registerFactory(ChangeFunctionLiteralSignatureFix)
|
||||
|
||||
EXPECTED_PARAMETER_TYPE_MISMATCH.registerFactory(ChangeTypeFix.createFactoryForExpectedParameterTypeMismatch())
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.modify
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
|
||||
class RemoveFunctionParametersFix(
|
||||
context: PsiElement,
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
private val parameterToRemove: ValueParameterDescriptor
|
||||
) : ChangeFunctionSignatureFix(context, functionDescriptor) {
|
||||
|
||||
override fun getText() = "Remove parameter '${parameterToRemove.name.asString()}'"
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||
runChangeSignature(
|
||||
project,
|
||||
functionDescriptor,
|
||||
object : JetChangeSignatureConfiguration {
|
||||
override fun configure(originalDescriptor: JetMethodDescriptor): JetMethodDescriptor {
|
||||
return originalDescriptor.modify { descriptor ->
|
||||
val index = functionDescriptor.valueParameters.indexOf(parameterToRemove)
|
||||
descriptor.removeParameter(if (descriptor.receiver != null) index + 1 else index)
|
||||
}
|
||||
}
|
||||
|
||||
override fun performSilently(affectedFunctions: Collection<PsiElement>) = false
|
||||
override fun forcePerformForSelectedFunctionOnly() = false
|
||||
},
|
||||
context,
|
||||
text)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.quickfix
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.psi.JetParameter
|
||||
|
||||
class RemoveUnusedFunctionParameterFix(parameter: JetParameter) : KotlinQuickFixAction<JetParameter>(parameter) {
|
||||
override fun getFamilyName() = ChangeFunctionSignatureFix.FAMILY_NAME
|
||||
|
||||
override fun getText() = "Remove parameter '${element.name}'"
|
||||
|
||||
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||
val parameterDescriptor = element.resolveToDescriptor() as ValueParameterDescriptor
|
||||
ChangeFunctionSignatureFix.runRemoveParameter(parameterDescriptor, element)
|
||||
}
|
||||
|
||||
companion object : JetSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction<JetParameter> {
|
||||
return RemoveUnusedFunctionParameterFix(Errors.UNUSED_PARAMETER.cast(diagnostic).psiElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "class org.jetbrains.kotlin.idea.quickfix.RemoveFunctionParametersFix" "false"
|
||||
// "class org.jetbrains.kotlin.idea.quickfix.ChangeFunctionSignatureFix" "false"
|
||||
//ERROR: No value passed for parameter other
|
||||
|
||||
abstract class StringComparable {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "class org.jetbrains.kotlin.idea.quickfix.RemoveFunctionParametersFix" "false"
|
||||
// "class org.jetbrains.kotlin.idea.quickfix.ChangeFunctionSignatureFix" "false"
|
||||
// ERROR: No value passed for parameter other
|
||||
|
||||
fun f(d: Boolean) {
|
||||
|
||||
Reference in New Issue
Block a user