J2K: JetCallableDefinitionUsage

This commit is contained in:
Alexey Sedunov
2015-11-02 17:33:51 +03:00
parent b1ec5c0672
commit a7e4f73c82
5 changed files with 229 additions and 331 deletions
@@ -255,16 +255,16 @@ public open class JetChangeInfo(
&& getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor) && getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor)
} }
public fun getNewParametersSignature(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String { public fun getNewParametersSignature(inheritedCallable: JetCallableDefinitionUsage<*>): String {
return "(" + getNewParametersSignatureWithoutParentheses(inheritedCallable) + ")" return "(" + getNewParametersSignatureWithoutParentheses(inheritedCallable) + ")"
} }
public fun getNewParametersSignatureWithoutParentheses( public fun getNewParametersSignatureWithoutParentheses(
inheritedCallable: JetCallableDefinitionUsage<PsiElement> inheritedCallable: JetCallableDefinitionUsage<*>
): String { ): String {
val signatureParameters = getNonReceiverParameters() val signatureParameters = getNonReceiverParameters()
val isLambda = inheritedCallable.getDeclaration() is KtFunctionLiteral val isLambda = inheritedCallable.declaration is KtFunctionLiteral
if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedCallable)) { if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedCallable)) {
return signatureParameters.get(0).getDeclarationSignature(0, inheritedCallable) return signatureParameters.get(0).getDeclarationSignature(0, inheritedCallable)
} }
@@ -274,16 +274,16 @@ public open class JetChangeInfo(
.joinToString(separator = ", ") .joinToString(separator = ", ")
} }
public fun renderReceiverType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String? { public fun renderReceiverType(inheritedCallable: JetCallableDefinitionUsage<*>): String? {
val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return receiverTypeText val typeSubstitutor = inheritedCallable.typeSubstitutor ?: return receiverTypeText
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return receiverTypeText val currentBaseFunction = inheritedCallable.baseFunction.currentCallableDescriptor ?: return receiverTypeText
return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false) return currentBaseFunction.extensionReceiverParameter!!.type.renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
} }
public fun renderReturnType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String { public fun renderReturnType(inheritedCallable: JetCallableDefinitionUsage<*>): String {
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return newReturnTypeText val typeSubstitutor = inheritedCallable.typeSubstitutor ?: return newReturnTypeText
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return newReturnTypeText val currentBaseFunction = inheritedCallable.baseFunction.currentCallableDescriptor ?: return newReturnTypeText
return currentBaseFunction.getReturnType()!!.renderTypeWithSubstitution(typeSubstitutor, newReturnTypeText, false) return currentBaseFunction.getReturnType()!!.renderTypeWithSubstitution(typeSubstitutor, newReturnTypeText, false)
} }
@@ -101,12 +101,12 @@ public class JetChangeSignatureData(
} }
override val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement> by lazy { override val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement> by lazy {
primaryCallables.first { it.getDeclaration() == baseDeclaration } primaryCallables.first { it.declaration == baseDeclaration }
} }
override val affectedCallables: Collection<UsageInfo> by lazy { override val affectedCallables: Collection<UsageInfo> by lazy {
primaryCallables + primaryCallables.flatMapTo(HashSet<UsageInfo>()) { primaryFunction -> primaryCallables + primaryCallables.flatMapTo(HashSet<UsageInfo>()) { primaryFunction ->
val primaryDeclaration = primaryFunction.getDeclaration() as? KtCallableDeclaration val primaryDeclaration = primaryFunction.declaration as? KtCallableDeclaration
val lightMethods = primaryDeclaration?.toLightMethods() ?: Collections.emptyList() val lightMethods = primaryDeclaration?.toLightMethods() ?: Collections.emptyList()
lightMethods.flatMap { baseMethod -> lightMethods.flatMap { baseMethod ->
OverridingMethodsSearch OverridingMethodsSearch
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.refactoring.changeSignature package org.jetbrains.kotlin.idea.refactoring.changeSignature
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference import com.intellij.psi.PsiReference
import com.intellij.refactoring.changeSignature.ParameterInfo import com.intellij.refactoring.changeSignature.ParameterInfo
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -152,19 +151,19 @@ public class JetParameterInfo @JvmOverloads constructor (
} }
public fun renderType(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String { public fun renderType(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String {
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return currentTypeText val typeSubstitutor = inheritedCallable.typeSubstitutor ?: return currentTypeText
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return currentTypeText val currentBaseFunction = inheritedCallable.baseFunction.currentCallableDescriptor ?: return currentTypeText
val parameterType = currentBaseFunction.getValueParameters().get(parameterIndex).getType() val parameterType = currentBaseFunction.getValueParameters().get(parameterIndex).getType()
return parameterType.renderTypeWithSubstitution(typeSubstitutor, currentTypeText, true) return parameterType.renderTypeWithSubstitution(typeSubstitutor, currentTypeText, true)
} }
public fun getInheritedName(inheritedCallable: JetCallableDefinitionUsage<*>): String { public fun getInheritedName(inheritedCallable: JetCallableDefinitionUsage<*>): String {
if (!inheritedCallable.isInherited()) return name if (!inheritedCallable.isInherited) return name
val baseFunction = inheritedCallable.getBaseFunction() val baseFunction = inheritedCallable.baseFunction
val baseFunctionDescriptor = baseFunction.getOriginalCallableDescriptor() val baseFunctionDescriptor = baseFunction.originalCallableDescriptor
val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor() val inheritedFunctionDescriptor = inheritedCallable.originalCallableDescriptor
val inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters() val inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters()
if (originalIndex < 0 if (originalIndex < 0
|| originalIndex >= baseFunctionDescriptor.getValueParameters().size() || originalIndex >= baseFunctionDescriptor.getValueParameters().size()
@@ -179,18 +178,18 @@ public class JetParameterInfo @JvmOverloads constructor (
} }
} }
public fun requiresExplicitType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): Boolean { public fun requiresExplicitType(inheritedCallable: JetCallableDefinitionUsage<*>): Boolean {
val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor() val inheritedFunctionDescriptor = inheritedCallable.originalCallableDescriptor
if (inheritedFunctionDescriptor !is AnonymousFunctionDescriptor) return true if (inheritedFunctionDescriptor !is AnonymousFunctionDescriptor) return true
if (originalIndex < 0) return !inheritedCallable.hasExpectedType() if (originalIndex < 0) return !inheritedCallable.hasExpectedType
val inheritedParameterDescriptor = inheritedFunctionDescriptor.getValueParameters().get(originalIndex) val inheritedParameterDescriptor = inheritedFunctionDescriptor.getValueParameters().get(originalIndex)
val parameter = DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor) as? KtParameter ?: return false val parameter = DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor) as? KtParameter ?: return false
return parameter.getTypeReference() != null return parameter.getTypeReference() != null
} }
public fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String { public fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String {
val buffer = StringBuilder() val buffer = StringBuilder()
if (modifierList != null) { if (modifierList != null) {
@@ -207,7 +206,7 @@ public class JetParameterInfo @JvmOverloads constructor (
buffer.append(": ").append(renderType(parameterIndex, inheritedCallable)) buffer.append(": ").append(renderType(parameterIndex, inheritedCallable))
} }
if (!inheritedCallable.isInherited()) { if (!inheritedCallable.isInherited) {
defaultValueForParameter?.let { buffer.append(" = ").append(it.getText()) } defaultValueForParameter?.let { buffer.append(" = ").append(it.getText()) }
} }
@@ -68,8 +68,8 @@ fun getCallableSubstitutor(
baseFunction: JetCallableDefinitionUsage<*>, baseFunction: JetCallableDefinitionUsage<*>,
derivedCallable: JetCallableDefinitionUsage<*> derivedCallable: JetCallableDefinitionUsage<*>
): TypeSubstitutor? { ): TypeSubstitutor? {
val currentBaseFunction = baseFunction.getCurrentCallableDescriptor() ?: return null val currentBaseFunction = baseFunction.currentCallableDescriptor ?: return null
val currentDerivedFunction = derivedCallable.getCurrentCallableDescriptor() ?: return null val currentDerivedFunction = derivedCallable.currentCallableDescriptor ?: return null
return getCallableSubstitutor(currentBaseFunction, currentDerivedFunction) return getCallableSubstitutor(currentBaseFunction, currentDerivedFunction)
} }
@@ -14,380 +14,279 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages; package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages
import com.intellij.psi.PsiComment; import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil
import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageInfo
import kotlin.CollectionsKt; import org.jetbrains.kotlin.descriptors.CallableDescriptor
import kotlin.Pair; import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.idea.core.refactoring.createPrimaryConstructorIfAbsent
import org.jetbrains.kotlin.idea.caches.resolve.JavaResolutionUtils; import org.jetbrains.kotlin.idea.core.setVisibility
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; import org.jetbrains.kotlin.idea.core.toKeywordToken
import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenWaitingSetKt; import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
import org.jetbrains.kotlin.idea.core.DescriptorUtilsKt; import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
import org.jetbrains.kotlin.idea.core.PsiModificationUtilsKt; import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetValVar
import org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignatureUtilsKt; import org.jetbrains.kotlin.idea.refactoring.changeSignature.getCallableSubstitutor
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo; import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo; import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetValVar; import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.util.ShortenReferences; import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options; import org.jetbrains.kotlin.psi.psiUtil.getValueParameterList
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken; import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersKt; import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode; import org.jetbrains.kotlin.utils.sure
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeSubstitutor;
import org.jetbrains.kotlin.types.substitutions.SubstitutionUtilsKt;
import java.util.List; class JetCallableDefinitionUsage<T : PsiElement>(
function: T,
val originalCallableDescriptor: CallableDescriptor,
baseFunction: JetCallableDefinitionUsage<PsiElement>?,
private val samCallType: KotlinType?
) : JetUsageInfo<T>(function) {
val baseFunction: JetCallableDefinitionUsage<*> = baseFunction ?: this
import static org.jetbrains.kotlin.idea.core.refactoring.JetRefactoringUtilKt.createPrimaryConstructorIfAbsent; val hasExpectedType: Boolean = checkIfHasExpectedType(originalCallableDescriptor, isInherited)
public class JetCallableDefinitionUsage<T extends PsiElement> extends JetUsageInfo<T> { val currentCallableDescriptor: CallableDescriptor? by lazy {
@NotNull val element = declaration
private final CallableDescriptor originalCallableDescriptor; when (element) {
is KtFunction, is KtProperty, is KtParameter -> (element as KtDeclaration).resolveToDescriptor() as CallableDescriptor
private CallableDescriptor currentCallableDescriptor; is KtClass -> (element.resolveToDescriptor() as ClassDescriptor).unsubstitutedPrimaryConstructor
is PsiMethod -> element.getJavaMethodDescriptor()
@NotNull else -> null
private final JetCallableDefinitionUsage<? extends PsiElement> baseFunction;
private final boolean hasExpectedType;
@Nullable
private final KotlinType samCallType;
@Nullable
private TypeSubstitutor typeSubstitutor;
public JetCallableDefinitionUsage(
@NotNull T function,
@NotNull CallableDescriptor originalCallableDescriptor,
@Nullable JetCallableDefinitionUsage<PsiElement> baseFunction,
@Nullable KotlinType samCallType
) {
super(function);
this.originalCallableDescriptor = originalCallableDescriptor;
this.baseFunction = baseFunction != null ? baseFunction : this;
this.hasExpectedType = checkIfHasExpectedType(originalCallableDescriptor, isInherited());
this.samCallType = samCallType;
}
private static boolean checkIfHasExpectedType(@NotNull CallableDescriptor callableDescriptor, boolean isInherited) {
if (!(callableDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false;
KtFunctionLiteral functionLiteral =
(KtFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor);
assert functionLiteral != null : "No declaration found for " + callableDescriptor;
PsiElement parent = functionLiteral.getParent();
if (!(parent instanceof KtFunctionLiteralExpression)) return false;
KtFunctionLiteralExpression expression = (KtFunctionLiteralExpression) parent;
return ResolutionUtils.analyze(expression, BodyResolveMode.PARTIAL).get(BindingContext.EXPECTED_EXPRESSION_TYPE, expression) != null;
}
@NotNull
public JetCallableDefinitionUsage<?> getBaseFunction() {
return baseFunction;
}
@NotNull
public PsiElement getDeclaration() {
//noinspection ConstantConditions
return getElement();
}
@Nullable
public TypeSubstitutor getOrCreateTypeSubstitutor() {
if (!isInherited()) return null;
if (typeSubstitutor == null) {
if (samCallType == null) {
typeSubstitutor = ChangeSignatureUtilsKt.getCallableSubstitutor(baseFunction, this);
}
else {
DeclarationDescriptor currentBaseDescriptor = baseFunction.getCurrentCallableDescriptor();
DeclarationDescriptor classDescriptor = currentBaseDescriptor != null
? currentBaseDescriptor.getContainingDeclaration()
: null;
if (!(classDescriptor instanceof ClassDescriptor)) return null;
typeSubstitutor = SubstitutionUtilsKt.getTypeSubstitutor(
((ClassDescriptor) classDescriptor).getDefaultType(),
samCallType
);
}
} }
return typeSubstitutor;
} }
public final boolean isInherited() { val typeSubstitutor: TypeSubstitutor? by lazy {
return baseFunction != this; if (!isInherited) return@lazy null
}
public boolean hasExpectedType() { if (samCallType == null) {
return hasExpectedType; getCallableSubstitutor(this.baseFunction, this)
}
@NotNull
public final CallableDescriptor getOriginalCallableDescriptor() {
return originalCallableDescriptor;
}
@Nullable
public final CallableDescriptor getCurrentCallableDescriptor() {
if (currentCallableDescriptor == null) {
PsiElement element = getDeclaration();
if (element instanceof KtFunction || element instanceof KtProperty || element instanceof KtParameter) {
currentCallableDescriptor = (CallableDescriptor) ResolutionUtils.resolveToDescriptor((KtDeclaration) element);
}
else if (element instanceof KtClass) {
currentCallableDescriptor = ((ClassDescriptor) ResolutionUtils.resolveToDescriptor((KtClass) element)).getUnsubstitutedPrimaryConstructor();
}
else if (element instanceof PsiMethod) {
currentCallableDescriptor = JavaResolutionUtils.getJavaMethodDescriptor((PsiMethod) element);
}
}
return currentCallableDescriptor;
}
@Override
public boolean processUsage(@NotNull JetChangeInfo changeInfo, @NotNull T element, @NotNull UsageInfo[] allUsages) {
if (!(element instanceof KtNamedDeclaration)) return true;
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(element.getProject());
if (changeInfo.isNameChanged()) {
PsiElement identifier = ((KtCallableDeclaration) element).getNameIdentifier();
if (identifier != null) {
identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName()));
}
}
changeReturnTypeIfNeeded(changeInfo, element);
KtParameterList parameterList = KtPsiUtilKt.getValueParameterList((KtNamedDeclaration) element);
if (changeInfo.isParameterSetOrOrderChanged()) {
processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory);
}
else if (parameterList != null) {
int paramIndex = originalCallableDescriptor.getExtensionReceiverParameter() != null ? 1 : 0;
for (KtParameter parameter : parameterList.getParameters()) {
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex];
changeParameter(paramIndex, parameter, parameterInfo);
paramIndex++;
}
ShortenWaitingSetKt.addToShorteningWaitSet(parameterList, Options.DEFAULT);
}
if (element instanceof KtCallableDeclaration && changeInfo.isReceiverTypeChanged()) {
//noinspection unchecked
String receiverTypeText = changeInfo.renderReceiverType((JetCallableDefinitionUsage<PsiElement>) this);
KtTypeReference receiverTypeRef = receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null;
KtTypeReference newReceiverTypeRef = TypeRefHelpersKt
.setReceiverTypeReference((KtCallableDeclaration) element, receiverTypeRef);
if (newReceiverTypeRef != null) {
ShortenWaitingSetKt.addToShorteningWaitSet(newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
}
}
if (changeInfo.isVisibilityChanged() && !KtPsiUtil.isLocal((KtDeclaration) element)) {
changeVisibility(changeInfo, element);
}
return true;
}
protected void changeReturnTypeIfNeeded(JetChangeInfo changeInfo, PsiElement element) {
if (!(element instanceof KtCallableDeclaration)) return;
if (element instanceof KtConstructor) return;
KtCallableDeclaration callable = (KtCallableDeclaration) element;
boolean returnTypeIsNeeded;
if (element instanceof KtFunction) {
returnTypeIsNeeded = !(callable instanceof KtFunctionLiteral)
&& (changeInfo.isRefactoringTarget(originalCallableDescriptor) || callable.getTypeReference() != null);
} }
else { else {
returnTypeIsNeeded = element instanceof KtProperty || element instanceof KtParameter; val currentBaseDescriptor = this.baseFunction.currentCallableDescriptor
val classDescriptor = currentBaseDescriptor?.containingDeclaration as? ClassDescriptor ?: return@lazy null
getTypeSubstitutor(classDescriptor.defaultType, samCallType)
}
}
private fun checkIfHasExpectedType(callableDescriptor: CallableDescriptor, isInherited: Boolean): Boolean {
if (!(callableDescriptor is AnonymousFunctionDescriptor && isInherited)) return false
val functionLiteral = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor) as KtFunctionLiteral?
assert(functionLiteral != null) { "No declaration found for " + callableDescriptor }
val parent = functionLiteral!!.parent as? KtFunctionLiteralExpression ?: return false
return parent.analyze(BodyResolveMode.PARTIAL)[BindingContext.EXPECTED_EXPRESSION_TYPE, parent] != null
}
val declaration: PsiElement
get() = element!!
val isInherited: Boolean
get() = baseFunction !== this
override fun processUsage(changeInfo: JetChangeInfo, element: T, allUsages: Array<out UsageInfo>): Boolean {
if (element !is KtNamedDeclaration) return true
val psiFactory = KtPsiFactory(element.project)
if (changeInfo.isNameChanged) {
val identifier = (element as KtCallableDeclaration).nameIdentifier
identifier?.replace(psiFactory.createIdentifier(changeInfo.newName))
} }
if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) { changeReturnTypeIfNeeded(changeInfo, element)
callable.setTypeReference(null);
String returnTypeText = changeInfo.renderReturnType((JetCallableDefinitionUsage<PsiElement>) this); val parameterList = element.getValueParameterList()
if (changeInfo.isParameterSetOrOrderChanged) {
processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory)
}
else if (parameterList != null) {
var paramIndex = if (originalCallableDescriptor.extensionReceiverParameter != null) 1 else 0
for (parameter in parameterList.parameters) {
val parameterInfo = changeInfo.newParameters[paramIndex]
changeParameter(paramIndex, parameter, parameterInfo)
paramIndex++
}
parameterList.addToShorteningWaitSet(Options.DEFAULT)
}
if (element is KtCallableDeclaration && changeInfo.isReceiverTypeChanged()) {
val receiverTypeText = changeInfo.renderReceiverType(this)
val receiverTypeRef = if (receiverTypeText != null) psiFactory.createType(receiverTypeText) else null
val newReceiverTypeRef = element.setReceiverTypeReference(receiverTypeRef)
newReceiverTypeRef?.addToShorteningWaitSet(ShortenReferences.Options.DEFAULT)
}
if (changeInfo.isVisibilityChanged() && !KtPsiUtil.isLocal(element as KtDeclaration)) {
changeVisibility(changeInfo, element)
}
return true
}
protected fun changeReturnTypeIfNeeded(changeInfo: JetChangeInfo, element: PsiElement) {
if (element !is KtCallableDeclaration) return
if (element is KtConstructor<*>) return
val returnTypeIsNeeded = if (element is KtFunction) {
element !is KtFunctionLiteral && (changeInfo.isRefactoringTarget(originalCallableDescriptor) || element.typeReference != null)
}
else {
element is KtProperty || element is KtParameter
}
if (changeInfo.isReturnTypeChanged && returnTypeIsNeeded) {
element.setTypeReference(null)
val returnTypeText = changeInfo.renderReturnType(this)
//TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready //TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready
if (!(returnTypeText.equals("Unit") || returnTypeText.equals("kotlin.Unit"))) { if (!(returnTypeText == "Unit" || returnTypeText == "kotlin.Unit")) {
ShortenWaitingSetKt.addToShorteningWaitSet( element.setTypeReference(KtPsiFactory(element).createType(returnTypeText))!!.addToShorteningWaitSet(
callable.setTypeReference(KtPsiFactoryKt.KtPsiFactory(callable).createType(returnTypeText)), Options.DEFAULT)
Options.DEFAULT
);
} }
} }
} }
private void processParameterListWithStructuralChanges( private fun processParameterListWithStructuralChanges(
JetChangeInfo changeInfo, changeInfo: JetChangeInfo,
PsiElement element, element: PsiElement,
KtParameterList parameterList, originalParameterList: KtParameterList?,
KtPsiFactory psiFactory psiFactory: KtPsiFactory) {
) { var parameterList = originalParameterList
int parametersCount = changeInfo.getNonReceiverParametersCount(); val parametersCount = changeInfo.getNonReceiverParametersCount()
boolean isLambda = element instanceof KtFunctionLiteral; val isLambda = element is KtFunctionLiteral
boolean canReplaceEntireList = false; var canReplaceEntireList = false
KtParameterList newParameterList = null; var newParameterList: KtParameterList? = null
if (isLambda) { if (isLambda) {
if (parametersCount == 0) { if (parametersCount == 0) {
if (parameterList != null) { if (parameterList != null) {
parameterList.delete(); parameterList.delete()
PsiElement arrow = ((KtFunctionLiteral)element).getArrow(); val arrow = (element as KtFunctionLiteral).arrow
if (arrow != null) { arrow?.delete()
arrow.delete(); parameterList = null
}
parameterList = null;
} }
} }
else { else {
newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignatureWithoutParentheses( newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignatureWithoutParentheses(this))
(JetCallableDefinitionUsage<PsiElement>) this) canReplaceEntireList = true
);
canReplaceEntireList = true;
} }
} }
else if (!(element instanceof KtProperty || element instanceof KtParameter)) { else if (!(element is KtProperty || element is KtParameter)) {
newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature( newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature(this))
(JetCallableDefinitionUsage<PsiElement>) this)
);
} }
if (newParameterList == null) return; if (newParameterList == null) return
if (parameterList != null) { if (parameterList != null) {
if (canReplaceEntireList) { if (canReplaceEntireList) {
newParameterList = (KtParameterList) parameterList.replace(newParameterList); newParameterList = parameterList.replace(newParameterList) as KtParameterList
} }
else { else {
newParameterList = replaceParameterListAndKeepDelimiters(parameterList, newParameterList); newParameterList = replaceParameterListAndKeepDelimiters(parameterList, newParameterList)
} }
} }
else { else {
if (element instanceof KtClass) { if (element is KtClass) {
KtPrimaryConstructor constructor = createPrimaryConstructorIfAbsent((KtClass) element); val constructor = element.createPrimaryConstructorIfAbsent()
KtParameterList oldParameterList = constructor.getValueParameterList(); val oldParameterList = constructor.valueParameterList.sure { "primary constructor from factory has parameter list" }
assert oldParameterList != null : "primary constructor from factory has parameter list"; newParameterList = oldParameterList.replace(newParameterList) as KtParameterList
newParameterList = (KtParameterList) oldParameterList.replace(newParameterList);
} }
else if (isLambda) { else if (isLambda) {
//noinspection ConstantConditions val functionLiteral = element as KtFunctionLiteral
KtFunctionLiteral functionLiteral = (KtFunctionLiteral) element; val anchor = functionLiteral.lBrace
PsiElement anchor = functionLiteral.getLBrace(); newParameterList = element.addAfter(newParameterList, anchor) as KtParameterList
newParameterList = (KtParameterList) element.addAfter(newParameterList, anchor); if (functionLiteral.arrow == null) {
if (functionLiteral.getArrow() == null) { val whitespaceAndArrow = psiFactory.createWhitespaceAndArrow()
Pair<PsiElement, PsiElement> whitespaceAndArrow = psiFactory.createWhitespaceAndArrow(); element.addRangeAfter(whitespaceAndArrow.first, whitespaceAndArrow.second, newParameterList)
element.addRangeAfter(whitespaceAndArrow.getFirst(), whitespaceAndArrow.getSecond(), newParameterList);
} }
} }
} }
if (newParameterList != null) { newParameterList.addToShorteningWaitSet(Options.DEFAULT)
ShortenWaitingSetKt.addToShorteningWaitSet(newParameterList, Options.DEFAULT);
}
} }
private static KtParameterList replaceParameterListAndKeepDelimiters(KtParameterList parameterList, KtParameterList newParameterList) { private fun replaceParameterListAndKeepDelimiters(parameterList: KtParameterList, newParameterList: KtParameterList): KtParameterList {
List<KtParameter> oldParameters = parameterList.getParameters(); val oldParameters = parameterList.parameters
List<KtParameter> newParameters = newParameterList.getParameters(); val newParameters = newParameterList.parameters
int oldCount = oldParameters.size(); val oldCount = oldParameters.size
int newCount = newParameters.size(); val newCount = newParameters.size
int commonCount = Math.min(oldCount, newCount); val commonCount = Math.min(oldCount, newCount)
for (int i = 0; i < commonCount; i++) { for (i in 0..commonCount - 1) {
oldParameters.set(i, (KtParameter) oldParameters.get(i).replace(newParameters.get(i))); oldParameters[i] = oldParameters[i].replace(newParameters[i]) as KtParameter
} }
if (commonCount == 0) return (KtParameterList) parameterList.replace(newParameterList); if (commonCount == 0) return parameterList.replace(newParameterList) as KtParameterList
if (oldCount > commonCount) { if (oldCount > commonCount) {
parameterList.deleteChildRange(oldParameters.get(commonCount - 1).getNextSibling(), parameterList.deleteChildRange(oldParameters[commonCount - 1].nextSibling, oldParameters.last())
CollectionsKt.last(oldParameters));
} }
else if (newCount > commonCount) { else if (newCount > commonCount) {
parameterList.addRangeAfter(newParameters.get(commonCount - 1).getNextSibling(), parameterList.addRangeAfter(newParameters[commonCount - 1].nextSibling,
newParameterList.getLastChild().getPrevSibling(), newParameterList.lastChild.prevSibling,
PsiTreeUtil.skipSiblingsBackward(parameterList.getLastChild(), PsiTreeUtil.skipSiblingsBackward(parameterList.lastChild,
PsiWhiteSpace.class, PsiComment.class)); PsiWhiteSpace::class.java, PsiComment::class.java))
} }
return parameterList; return parameterList
} }
private static void changeVisibility(JetChangeInfo changeInfo, PsiElement element) { private fun changeVisibility(changeInfo: JetChangeInfo, element: PsiElement) {
KtModifierKeywordToken newVisibilityToken = DescriptorUtilsKt.toKeywordToken(changeInfo.getNewVisibility()); val newVisibilityToken = changeInfo.newVisibility.toKeywordToken()
when (element) {
if (element instanceof KtCallableDeclaration) { is KtCallableDeclaration -> element.setVisibility(newVisibilityToken)
PsiModificationUtilsKt.setVisibility((KtCallableDeclaration)element, newVisibilityToken); is KtClass -> element.createPrimaryConstructorIfAbsent().setVisibility(newVisibilityToken)
else -> throw AssertionError("Invalid element: " + element.getElementTextWithContext())
} }
else if (element instanceof KtClass) {
PsiModificationUtilsKt.setVisibility(createPrimaryConstructorIfAbsent((KtClass) element), newVisibilityToken);
}
else throw new AssertionError("Invalid element: " + PsiUtilsKt.getElementTextWithContext(element));
} }
private void changeParameter(int parameterIndex, KtParameter parameter, JetParameterInfo parameterInfo) { private fun changeParameter(parameterIndex: Int, parameter: KtParameter, parameterInfo: JetParameterInfo) {
PsiElement valOrVarKeyword = parameter.getValOrVarKeyword(); val valOrVarKeyword = parameter.valOrVarKeyword
JetValVar valOrVar = parameterInfo.getValOrVar(); val valOrVar = parameterInfo.valOrVar
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(getProject()); val psiFactory = KtPsiFactory(project)
val newKeyword = valOrVar.createKeyword(psiFactory)
if (valOrVarKeyword != null) { if (valOrVarKeyword != null) {
PsiElement newKeyword = valOrVar.createKeyword(psiFactory);
if (newKeyword != null) { if (newKeyword != null) {
valOrVarKeyword.replace(newKeyword); valOrVarKeyword.replace(newKeyword)
} }
else { else {
valOrVarKeyword.delete(); valOrVarKeyword.delete()
} }
} }
else if (valOrVar != JetValVar.None) { else if (valOrVar != JetValVar.None && newKeyword != null) {
PsiElement firstChild = parameter.getFirstChild(); val firstChild = parameter.firstChild
//noinspection ConstantConditions parameter.addBefore(newKeyword, firstChild)
parameter.addBefore(valOrVar.createKeyword(psiFactory), firstChild); parameter.addBefore(psiFactory.createWhiteSpace(), firstChild)
parameter.addBefore(psiFactory.createWhiteSpace(), firstChild);
} }
if (parameterInfo.isTypeChanged() && parameter.getTypeReference() != null) { if (parameterInfo.isTypeChanged && parameter.typeReference != null) {
String renderedType = parameterInfo.renderType(parameterIndex, this); val renderedType = parameterInfo.renderType(parameterIndex, this)
parameter.setTypeReference(psiFactory.createType(renderedType)); parameter.setTypeReference(psiFactory.createType(renderedType))
} }
PsiElement identifier = parameter.getNameIdentifier(); val newIdentifier = psiFactory.createIdentifier(parameterInfo.getInheritedName(this))
parameter.nameIdentifier?.replace(newIdentifier)
if (identifier != null) {
//noinspection unchecked
String newName = parameterInfo.getInheritedName(this);
identifier.replace(psiFactory.createIdentifier(newName));
}
} }
} }