J2K: JetCallableDefinitionUsage
This commit is contained in:
@@ -255,16 +255,16 @@ public open class JetChangeInfo(
|
||||
&& getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor)
|
||||
}
|
||||
|
||||
public fun getNewParametersSignature(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
|
||||
public fun getNewParametersSignature(inheritedCallable: JetCallableDefinitionUsage<*>): String {
|
||||
return "(" + getNewParametersSignatureWithoutParentheses(inheritedCallable) + ")"
|
||||
}
|
||||
|
||||
public fun getNewParametersSignatureWithoutParentheses(
|
||||
inheritedCallable: JetCallableDefinitionUsage<PsiElement>
|
||||
inheritedCallable: JetCallableDefinitionUsage<*>
|
||||
): String {
|
||||
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)) {
|
||||
return signatureParameters.get(0).getDeclarationSignature(0, inheritedCallable)
|
||||
}
|
||||
@@ -274,16 +274,16 @@ public open class JetChangeInfo(
|
||||
.joinToString(separator = ", ")
|
||||
}
|
||||
|
||||
public fun renderReceiverType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String? {
|
||||
public fun renderReceiverType(inheritedCallable: JetCallableDefinitionUsage<*>): String? {
|
||||
val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null
|
||||
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return receiverTypeText
|
||||
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return receiverTypeText
|
||||
return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
|
||||
val typeSubstitutor = inheritedCallable.typeSubstitutor ?: return receiverTypeText
|
||||
val currentBaseFunction = inheritedCallable.baseFunction.currentCallableDescriptor ?: return receiverTypeText
|
||||
return currentBaseFunction.extensionReceiverParameter!!.type.renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
|
||||
}
|
||||
|
||||
public fun renderReturnType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
|
||||
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
|
||||
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return newReturnTypeText
|
||||
public fun renderReturnType(inheritedCallable: JetCallableDefinitionUsage<*>): String {
|
||||
val typeSubstitutor = inheritedCallable.typeSubstitutor ?: return newReturnTypeText
|
||||
val currentBaseFunction = inheritedCallable.baseFunction.currentCallableDescriptor ?: return newReturnTypeText
|
||||
return currentBaseFunction.getReturnType()!!.renderTypeWithSubstitution(typeSubstitutor, newReturnTypeText, false)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -101,12 +101,12 @@ public class JetChangeSignatureData(
|
||||
}
|
||||
|
||||
override val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement> by lazy {
|
||||
primaryCallables.first { it.getDeclaration() == baseDeclaration }
|
||||
primaryCallables.first { it.declaration == baseDeclaration }
|
||||
}
|
||||
|
||||
override val affectedCallables: Collection<UsageInfo> by lazy {
|
||||
primaryCallables + primaryCallables.flatMapTo(HashSet<UsageInfo>()) { primaryFunction ->
|
||||
val primaryDeclaration = primaryFunction.getDeclaration() as? KtCallableDeclaration
|
||||
val primaryDeclaration = primaryFunction.declaration as? KtCallableDeclaration
|
||||
val lightMethods = primaryDeclaration?.toLightMethods() ?: Collections.emptyList()
|
||||
lightMethods.flatMap { baseMethod ->
|
||||
OverridingMethodsSearch
|
||||
|
||||
+11
-12
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.changeSignature
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfo
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -152,19 +151,19 @@ public class JetParameterInfo @JvmOverloads constructor (
|
||||
}
|
||||
|
||||
public fun renderType(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String {
|
||||
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return currentTypeText
|
||||
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return currentTypeText
|
||||
val typeSubstitutor = inheritedCallable.typeSubstitutor ?: return currentTypeText
|
||||
val currentBaseFunction = inheritedCallable.baseFunction.currentCallableDescriptor ?: return currentTypeText
|
||||
val parameterType = currentBaseFunction.getValueParameters().get(parameterIndex).getType()
|
||||
return parameterType.renderTypeWithSubstitution(typeSubstitutor, currentTypeText, true)
|
||||
}
|
||||
|
||||
public fun getInheritedName(inheritedCallable: JetCallableDefinitionUsage<*>): String {
|
||||
if (!inheritedCallable.isInherited()) return name
|
||||
if (!inheritedCallable.isInherited) return name
|
||||
|
||||
val baseFunction = inheritedCallable.getBaseFunction()
|
||||
val baseFunctionDescriptor = baseFunction.getOriginalCallableDescriptor()
|
||||
val baseFunction = inheritedCallable.baseFunction
|
||||
val baseFunctionDescriptor = baseFunction.originalCallableDescriptor
|
||||
|
||||
val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor()
|
||||
val inheritedFunctionDescriptor = inheritedCallable.originalCallableDescriptor
|
||||
val inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters()
|
||||
if (originalIndex < 0
|
||||
|| originalIndex >= baseFunctionDescriptor.getValueParameters().size()
|
||||
@@ -179,18 +178,18 @@ public class JetParameterInfo @JvmOverloads constructor (
|
||||
}
|
||||
}
|
||||
|
||||
public fun requiresExplicitType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): Boolean {
|
||||
val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor()
|
||||
public fun requiresExplicitType(inheritedCallable: JetCallableDefinitionUsage<*>): Boolean {
|
||||
val inheritedFunctionDescriptor = inheritedCallable.originalCallableDescriptor
|
||||
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 parameter = DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor) as? KtParameter ?: return false
|
||||
return parameter.getTypeReference() != null
|
||||
}
|
||||
|
||||
public fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
|
||||
public fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String {
|
||||
val buffer = StringBuilder()
|
||||
|
||||
if (modifierList != null) {
|
||||
@@ -207,7 +206,7 @@ public class JetParameterInfo @JvmOverloads constructor (
|
||||
buffer.append(": ").append(renderType(parameterIndex, inheritedCallable))
|
||||
}
|
||||
|
||||
if (!inheritedCallable.isInherited()) {
|
||||
if (!inheritedCallable.isInherited) {
|
||||
defaultValueForParameter?.let { buffer.append(" = ").append(it.getText()) }
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -68,8 +68,8 @@ fun getCallableSubstitutor(
|
||||
baseFunction: JetCallableDefinitionUsage<*>,
|
||||
derivedCallable: JetCallableDefinitionUsage<*>
|
||||
): TypeSubstitutor? {
|
||||
val currentBaseFunction = baseFunction.getCurrentCallableDescriptor() ?: return null
|
||||
val currentDerivedFunction = derivedCallable.getCurrentCallableDescriptor() ?: return null
|
||||
val currentBaseFunction = baseFunction.currentCallableDescriptor ?: return null
|
||||
val currentDerivedFunction = derivedCallable.currentCallableDescriptor ?: return null
|
||||
return getCallableSubstitutor(currentBaseFunction, currentDerivedFunction)
|
||||
}
|
||||
|
||||
|
||||
+204
-305
@@ -14,380 +14,279 @@
|
||||
* 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.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.JavaResolutionUtils;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenWaitingSetKt;
|
||||
import org.jetbrains.kotlin.idea.core.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.core.PsiModificationUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignatureUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetValVar;
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences;
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options;
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
import org.jetbrains.kotlin.types.substitutions.SubstitutionUtilsKt;
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.createPrimaryConstructorIfAbsent
|
||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||
import org.jetbrains.kotlin.idea.core.toKeywordToken
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetValVar
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.getCallableSubstitutor
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getValueParameterList
|
||||
import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
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> {
|
||||
@NotNull
|
||||
private final CallableDescriptor originalCallableDescriptor;
|
||||
|
||||
private CallableDescriptor currentCallableDescriptor;
|
||||
|
||||
@NotNull
|
||||
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
|
||||
);
|
||||
}
|
||||
val currentCallableDescriptor: CallableDescriptor? by lazy {
|
||||
val element = declaration
|
||||
when (element) {
|
||||
is KtFunction, is KtProperty, is KtParameter -> (element as KtDeclaration).resolveToDescriptor() as CallableDescriptor
|
||||
is KtClass -> (element.resolveToDescriptor() as ClassDescriptor).unsubstitutedPrimaryConstructor
|
||||
is PsiMethod -> element.getJavaMethodDescriptor()
|
||||
else -> null
|
||||
}
|
||||
return typeSubstitutor;
|
||||
}
|
||||
|
||||
public final boolean isInherited() {
|
||||
return baseFunction != this;
|
||||
}
|
||||
val typeSubstitutor: TypeSubstitutor? by lazy {
|
||||
if (!isInherited) return@lazy null
|
||||
|
||||
public boolean hasExpectedType() {
|
||||
return hasExpectedType;
|
||||
}
|
||||
|
||||
@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);
|
||||
if (samCallType == null) {
|
||||
getCallableSubstitutor(this.baseFunction, this)
|
||||
}
|
||||
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) {
|
||||
callable.setTypeReference(null);
|
||||
String returnTypeText = changeInfo.renderReturnType((JetCallableDefinitionUsage<PsiElement>) this);
|
||||
changeReturnTypeIfNeeded(changeInfo, element)
|
||||
|
||||
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
|
||||
if (!(returnTypeText.equals("Unit") || returnTypeText.equals("kotlin.Unit"))) {
|
||||
ShortenWaitingSetKt.addToShorteningWaitSet(
|
||||
callable.setTypeReference(KtPsiFactoryKt.KtPsiFactory(callable).createType(returnTypeText)),
|
||||
Options.DEFAULT
|
||||
);
|
||||
if (!(returnTypeText == "Unit" || returnTypeText == "kotlin.Unit")) {
|
||||
element.setTypeReference(KtPsiFactory(element).createType(returnTypeText))!!.addToShorteningWaitSet(
|
||||
Options.DEFAULT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processParameterListWithStructuralChanges(
|
||||
JetChangeInfo changeInfo,
|
||||
PsiElement element,
|
||||
KtParameterList parameterList,
|
||||
KtPsiFactory psiFactory
|
||||
) {
|
||||
int parametersCount = changeInfo.getNonReceiverParametersCount();
|
||||
boolean isLambda = element instanceof KtFunctionLiteral;
|
||||
boolean canReplaceEntireList = false;
|
||||
private fun processParameterListWithStructuralChanges(
|
||||
changeInfo: JetChangeInfo,
|
||||
element: PsiElement,
|
||||
originalParameterList: KtParameterList?,
|
||||
psiFactory: KtPsiFactory) {
|
||||
var parameterList = originalParameterList
|
||||
val parametersCount = changeInfo.getNonReceiverParametersCount()
|
||||
val isLambda = element is KtFunctionLiteral
|
||||
var canReplaceEntireList = false
|
||||
|
||||
KtParameterList newParameterList = null;
|
||||
var newParameterList: KtParameterList? = null
|
||||
if (isLambda) {
|
||||
if (parametersCount == 0) {
|
||||
if (parameterList != null) {
|
||||
parameterList.delete();
|
||||
PsiElement arrow = ((KtFunctionLiteral)element).getArrow();
|
||||
if (arrow != null) {
|
||||
arrow.delete();
|
||||
}
|
||||
parameterList = null;
|
||||
parameterList.delete()
|
||||
val arrow = (element as KtFunctionLiteral).arrow
|
||||
arrow?.delete()
|
||||
parameterList = null
|
||||
}
|
||||
}
|
||||
else {
|
||||
newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignatureWithoutParentheses(
|
||||
(JetCallableDefinitionUsage<PsiElement>) this)
|
||||
);
|
||||
canReplaceEntireList = true;
|
||||
newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignatureWithoutParentheses(this))
|
||||
canReplaceEntireList = true
|
||||
}
|
||||
}
|
||||
else if (!(element instanceof KtProperty || element instanceof KtParameter)) {
|
||||
newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature(
|
||||
(JetCallableDefinitionUsage<PsiElement>) this)
|
||||
);
|
||||
else if (!(element is KtProperty || element is KtParameter)) {
|
||||
newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature(this))
|
||||
}
|
||||
|
||||
if (newParameterList == null) return;
|
||||
if (newParameterList == null) return
|
||||
|
||||
if (parameterList != null) {
|
||||
if (canReplaceEntireList) {
|
||||
newParameterList = (KtParameterList) parameterList.replace(newParameterList);
|
||||
newParameterList = parameterList.replace(newParameterList) as KtParameterList
|
||||
}
|
||||
else {
|
||||
newParameterList = replaceParameterListAndKeepDelimiters(parameterList, newParameterList);
|
||||
newParameterList = replaceParameterListAndKeepDelimiters(parameterList, newParameterList)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (element instanceof KtClass) {
|
||||
KtPrimaryConstructor constructor = createPrimaryConstructorIfAbsent((KtClass) element);
|
||||
KtParameterList oldParameterList = constructor.getValueParameterList();
|
||||
assert oldParameterList != null : "primary constructor from factory has parameter list";
|
||||
newParameterList = (KtParameterList) oldParameterList.replace(newParameterList);
|
||||
if (element is KtClass) {
|
||||
val constructor = element.createPrimaryConstructorIfAbsent()
|
||||
val oldParameterList = constructor.valueParameterList.sure { "primary constructor from factory has parameter list" }
|
||||
newParameterList = oldParameterList.replace(newParameterList) as KtParameterList
|
||||
}
|
||||
else if (isLambda) {
|
||||
//noinspection ConstantConditions
|
||||
KtFunctionLiteral functionLiteral = (KtFunctionLiteral) element;
|
||||
PsiElement anchor = functionLiteral.getLBrace();
|
||||
newParameterList = (KtParameterList) element.addAfter(newParameterList, anchor);
|
||||
if (functionLiteral.getArrow() == null) {
|
||||
Pair<PsiElement, PsiElement> whitespaceAndArrow = psiFactory.createWhitespaceAndArrow();
|
||||
element.addRangeAfter(whitespaceAndArrow.getFirst(), whitespaceAndArrow.getSecond(), newParameterList);
|
||||
val functionLiteral = element as KtFunctionLiteral
|
||||
val anchor = functionLiteral.lBrace
|
||||
newParameterList = element.addAfter(newParameterList, anchor) as KtParameterList
|
||||
if (functionLiteral.arrow == null) {
|
||||
val whitespaceAndArrow = psiFactory.createWhitespaceAndArrow()
|
||||
element.addRangeAfter(whitespaceAndArrow.first, whitespaceAndArrow.second, newParameterList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newParameterList != null) {
|
||||
ShortenWaitingSetKt.addToShorteningWaitSet(newParameterList, Options.DEFAULT);
|
||||
}
|
||||
newParameterList.addToShorteningWaitSet(Options.DEFAULT)
|
||||
}
|
||||
|
||||
private static KtParameterList replaceParameterListAndKeepDelimiters(KtParameterList parameterList, KtParameterList newParameterList) {
|
||||
List<KtParameter> oldParameters = parameterList.getParameters();
|
||||
List<KtParameter> newParameters = newParameterList.getParameters();
|
||||
int oldCount = oldParameters.size();
|
||||
int newCount = newParameters.size();
|
||||
private fun replaceParameterListAndKeepDelimiters(parameterList: KtParameterList, newParameterList: KtParameterList): KtParameterList {
|
||||
val oldParameters = parameterList.parameters
|
||||
val newParameters = newParameterList.parameters
|
||||
val oldCount = oldParameters.size
|
||||
val newCount = newParameters.size
|
||||
|
||||
int commonCount = Math.min(oldCount, newCount);
|
||||
for (int i = 0; i < commonCount; i++) {
|
||||
oldParameters.set(i, (KtParameter) oldParameters.get(i).replace(newParameters.get(i)));
|
||||
val commonCount = Math.min(oldCount, newCount)
|
||||
for (i in 0..commonCount - 1) {
|
||||
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) {
|
||||
parameterList.deleteChildRange(oldParameters.get(commonCount - 1).getNextSibling(),
|
||||
CollectionsKt.last(oldParameters));
|
||||
parameterList.deleteChildRange(oldParameters[commonCount - 1].nextSibling, oldParameters.last())
|
||||
}
|
||||
else if (newCount > commonCount) {
|
||||
parameterList.addRangeAfter(newParameters.get(commonCount - 1).getNextSibling(),
|
||||
newParameterList.getLastChild().getPrevSibling(),
|
||||
PsiTreeUtil.skipSiblingsBackward(parameterList.getLastChild(),
|
||||
PsiWhiteSpace.class, PsiComment.class));
|
||||
parameterList.addRangeAfter(newParameters[commonCount - 1].nextSibling,
|
||||
newParameterList.lastChild.prevSibling,
|
||||
PsiTreeUtil.skipSiblingsBackward(parameterList.lastChild,
|
||||
PsiWhiteSpace::class.java, PsiComment::class.java))
|
||||
}
|
||||
|
||||
return parameterList;
|
||||
return parameterList
|
||||
}
|
||||
|
||||
private static void changeVisibility(JetChangeInfo changeInfo, PsiElement element) {
|
||||
KtModifierKeywordToken newVisibilityToken = DescriptorUtilsKt.toKeywordToken(changeInfo.getNewVisibility());
|
||||
|
||||
if (element instanceof KtCallableDeclaration) {
|
||||
PsiModificationUtilsKt.setVisibility((KtCallableDeclaration)element, newVisibilityToken);
|
||||
private fun changeVisibility(changeInfo: JetChangeInfo, element: PsiElement) {
|
||||
val newVisibilityToken = changeInfo.newVisibility.toKeywordToken()
|
||||
when (element) {
|
||||
is KtCallableDeclaration -> element.setVisibility(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) {
|
||||
PsiElement valOrVarKeyword = parameter.getValOrVarKeyword();
|
||||
JetValVar valOrVar = parameterInfo.getValOrVar();
|
||||
private fun changeParameter(parameterIndex: Int, parameter: KtParameter, parameterInfo: JetParameterInfo) {
|
||||
val valOrVarKeyword = parameter.valOrVarKeyword
|
||||
val valOrVar = parameterInfo.valOrVar
|
||||
|
||||
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(getProject());
|
||||
val psiFactory = KtPsiFactory(project)
|
||||
val newKeyword = valOrVar.createKeyword(psiFactory)
|
||||
if (valOrVarKeyword != null) {
|
||||
PsiElement newKeyword = valOrVar.createKeyword(psiFactory);
|
||||
if (newKeyword != null) {
|
||||
valOrVarKeyword.replace(newKeyword);
|
||||
valOrVarKeyword.replace(newKeyword)
|
||||
}
|
||||
else {
|
||||
valOrVarKeyword.delete();
|
||||
valOrVarKeyword.delete()
|
||||
}
|
||||
}
|
||||
else if (valOrVar != JetValVar.None) {
|
||||
PsiElement firstChild = parameter.getFirstChild();
|
||||
//noinspection ConstantConditions
|
||||
parameter.addBefore(valOrVar.createKeyword(psiFactory), firstChild);
|
||||
parameter.addBefore(psiFactory.createWhiteSpace(), firstChild);
|
||||
else if (valOrVar != JetValVar.None && newKeyword != null) {
|
||||
val firstChild = parameter.firstChild
|
||||
parameter.addBefore(newKeyword, firstChild)
|
||||
parameter.addBefore(psiFactory.createWhiteSpace(), firstChild)
|
||||
}
|
||||
|
||||
if (parameterInfo.isTypeChanged() && parameter.getTypeReference() != null) {
|
||||
String renderedType = parameterInfo.renderType(parameterIndex, this);
|
||||
parameter.setTypeReference(psiFactory.createType(renderedType));
|
||||
if (parameterInfo.isTypeChanged && parameter.typeReference != null) {
|
||||
val renderedType = parameterInfo.renderType(parameterIndex, this)
|
||||
parameter.setTypeReference(psiFactory.createType(renderedType))
|
||||
}
|
||||
|
||||
PsiElement identifier = parameter.getNameIdentifier();
|
||||
|
||||
if (identifier != null) {
|
||||
//noinspection unchecked
|
||||
String newName = parameterInfo.getInheritedName(this);
|
||||
identifier.replace(psiFactory.createIdentifier(newName));
|
||||
}
|
||||
val newIdentifier = psiFactory.createIdentifier(parameterInfo.getInheritedName(this))
|
||||
parameter.nameIdentifier?.replace(newIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user