Change Signature: Make JetChangeSignatureData read-only and use JetDelegatingMethodDescriptor for refactoring configuration

This commit is contained in:
Alexey Sedunov
2015-01-27 16:04:35 +03:00
parent fecfc93e63
commit 7b6160b92f
10 changed files with 153 additions and 85 deletions
@@ -23,6 +23,8 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference; import com.intellij.psi.PsiReference;
import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import kotlin.ExtensionFunction0;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor; import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
@@ -31,9 +33,7 @@ import org.jetbrains.kotlin.idea.JetBundle;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.refactoring.JetNameValidator; import org.jetbrains.kotlin.idea.refactoring.JetNameValidator;
import org.jetbrains.kotlin.idea.refactoring.SimpleCollectingValidator; import org.jetbrains.kotlin.idea.refactoring.SimpleCollectingValidator;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration; import org.jetbrains.kotlin.idea.refactoring.changeSignature.*;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureData;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers; import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
import org.jetbrains.kotlin.psi.JetCallElement; import org.jetbrains.kotlin.psi.JetCallElement;
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.psi.JetExpression;
@@ -120,39 +120,47 @@ public class AddFunctionParametersFix extends ChangeFunctionSignatureFix {
private JetChangeSignatureConfiguration addParameterConfiguration() { private JetChangeSignatureConfiguration addParameterConfiguration() {
return new JetChangeSignatureConfiguration() { return new JetChangeSignatureConfiguration() {
@NotNull
@Override @Override
public void configure(@NotNull JetChangeSignatureData changeSignatureData, @NotNull BindingContext bindingContext) { public JetMethodDescriptor configure(@NotNull JetMethodDescriptor originalDescriptor, @NotNull final BindingContext bindingContext) {
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters(); return ChangeSignaturePackage.modify(
List<? extends ValueArgument> arguments = callElement.getValueArguments(); originalDescriptor,
JetNameValidator validator = new SimpleCollectingValidator(); new ExtensionFunction0<JetMutableMethodDescriptor, Unit>() {
@Override
public Unit invoke(JetMutableMethodDescriptor descriptor) {
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
List<? extends ValueArgument> arguments = callElement.getValueArguments();
JetNameValidator validator = new SimpleCollectingValidator();
for (int i = 0; i < arguments.size(); i ++) { for (int i = 0; i < arguments.size(); i ++) {
ValueArgument argument = arguments.get(i); ValueArgument argument = arguments.get(i);
JetExpression expression = argument.getArgumentExpression(); JetExpression expression = argument.getArgumentExpression();
if (i < parameters.size()) { if (i < parameters.size()) {
validator.validateName(parameters.get(i).getName().asString()); validator.validateName(parameters.get(i).getName().asString());
JetType argumentType = expression != null ? bindingContext.get(BindingContext.EXPRESSION_TYPE, expression) : null; JetType argumentType = expression != null ? bindingContext.get(BindingContext.EXPRESSION_TYPE, expression) : null;
JetType parameterType = parameters.get(i).getType(); JetType parameterType = parameters.get(i).getType();
if (argumentType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) { if (argumentType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(argumentType, parameterType)) {
changeSignatureData.getParameters().get(i).setCurrentTypeText( descriptor.getParameters().get(i).setCurrentTypeText(IdeDescriptorRenderers.SOURCE_CODE.renderType(argumentType));
IdeDescriptorRenderers.SOURCE_CODE.renderType(argumentType) typesToShorten.add(argumentType);
); }
typesToShorten.add(argumentType); }
else {
JetParameterInfo parameterInfo = getNewParameterInfo(bindingContext, argument, validator);
typesToShorten.add(parameterInfo.getOriginalType());
if (expression != null) {
parameterInfo.setDefaultValueForCall(expression.getText());
}
descriptor.addParameter(parameterInfo);
}
}
return null;
}
} }
} );
else {
JetParameterInfo parameterInfo = getNewParameterInfo(bindingContext, argument, validator);
typesToShorten.add(parameterInfo.getOriginalType());
if (expression != null) {
parameterInfo.setDefaultValueForCall(expression.getText());
}
changeSignatureData.addParameter(parameterInfo);
}
}
} }
@Override @Override
@@ -19,6 +19,8 @@ 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 kotlin.ExtensionFunction0;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.idea.JetBundle; import org.jetbrains.kotlin.idea.JetBundle;
@@ -26,9 +28,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.refactoring.JetNameSuggester; import org.jetbrains.kotlin.idea.refactoring.JetNameSuggester;
import org.jetbrains.kotlin.idea.refactoring.JetNameValidator; import org.jetbrains.kotlin.idea.refactoring.JetNameValidator;
import org.jetbrains.kotlin.idea.refactoring.SimpleCollectingValidator; import org.jetbrains.kotlin.idea.refactoring.SimpleCollectingValidator;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration; import org.jetbrains.kotlin.idea.refactoring.changeSignature.*;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureData;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.psi.JetFunctionLiteral; import org.jetbrains.kotlin.psi.JetFunctionLiteral;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
@@ -60,18 +60,28 @@ public class ChangeFunctionLiteralSignatureFix extends ChangeFunctionSignatureFi
protected void invoke(@NotNull Project project, Editor editor, JetFile file) { protected void invoke(@NotNull Project project, Editor editor, JetFile file) {
BindingContext bindingContext = ResolvePackage.analyzeFully(file); BindingContext bindingContext = ResolvePackage.analyzeFully(file);
runChangeSignature(project, functionDescriptor, new JetChangeSignatureConfiguration() { runChangeSignature(project, functionDescriptor, new JetChangeSignatureConfiguration() {
@NotNull
@Override @Override
public void configure(@NotNull JetChangeSignatureData changeSignatureData, @NotNull BindingContext bindingContext) { public JetMethodDescriptor configure(@NotNull JetMethodDescriptor originalDescriptor, @NotNull BindingContext bindingContext) {
JetNameValidator validator = new SimpleCollectingValidator(); return ChangeSignaturePackage.modify(
changeSignatureData.clearParameters(); originalDescriptor,
for (JetType type : parameterTypes) { new ExtensionFunction0<JetMutableMethodDescriptor, Unit>() {
String name = JetNameSuggester.suggestNames(type, validator, "param")[0]; @Override
changeSignatureData.addParameter(new JetParameterInfo(-1, name, type, null, "", null, null)); public Unit invoke(JetMutableMethodDescriptor descriptor) {
} JetNameValidator validator = new SimpleCollectingValidator();
descriptor.clearParameters();
for (JetType type : parameterTypes) {
String name = JetNameSuggester.suggestNames(type, validator, "param")[0];
descriptor.addParameter(new JetParameterInfo(-1, name, type, null, "", null, null));
}
return null;
}
}
);
} }
@Override @Override
public boolean performSilently(Collection<? extends PsiElement> elements) { public boolean performSilently(@NotNull Collection<? extends PsiElement> elements) {
return false; return false;
} }
}, bindingContext, context, getText()); }, bindingContext, context, getText());
@@ -19,13 +19,17 @@ 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 kotlin.ExtensionFunction0;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.idea.JetBundle; import org.jetbrains.kotlin.idea.JetBundle;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignaturePackage;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration; import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureData; import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMutableMethodDescriptor;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
@@ -56,12 +60,20 @@ public class RemoveFunctionParametersFix extends ChangeFunctionSignatureFix {
protected void invoke(@NotNull Project project, Editor editor, JetFile file) { protected void invoke(@NotNull Project project, Editor editor, JetFile file) {
BindingContext bindingContext = ResolvePackage.analyzeFully(file); BindingContext bindingContext = ResolvePackage.analyzeFully(file);
runChangeSignature(project, functionDescriptor, new JetChangeSignatureConfiguration() { runChangeSignature(project, functionDescriptor, new JetChangeSignatureConfiguration() {
@NotNull
@Override @Override
public void configure( public JetMethodDescriptor configure(@NotNull JetMethodDescriptor originalDescriptor, @NotNull BindingContext bindingContext) {
@NotNull JetChangeSignatureData changeSignatureData, @NotNull BindingContext bindingContext return ChangeSignaturePackage.modify(
) { originalDescriptor,
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters(); new ExtensionFunction0<JetMutableMethodDescriptor, Unit>() {
changeSignatureData.removeParameter(parameters.indexOf(parameterToRemove)); @Override
public Unit invoke(JetMutableMethodDescriptor descriptor) {
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
descriptor.removeParameter(parameters.indexOf(parameterToRemove));
return null;
}
}
);
} }
@Override @Override
@@ -23,12 +23,13 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureConfiguration
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureData
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor
import org.jetbrains.kotlin.idea.refactoring.changeSignature.modify
public class CreateParameterFromUsageFix( public class CreateParameterFromUsageFix(
val functionDescriptor: FunctionDescriptor, val functionDescriptor: FunctionDescriptor,
@@ -42,8 +43,8 @@ public class CreateParameterFromUsageFix(
override fun invoke(project: Project, editor: Editor?, file: JetFile?) { override fun invoke(project: Project, editor: Editor?, file: JetFile?) {
val config = object : JetChangeSignatureConfiguration { val config = object : JetChangeSignatureConfiguration {
override fun configure(changeSignatureData: JetChangeSignatureData, bindingContext: BindingContext) { override fun configure(originalDescriptor: JetMethodDescriptor, bindingContext: BindingContext): JetMethodDescriptor {
changeSignatureData.addParameter(parameterInfo) return originalDescriptor.modify { addParameter(parameterInfo) }
} }
override fun performSilently(affectedFunctions: Collection<PsiElement>): Boolean = false override fun performSilently(affectedFunctions: Collection<PsiElement>): Boolean = false
@@ -38,13 +38,19 @@ import org.jetbrains.kotlin.resolve.OverrideResolver
import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring
public trait JetChangeSignatureConfiguration { public trait JetChangeSignatureConfiguration {
fun configure(changeSignatureData: JetChangeSignatureData, bindingContext: BindingContext) fun configure(originalDescriptor: JetMethodDescriptor, bindingContext: BindingContext): JetMethodDescriptor
fun performSilently(affectedFunctions: Collection<PsiElement>): Boolean { fun performSilently(affectedFunctions: Collection<PsiElement>): Boolean {
return false return false
} }
} }
fun JetMethodDescriptor.modify(action: JetMutableMethodDescriptor.() -> Unit): JetMethodDescriptor {
val newDescriptor = JetMutableMethodDescriptor(this)
newDescriptor.action()
return newDescriptor
}
public fun runChangeSignature(project: Project, public fun runChangeSignature(project: Project,
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
configuration: JetChangeSignatureConfiguration, configuration: JetChangeSignatureConfiguration,
@@ -97,9 +103,9 @@ public class JetChangeSignature(project: Project,
return null return null
} }
val changeSignatureData = JetChangeSignatureData(baseDescriptor, functionDeclaration, descriptorsForSignatureChange) val originalDescriptor = JetChangeSignatureData(baseDescriptor, functionDeclaration, descriptorsForSignatureChange)
configuration.configure(changeSignatureData, bindingContext) val adjustedDescriptor = configuration.configure(originalDescriptor, bindingContext)
return JetChangeSignatureDialog(project, changeSignatureData, defaultValueContext, commandName) return JetChangeSignatureDialog(project, adjustedDescriptor, defaultValueContext, commandName)
} }
private fun performRefactoringSilently(dialog: JetChangeSignatureDialog) { private fun performRefactoringSilently(dialog: JetChangeSignatureDialog) {
@@ -42,14 +42,8 @@ public class JetChangeSignatureData(
override val baseDeclaration: PsiElement, override val baseDeclaration: PsiElement,
private val descriptorsForSignatureChange: Collection<FunctionDescriptor> private val descriptorsForSignatureChange: Collection<FunctionDescriptor>
) : JetMethodDescriptor { ) : JetMethodDescriptor {
private val parameters: MutableList<JetParameterInfo> private val parameters: List<JetParameterInfo>
override var receiver: JetParameterInfo? override val receiver: JetParameterInfo?
set(value: JetParameterInfo?) {
if (value != null && value !in parameters) {
parameters.add(value)
}
$receiver = value
}
;{ ;{
$receiver = createReceiverInfoIfNeeded() $receiver = createReceiverInfoIfNeeded()
@@ -120,18 +114,6 @@ public class JetChangeSignatureData(
return parameters return parameters
} }
public fun addParameter(parameter: JetParameterInfo) {
parameters.add(parameter)
}
public fun removeParameter(index: Int) {
parameters.remove(index)
}
public fun clearParameters() {
parameters.clear()
}
override fun getName(): String { override fun getName(): String {
if (baseDescriptor is ConstructorDescriptor) { if (baseDescriptor is ConstructorDescriptor) {
return baseDescriptor.getContainingDeclaration().getName().asString() return baseDescriptor.getContainingDeclaration().getName().asString()
@@ -452,9 +452,11 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
} }
String returnTypeText = myReturnTypeCodeFragment != null ? myReturnTypeCodeFragment.getText().trim() : ""; String returnTypeText = myReturnTypeCodeFragment != null ? myReturnTypeCodeFragment.getText().trim() : "";
return new JetChangeInfo(myMethod, getMethodName(), getReturnType(), returnTypeText, JetMethodDescriptor descriptor = myMethod instanceof JetMutableMethodDescriptor
getVisibility(), parameters, myParametersTableModel.getReceiver(), myDefaultValueContext ? ((JetMutableMethodDescriptor) myMethod).getOriginal()
); : myMethod;
return new JetChangeInfo(descriptor, getMethodName(), getReturnType(), returnTypeText,
getVisibility(), parameters, myParametersTableModel.getReceiver(), myDefaultValueContext);
} }
@Override @Override
@@ -138,11 +138,11 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
private static JetChangeSignatureConfiguration emptyConfiguration() { private static JetChangeSignatureConfiguration emptyConfiguration() {
return new JetChangeSignatureConfiguration() { return new JetChangeSignatureConfiguration() {
@NotNull
@Override @Override
public void configure( public JetMethodDescriptor configure(@NotNull JetMethodDescriptor originalDescriptor, @NotNull BindingContext bindingContext) {
@NotNull JetChangeSignatureData changeSignatureData, @NotNull BindingContext bindingContext
) {
//do nothing //do nothing
return originalDescriptor;
} }
@Override @Override
@@ -0,0 +1,47 @@
/*
* 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.refactoring.changeSignature
import org.jetbrains.kotlin.descriptors.Visibility
public class JetMutableMethodDescriptor(val original: JetMethodDescriptor): JetMethodDescriptor by original {
private val parameters: MutableList<JetParameterInfo> = original.getParameters()
override var receiver: JetParameterInfo? = original.receiver
set(value: JetParameterInfo?) {
if (value != null && value !in parameters) {
parameters.add(value)
}
$receiver = value
}
public fun addParameter(parameter: JetParameterInfo) {
parameters.add(parameter)
}
public fun removeParameter(index: Int) {
parameters.remove(index)
}
public fun clearParameters() {
parameters.clear()
}
override fun getVisibility(): Visibility? {
return original.getVisibility()
}
}
@@ -227,14 +227,14 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
JetChangeInfo changeInfo = getChangeInfo(); JetChangeInfo changeInfo = getChangeInfo();
JetElement method = (JetElement) changeInfo.getMethod(); JetElement method = (JetElement) changeInfo.getMethod();
JetChangeSignatureConfiguration empty = new JetChangeSignatureConfiguration() { JetChangeSignatureConfiguration empty = new JetChangeSignatureConfiguration() {
@NotNull
@Override @Override
public void configure( public JetMethodDescriptor configure(@NotNull JetMethodDescriptor originalDescriptor, @NotNull BindingContext bindingContext) {
JetChangeSignatureData data, BindingContext bindingContext return originalDescriptor;
) {
} }
@Override @Override
public boolean performSilently(Collection<? extends PsiElement> elements) { public boolean performSilently(@NotNull Collection<? extends PsiElement> elements) {
return true; return true;
} }
}; };