J2K: JetCallableDefinitionUsage
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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
|
||||||
|
|||||||
+11
-12
@@ -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()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+204
-305
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user