diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties index 58cd86d0973..cb4bd3012c2 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/JetBundle.properties @@ -60,10 +60,7 @@ change.function.parameter.type=Change parameter ''{0}'' type of function ''{1}'' change.primary.constructor.parameter.type=Change parameter ''{0}'' type of primary constructor of class ''{1}'' to ''{2}'' change.type=Change type from ''{0}'' to ''{1}'' change.type.family=Change Type -add.parameters.to.function=Add parameter{0} to function ''{1}'' -add.parameters.to.constructor=Add parameter{0} to constructor ''{1}'' change.function.signature=Change the signature of function ''{0}'' -change.constructor.signature=Change the signature of constructor ''{0}'' change.function.literal.signature=Change the signature of function literal remove.parameter=Remove parameter ''{0}'' change.signature.family=Change signature of function/constructor diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddFunctionParametersFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddFunctionParametersFix.kt index 0fd9d35fad9..44a9a8cc765 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddFunctionParametersFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddFunctionParametersFix.kt @@ -14,183 +14,127 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.quickfix; +package org.jetbrains.kotlin.idea.quickfix -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.PsiReference; -import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.PsiTreeUtil; -import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor; -import org.jetbrains.kotlin.descriptors.FunctionDescriptor; -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; -import org.jetbrains.kotlin.idea.JetBundle; -import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; -import org.jetbrains.kotlin.idea.core.CollectingNameValidator; -import org.jetbrains.kotlin.idea.refactoring.changeSignature.*; -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers; -import org.jetbrains.kotlin.psi.JetCallElement; -import org.jetbrains.kotlin.psi.JetExpression; -import org.jetbrains.kotlin.psi.JetFile; -import org.jetbrains.kotlin.psi.ValueArgument; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.types.JetType; -import org.jetbrains.kotlin.types.checker.JetTypeChecker; +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.search.searches.ReferencesSearch +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully +import org.jetbrains.kotlin.idea.core.CollectingNameValidator +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.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.psi.JetCallElement +import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.types.checker.JetTypeChecker +import java.util.* -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +public class AddFunctionParametersFix( + private val callElement: JetCallElement, + functionDescriptor: FunctionDescriptor, + private val hasTypeMismatches: Boolean) : ChangeFunctionSignatureFix(callElement, functionDescriptor) { + private val typesToShorten = ArrayList() -import static org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignaturePackage.runChangeSignature; + override fun getText(): String { + val parameters = functionDescriptor.valueParameters + val arguments = callElement.valueArguments + val newParametersCnt = arguments.size() - parameters.size() + assert(newParametersCnt > 0) -public class AddFunctionParametersFix extends ChangeFunctionSignatureFix { - private final JetCallElement callElement; - private final boolean hasTypeMismatches; - private final List typesToShorten = new ArrayList(); + val subjectSuffix = if (newParametersCnt > 1) "s" else "" - public AddFunctionParametersFix( - @NotNull JetCallElement callElement, - @NotNull FunctionDescriptor functionDescriptor, - boolean hasTypeMismatches - ) { - super(callElement, functionDescriptor); - this.callElement = callElement; - this.hasTypeMismatches = hasTypeMismatches; - } - - @NotNull - @Override - public String getText() { - List parameters = functionDescriptor.getValueParameters(); - List arguments = callElement.getValueArguments(); - int newParametersCnt = arguments.size() - parameters.size(); - assert newParametersCnt > 0; - String subjectSuffix = newParametersCnt > 1 ? "s" : ""; - - if (isConstructor()) { - String className = functionDescriptor.getContainingDeclaration().getName().asString(); - - if (hasTypeMismatches) - return JetBundle.message("change.constructor.signature", className); - else - return JetBundle.message("add.parameters.to.constructor", subjectSuffix, className); + val callableDescription = if (isConstructor()) { + val className = functionDescriptor.containingDeclaration.name.asString() + "constructor '$className'" } else { - String functionName = functionDescriptor.getName().asString(); - - if (hasTypeMismatches) - return JetBundle.message("change.function.signature", functionName); - else - return JetBundle.message("add.parameters.to.function", subjectSuffix, functionName); - } - } - - @Override - public boolean isAvailable( - @NotNull Project project, Editor editor, PsiFile file - ) { - if (!super.isAvailable(project, editor, file)) { - return false; + val functionName = functionDescriptor.name.asString() + "function '$functionName'" } - int newParametersCnt = callElement.getValueArguments().size() - functionDescriptor.getValueParameters().size(); - if (newParametersCnt <= 0) { - // psi for this quickfix is no longer valid - return false; - } - return true; + return if (hasTypeMismatches) + "Change the signature of $callableDescription" + else + "Add parameter$subjectSuffix to $callableDescription" } - @Override - public boolean startInWriteAction() { - return true; + override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { + if (!super.isAvailable(project, editor, file)) return false + + // newParametersCnt <= 0: psi for this quickfix is no longer valid + val newParametersCnt = callElement.valueArguments.size() - functionDescriptor.valueParameters.size() + return newParametersCnt > 0 } - @Override - protected void invoke(@NotNull Project project, Editor editor, JetFile file) { - BindingContext bindingContext = ResolutionUtils.analyzeFully((JetFile) callElement.getContainingFile()); - runChangeSignature(project, functionDescriptor, addParameterConfiguration(), bindingContext, callElement, getText()); + override fun startInWriteAction() = true + + override fun invoke(project: Project, editor: Editor?, file: JetFile) { + runChangeSignature(project, functionDescriptor, addParameterConfiguration(), callElement.analyzeFully(), callElement, text) } - private JetChangeSignatureConfiguration addParameterConfiguration() { - return new JetChangeSignatureConfiguration() { - @NotNull - @Override - public JetMethodDescriptor configure(@NotNull final JetMethodDescriptor originalDescriptor, @NotNull final BindingContext bindingContext) { - return ChangeSignaturePackage.modify( - originalDescriptor, - new Function1() { - @Override - public Unit invoke(JetMutableMethodDescriptor descriptor) { - List parameters = functionDescriptor.getValueParameters(); - List arguments = callElement.getValueArguments(); - CollectingNameValidator validator = new CollectingNameValidator(); + private fun addParameterConfiguration(): JetChangeSignatureConfiguration { + return object : JetChangeSignatureConfiguration { + override fun configure(originalDescriptor: JetMethodDescriptor, bindingContext: BindingContext): JetMethodDescriptor { + return originalDescriptor.modify { + val parameters = functionDescriptor.valueParameters + val arguments = callElement.valueArguments + val validator = CollectingNameValidator() - for (int i = 0; i < arguments.size(); i ++) { - ValueArgument argument = arguments.get(i); - JetExpression expression = argument.getArgumentExpression(); + for (i in arguments.indices) { + val argument = arguments.get(i) + val expression = argument.getArgumentExpression() - if (i < parameters.size()) { - validator.addName(parameters.get(i).getName().asString()); - JetType argumentType = expression != null ? bindingContext.getType(expression) : null; - JetType parameterType = parameters.get(i).getType(); + if (i < parameters.size()) { + validator.addName(parameters.get(i).name.asString()) + val argumentType = expression?.let { bindingContext.getType(it) } + val parameterType = parameters.get(i).type - if (argumentType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) { - descriptor.getParameters().get(i).setCurrentTypeText(IdeDescriptorRenderers.SOURCE_CODE.renderType(argumentType)); - typesToShorten.add(argumentType); - } - } - else { - JetParameterInfo parameterInfo = - getNewParameterInfo((FunctionDescriptor) originalDescriptor.getBaseDescriptor(), bindingContext, argument, validator); - typesToShorten.add(parameterInfo.getOriginalType()); - - if (expression != null) { - parameterInfo.setDefaultValueForCall(expression); - } - - descriptor.addParameter(parameterInfo); - } - } - return null; + if (argumentType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) { + it.parameters.get(i).currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(argumentType) + typesToShorten.add(argumentType) } } - ); - } + else { + val parameterInfo = ChangeFunctionSignatureFix.getNewParameterInfo( + originalDescriptor.baseDescriptor as FunctionDescriptor, + bindingContext, + argument, + validator + ) + parameterInfo.originalType?.let { typesToShorten.add(it) } - @Override - public boolean performSilently(@NotNull Collection affectedFunctions) { - if (affectedFunctions.size() != 1) { - return false; + if (expression != null) { + parameterInfo.defaultValueForCall = expression + } + + it.addParameter(parameterInfo) + } + } } - PsiElement onlyFunction = affectedFunctions.iterator().next(); - return !hasTypeMismatches && !isConstructor() && !hasOtherUsages(onlyFunction); } - @Override - public boolean forcePerformForSelectedFunctionOnly() { - return false; - } - }; - } - - private boolean hasOtherUsages(@NotNull PsiElement function) { - for (PsiReference reference : ReferencesSearch.search(function)) { - JetCallElement call = PsiTreeUtil.getParentOfType(reference.getElement(), JetCallElement.class); - if (call != null && !callElement.equals(call)) { - return true; + override fun performSilently(affectedFunctions: Collection): Boolean { + val onlyFunction = affectedFunctions.singleOrNull() ?: return false + return !hasTypeMismatches && !isConstructor() && !hasOtherUsages(onlyFunction) } } - - return false; } - private boolean isConstructor() { - return functionDescriptor instanceof ConstructorDescriptor; + private fun hasOtherUsages(function: PsiElement): Boolean { + return ReferencesSearch.search(function).any { + val call = it.element.getParentOfType(false) + call != null && callElement != call + } } + + private fun isConstructor() = functionDescriptor is ConstructorDescriptor }