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