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.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
|
||||
|
||||
@@ -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<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 {
|
||||
private final JetCallElement callElement;
|
||||
private final boolean hasTypeMismatches;
|
||||
private final List<JetType> typesToShorten = new ArrayList<JetType>();
|
||||
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<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);
|
||||
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<JetMutableMethodDescriptor, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(JetMutableMethodDescriptor descriptor) {
|
||||
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
|
||||
List<? extends ValueArgument> 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<? extends PsiElement> 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<PsiElement>): 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<JetCallElement>(false)
|
||||
call != null && callElement != call
|
||||
}
|
||||
}
|
||||
|
||||
private fun isConstructor() = functionDescriptor is ConstructorDescriptor
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user