Change Signature: Support conversion between extension and non-extension functions
This commit is contained in:
@@ -54,3 +54,25 @@ fun setTypeReference(declaration: JetCallableDeclaration, addAfter: PsiElement?,
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun JetCallableDeclaration.setReceiverTypeReference(typeRef: JetTypeReference?): JetTypeReference? {
|
||||
val oldTypeRef = getReceiverTypeReference()
|
||||
if (typeRef != null) {
|
||||
if (oldTypeRef != null) {
|
||||
return oldTypeRef.replace(typeRef) as JetTypeReference
|
||||
}
|
||||
else {
|
||||
val anchor = getNameIdentifier()
|
||||
val newTypeRef = addBefore(typeRef, anchor) as JetTypeReference
|
||||
addAfter(JetPsiFactory(getProject()).createDot(), newTypeRef)
|
||||
return newTypeRef
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (oldTypeRef != null) {
|
||||
val dot = oldTypeRef.siblings(forward = true).firstOrNull { it.getNode().getElementType() == JetTokens.DOT }
|
||||
deleteChildRange(oldTypeRef, dot ?: oldTypeRef)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -17,21 +17,28 @@
|
||||
package org.jetbrains.kotlin.idea.refactoring.changeSignature
|
||||
|
||||
import com.intellij.lang.Language
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.PsiType
|
||||
import com.intellij.refactoring.changeSignature.*
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.Function
|
||||
import com.intellij.util.VisibilityUtil
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import kotlin.Function1
|
||||
import kotlin.Pair
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.psi.JetFunction
|
||||
import org.jetbrains.kotlin.psi.JetFunctionLiteral
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.idea.JetLanguage
|
||||
@@ -40,6 +47,9 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionD
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import java.util.HashMap
|
||||
import kotlin.properties.Delegates
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
public class JetChangeInfo(
|
||||
val methodDescriptor: JetMethodDescriptor,
|
||||
@@ -48,8 +58,17 @@ public class JetChangeInfo(
|
||||
var newReturnTypeText: String,
|
||||
var newVisibility: Visibility,
|
||||
parameterInfos: List<JetParameterInfo>,
|
||||
receiver: JetParameterInfo?,
|
||||
val context: PsiElement
|
||||
): ChangeInfo {
|
||||
var receiverParameterInfo: JetParameterInfo? = receiver
|
||||
set(value: JetParameterInfo?) {
|
||||
if (value != null && value !in newParameters) {
|
||||
newParameters.add(value)
|
||||
}
|
||||
$receiverParameterInfo = value
|
||||
}
|
||||
|
||||
private val newParameters = parameterInfos.toArrayList()
|
||||
private val originalPsiMethod: PsiMethod? = getCurrentPsiMethod()
|
||||
|
||||
@@ -63,8 +82,10 @@ public class JetChangeInfo(
|
||||
}
|
||||
|
||||
public val isParameterSetOrOrderChanged: Boolean by Delegates.lazy {
|
||||
newParameters.size() != methodDescriptor.getParametersCount() ||
|
||||
newParameters.indices.any { i -> newParameters.get(i).getOldIndex() != i }
|
||||
val signatureParameters = getNonReceiverParameters()
|
||||
methodDescriptor.receiver != receiverParameterInfo ||
|
||||
signatureParameters.size() != methodDescriptor.getParametersCount() ||
|
||||
signatureParameters.indices.any { i -> signatureParameters[i].getOldIndex() != i }
|
||||
}
|
||||
|
||||
private var isPrimaryMethodUpdated: Boolean = false
|
||||
@@ -88,6 +109,12 @@ public class JetChangeInfo(
|
||||
|
||||
override fun getNewParameters(): Array<JetParameterInfo> = newParameters.copyToArray()
|
||||
|
||||
fun getNonReceiverParametersCount(): Int = newParameters.size() - (if (receiverParameterInfo != null) 1 else 0)
|
||||
|
||||
fun getNonReceiverParameters(): List<JetParameterInfo> {
|
||||
return receiverParameterInfo?.let { receiver -> newParameters.filter { it != receiver } } ?: newParameters
|
||||
}
|
||||
|
||||
public fun setNewParameter(index: Int, parameterInfo: JetParameterInfo) {
|
||||
newParameters.set(index, parameterInfo)
|
||||
}
|
||||
@@ -97,9 +124,15 @@ public class JetChangeInfo(
|
||||
}
|
||||
|
||||
public fun removeParameter(index: Int) {
|
||||
newParameters.remove(index);
|
||||
val parameterInfo = newParameters.remove(index);
|
||||
if (parameterInfo == receiverParameterInfo) {
|
||||
receiverParameterInfo = null
|
||||
}
|
||||
}
|
||||
|
||||
public fun hasParameter(parameterInfo: JetParameterInfo): Boolean =
|
||||
parameterInfo in newParameters
|
||||
|
||||
override fun isGenerateDelegate(): Boolean = false
|
||||
|
||||
override fun getNewName(): String = name
|
||||
@@ -118,6 +151,8 @@ public class JetChangeInfo(
|
||||
|
||||
override fun isReturnTypeChanged(): Boolean = newReturnTypeText != methodDescriptor.renderOriginalReturnType()
|
||||
|
||||
fun isReceiverTypeChanged(): Boolean = receiverParameterInfo?.getTypeText() != methodDescriptor.renderOriginalReceiverType()
|
||||
|
||||
override fun getLanguage(): Language = JetLanguage.INSTANCE
|
||||
|
||||
public fun getNewSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
||||
@@ -135,9 +170,15 @@ public class JetChangeInfo(
|
||||
buffer.append(newVisibility).append(' ')
|
||||
}
|
||||
|
||||
buffer.append(JetTokens.FUN_KEYWORD).append(' ').append(name)
|
||||
buffer.append(JetTokens.FUN_KEYWORD).append(' ')
|
||||
}
|
||||
|
||||
receiverParameterInfo?.let {
|
||||
buffer.append(it.currentTypeText).append('.')
|
||||
}
|
||||
|
||||
buffer.append(name)
|
||||
|
||||
buffer.append(getNewParametersSignature(inheritedFunction))
|
||||
|
||||
if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && !isConstructor)
|
||||
@@ -152,16 +193,25 @@ public class JetChangeInfo(
|
||||
}
|
||||
|
||||
public fun getNewParametersSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
||||
val signatureParameters = getNonReceiverParameters()
|
||||
|
||||
val isLambda = inheritedFunction.getDeclaration() is JetFunctionLiteral
|
||||
if (isLambda && newParameters.size() == 1 && !newParameters.get(0).requiresExplicitType(inheritedFunction)) {
|
||||
return newParameters.get(0).getDeclarationSignature(0, inheritedFunction)
|
||||
if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedFunction)) {
|
||||
return signatureParameters.get(0).getDeclarationSignature(0, inheritedFunction)
|
||||
}
|
||||
|
||||
return newParameters.indices
|
||||
.map { i -> newParameters[i].getDeclarationSignature(i, inheritedFunction) }
|
||||
return signatureParameters.indices
|
||||
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedFunction) }
|
||||
.joinToString(prefix = "(", separator = ", ", postfix = ")")
|
||||
}
|
||||
|
||||
public fun renderReceiverType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String? {
|
||||
val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null
|
||||
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return receiverTypeText
|
||||
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return receiverTypeText
|
||||
return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
|
||||
}
|
||||
|
||||
public fun renderReturnType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
||||
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
|
||||
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return newReturnTypeText
|
||||
@@ -190,13 +240,24 @@ public class JetChangeInfo(
|
||||
else
|
||||
PsiModifier.PACKAGE_LOCAL
|
||||
|
||||
val newJavaParameters = newParameters.withIndex().map { pair ->
|
||||
val newParameterList = receiverParameterInfo.singletonOrEmptyList() + getNonReceiverParameters()
|
||||
val newJavaParameters = newParameterList.withIndex().map { pair ->
|
||||
val (i, info) = pair
|
||||
|
||||
val type = if (isPrimaryMethodUpdated)
|
||||
currentPsiMethod.getParameterList().getParameters()[i].getType()
|
||||
else
|
||||
PsiType.VOID
|
||||
ParameterInfoImpl(info.getOldIndex(), info.getName(), type, info.defaultValueForCall)
|
||||
|
||||
val oldIndex = info.getOldIndex()
|
||||
val javaOldIndex = when {
|
||||
methodDescriptor.receiver == null -> oldIndex
|
||||
info == methodDescriptor.receiver -> 0
|
||||
oldIndex >= 0 -> oldIndex + 1
|
||||
else -> -1
|
||||
}
|
||||
|
||||
ParameterInfoImpl(javaOldIndex, info.getName(), type, info.defaultValueForCall)
|
||||
}.copyToArray()
|
||||
|
||||
val returnType = if (isPrimaryMethodUpdated) currentPsiMethod.getReturnType() else PsiType.VOID
|
||||
@@ -257,5 +318,6 @@ public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMeth
|
||||
returnTypeText,
|
||||
functionDescriptor.getVisibility(),
|
||||
newParameters,
|
||||
null,
|
||||
method)
|
||||
}
|
||||
}
|
||||
+42
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,10 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionD
|
||||
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.idea.refactoring.CollectingValidator
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.idea.refactoring.JetNameSuggester
|
||||
|
||||
public class JetChangeSignatureData(
|
||||
override val baseDescriptor: FunctionDescriptor,
|
||||
@@ -39,24 +43,49 @@ public class JetChangeSignatureData(
|
||||
private val descriptorsForSignatureChange: Collection<FunctionDescriptor>
|
||||
) : JetMethodDescriptor {
|
||||
private val parameters: MutableList<JetParameterInfo>
|
||||
override var receiver: JetParameterInfo?
|
||||
set(value: JetParameterInfo?) {
|
||||
if (value != null && value !in parameters) {
|
||||
parameters.add(value)
|
||||
}
|
||||
$receiver = value
|
||||
}
|
||||
|
||||
;{
|
||||
$receiver = createReceiverInfoIfNeeded()
|
||||
|
||||
;{
|
||||
val valueParameters = when {
|
||||
baseDeclaration is JetFunction -> baseDeclaration.getValueParameters()
|
||||
baseDeclaration is JetClass -> baseDeclaration.getPrimaryConstructorParameters()
|
||||
else -> null
|
||||
}
|
||||
parameters = baseDescriptor.getValueParameters().mapTo(ArrayList()) { parameterDescriptor ->
|
||||
val jetParameter = valueParameters?.get(parameterDescriptor.getIndex())
|
||||
JetParameterInfo(
|
||||
originalIndex = parameterDescriptor.getIndex(),
|
||||
name = parameterDescriptor.getName().asString(),
|
||||
type = parameterDescriptor.getType(),
|
||||
defaultValueForParameter = jetParameter?.getDefaultValue(),
|
||||
valOrVarNode = jetParameter?.getValOrVarNode(),
|
||||
modifierList = jetParameter?.getModifierList()
|
||||
)
|
||||
}
|
||||
parameters = baseDescriptor.getValueParameters()
|
||||
.mapTo(receiver?.let{ arrayListOf(it) } ?: arrayListOf()) { parameterDescriptor ->
|
||||
val jetParameter = valueParameters?.get(parameterDescriptor.getIndex())
|
||||
JetParameterInfo(
|
||||
originalIndex = parameterDescriptor.getIndex(),
|
||||
name = parameterDescriptor.getName().asString(),
|
||||
type = parameterDescriptor.getType(),
|
||||
defaultValueForParameter = jetParameter?.getDefaultValue(),
|
||||
valOrVarNode = jetParameter?.getValOrVarNode(),
|
||||
modifierList = jetParameter?.getModifierList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createReceiverInfoIfNeeded(): JetParameterInfo? {
|
||||
val function = baseDeclaration as? JetFunction ?: return null
|
||||
val bodyScope = function.getBodyExpression()?.let { it.analyze()[BindingContext.RESOLUTION_SCOPE, it] }
|
||||
val paramNames = baseDescriptor.getValueParameters().map { it.getName().asString() }
|
||||
val validator = bodyScope?.let { bodyScope ->
|
||||
CollectingValidator(paramNames) {
|
||||
val name = Name.identifier(it)
|
||||
bodyScope.getLocalVariable(name) == null && bodyScope.getProperties(name).isEmpty()
|
||||
}
|
||||
} ?: CollectingValidator(paramNames)
|
||||
val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null
|
||||
val receiverName = JetNameSuggester.suggestNames(receiverType, validator, "receiver").first()
|
||||
return JetParameterInfo(name = receiverName, type = receiverType)
|
||||
}
|
||||
|
||||
override val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>> by Delegates.lazy {
|
||||
|
||||
+1
-1
@@ -420,7 +420,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
|
||||
|
||||
String returnTypeText = myReturnTypeCodeFragment != null ? myReturnTypeCodeFragment.getText().trim() : "";
|
||||
return new JetChangeInfo(myMethod, getMethodName(), getReturnType(), returnTypeText,
|
||||
getVisibility(), parameters, myDefaultValueContext
|
||||
getVisibility(), parameters, null, myDefaultValueContext
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+201
-5
@@ -25,31 +25,43 @@ import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.changeSignature.*;
|
||||
import com.intellij.refactoring.rename.ResolveSnapshotProvider;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver;
|
||||
import org.jetbrains.kotlin.idea.refactoring.RefactoringPackage;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
|
||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
|
||||
@@ -79,7 +91,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
}
|
||||
|
||||
private static void findOneMethodUsages(
|
||||
@NotNull JetFunctionDefinitionUsage functionUsageInfo,
|
||||
@NotNull JetFunctionDefinitionUsage<?> functionUsageInfo,
|
||||
JetChangeInfo changeInfo,
|
||||
Set<UsageInfo> result
|
||||
) {
|
||||
@@ -92,7 +104,6 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
PsiElement functionPsi = functionUsageInfo.getElement();
|
||||
if (functionPsi == null) return;
|
||||
|
||||
|
||||
for (PsiReference reference : ReferencesSearch.search(functionPsi, functionPsi.getUseScope())) {
|
||||
PsiElement element = reference.getElement();
|
||||
|
||||
@@ -119,12 +130,14 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
? ((JetFunction) functionPsi).getValueParameters()
|
||||
: ((JetClass) functionPsi).getPrimaryConstructorParameters();
|
||||
|
||||
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
|
||||
|
||||
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
||||
if (parameterInfo.getOldIndex() >= 0 && parameterInfo.getOldIndex() < oldParameters.size()) {
|
||||
JetParameter oldParam = oldParameters.get(parameterInfo.getOldIndex());
|
||||
String oldParamName = oldParam.getName();
|
||||
|
||||
if (oldParamName != null && !oldParamName.equals(parameterInfo.getName())) {
|
||||
if (parameterInfo == newReceiverInfo || (oldParamName != null && !oldParamName.equals(parameterInfo.getName()))) {
|
||||
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
|
||||
PsiElement element = reference.getElement();
|
||||
|
||||
@@ -140,6 +153,10 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
}
|
||||
}
|
||||
|
||||
if (functionPsi instanceof JetFunction && newReceiverInfo != changeInfo.getMethodDescriptor().getReceiver()) {
|
||||
findOriginalReceiversUsages(functionUsageInfo, result, changeInfo);
|
||||
}
|
||||
|
||||
if (functionPsi instanceof JetClass && ((JetClass) functionPsi).isEnum()) {
|
||||
for (JetDeclaration declaration : ((JetClass) functionPsi).getDeclarations()) {
|
||||
if (declaration instanceof JetEnumEntry && ((JetEnumEntry) declaration).getDelegationSpecifierList() == null) {
|
||||
@@ -149,6 +166,90 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
}
|
||||
}
|
||||
|
||||
private static void processInternalReferences(
|
||||
JetFunctionDefinitionUsage functionUsageInfo,
|
||||
JetTreeVisitor<BindingContext> visitor
|
||||
) {
|
||||
JetFunction jetFunction = (JetFunction) functionUsageInfo.getDeclaration();
|
||||
JetExpression body = jetFunction.getBodyExpression();
|
||||
if (body != null) {
|
||||
body.accept(visitor, ResolvePackage.analyze(body));
|
||||
}
|
||||
for (JetParameter parameter : jetFunction.getValueParameters()) {
|
||||
JetExpression defaultValue = parameter.getDefaultValue();
|
||||
if (defaultValue != null) {
|
||||
defaultValue.accept(visitor, ResolvePackage.analyze(defaultValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void findOriginalReceiversUsages(
|
||||
@NotNull final JetFunctionDefinitionUsage<?> functionUsageInfo,
|
||||
@NotNull final Set<UsageInfo> result,
|
||||
@NotNull final JetChangeInfo changeInfo
|
||||
) {
|
||||
final JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
|
||||
final FunctionDescriptor functionDescriptor = functionUsageInfo.getOriginalFunctionDescriptor();
|
||||
processInternalReferences(
|
||||
functionUsageInfo,
|
||||
new JetTreeVisitor<BindingContext>() {
|
||||
private void processExplicitThis(
|
||||
@NotNull JetSimpleNameExpression expression,
|
||||
@NotNull ReceiverParameterDescriptor receiverDescriptor
|
||||
) {
|
||||
if (originalReceiverInfo != null && !changeInfo.hasParameter(originalReceiverInfo)) return;
|
||||
if (!(expression.getParent() instanceof JetThisExpression)) return;
|
||||
|
||||
if (receiverDescriptor == functionDescriptor.getExtensionReceiverParameter()) {
|
||||
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
|
||||
result.add(new JetParameterUsage(expression, originalReceiverInfo, functionUsageInfo));
|
||||
}
|
||||
else {
|
||||
ClassifierDescriptor targetDescriptor = receiverDescriptor.getType().getConstructor().getDeclarationDescriptor();
|
||||
assert targetDescriptor != null : "Receiver type has no descriptor: " + functionUsageInfo.getDeclaration().getText();
|
||||
result.add(new JetNonQualifiedOuterThisUsage((JetThisExpression) expression.getParent(), targetDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
private void processImplicitThis(
|
||||
@NotNull JetElement callElement,
|
||||
@NotNull ThisReceiver receiverValue
|
||||
) {
|
||||
DeclarationDescriptor targetDescriptor = receiverValue.getDeclarationDescriptor();
|
||||
if (targetDescriptor == functionDescriptor) {
|
||||
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
|
||||
result.add(new JetImplicitThisToParameterUsage(callElement, originalReceiverInfo, functionUsageInfo));
|
||||
}
|
||||
else {
|
||||
result.add(new JetImplicitOuterThisToQualifiedThisUsage(callElement, targetDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, BindingContext context) {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilPackage.getResolvedCall(expression, context);
|
||||
if (resolvedCall == null) return null;
|
||||
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
if (resultingDescriptor instanceof ReceiverParameterDescriptor) {
|
||||
processExplicitThis(expression, (ReceiverParameterDescriptor) resultingDescriptor);
|
||||
return null;
|
||||
}
|
||||
|
||||
ReceiverValue receiverValue = resolvedCall.getExtensionReceiver();
|
||||
if (!(receiverValue instanceof ThisReceiver)) {
|
||||
receiverValue = resolvedCall.getDispatchReceiver();
|
||||
}
|
||||
if (receiverValue instanceof ThisReceiver) {
|
||||
processImplicitThis(resolvedCall.getCall().getCallElement(), (ThisReceiver) receiverValue);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static void findSAMUsages(ChangeInfo changeInfo, Set<UsageInfo> result) {
|
||||
PsiElement method = changeInfo.getMethod();
|
||||
if (!RefactoringPackage.isTrueJavaMethod(method)) return;
|
||||
@@ -203,9 +304,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
PsiElement element = function != null ? function : changeInfo.getContext();
|
||||
BindingContext bindingContext = ResolvePackage.analyze((JetElement) element);
|
||||
FunctionDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo);
|
||||
JetScope parametersScope = null;
|
||||
DeclarationDescriptor containingDeclaration = oldDescriptor != null ? oldDescriptor.getContainingDeclaration() : null;
|
||||
DeclarationDescriptor containingDeclaration = oldDescriptor.getContainingDeclaration();
|
||||
|
||||
JetScope parametersScope = null;
|
||||
if (oldDescriptor instanceof ConstructorDescriptor && containingDeclaration instanceof ClassDescriptorWithResolutionScopes)
|
||||
parametersScope = ((ClassDescriptorWithResolutionScopes) containingDeclaration).getScopeForInitializerResolution();
|
||||
else if (function instanceof JetFunction)
|
||||
@@ -256,9 +357,104 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
||||
}
|
||||
}
|
||||
|
||||
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
|
||||
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
|
||||
if (function instanceof JetNamedFunction && newReceiverInfo != originalReceiverInfo) {
|
||||
findReceiverIntroducingConflicts(result, function, newReceiverInfo);
|
||||
findInternalExplicitReceiverConflicts(refUsages.get(), result, originalReceiverInfo);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void findInternalExplicitReceiverConflicts(
|
||||
UsageInfo[] usages,
|
||||
MultiMap<PsiElement, String> result,
|
||||
JetParameterInfo originalReceiverInfo
|
||||
) {
|
||||
if (originalReceiverInfo == null) {
|
||||
for (UsageInfo usageInfo : usages) {
|
||||
if (!(usageInfo instanceof JetFunctionCallUsage)) continue;
|
||||
|
||||
JetFunctionCallUsage callUsage = (JetFunctionCallUsage) usageInfo;
|
||||
JetElement callElement = callUsage.getElement();
|
||||
if (callElement == null) continue;
|
||||
|
||||
PsiElement parent = callElement.getParent();
|
||||
if (parent instanceof JetQualifiedExpression && ((JetQualifiedExpression) parent).getSelectorExpression() == callElement) {
|
||||
String message = "Explicit receiver is already present in call element: " +
|
||||
CommonRefactoringUtil.htmlEmphasize(parent.getText());
|
||||
result.putValue(callElement, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void findReceiverIntroducingConflicts(
|
||||
MultiMap<PsiElement, String> result,
|
||||
PsiElement callable,
|
||||
JetParameterInfo newReceiverInfo
|
||||
) {
|
||||
if (newReceiverInfo != null && ((JetNamedFunction) callable).getBodyExpression() != null) {
|
||||
Map<JetReferenceExpression, BindingContext> noReceiverRefToContext = KotlinPackage.filter(
|
||||
JetFileReferencesResolver.INSTANCE$.resolve((JetNamedFunction) callable, true, true),
|
||||
new Function1<Map.Entry<? extends JetReferenceExpression, ? extends BindingContext>, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(Map.Entry<? extends JetReferenceExpression, ? extends BindingContext> entry) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(entry.getKey(), entry.getValue());
|
||||
return resolvedCall != null
|
||||
&& !resolvedCall.getDispatchReceiver().exists()
|
||||
&& !resolvedCall.getExtensionReceiver().exists();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
JetPsiFactory psiFactory = new JetPsiFactory(callable.getProject());
|
||||
JetFile tempFile = RefactoringPackage.createTempCopy(
|
||||
(JetFile) callable.getContainingFile(),
|
||||
new Function1<String, String>() {
|
||||
@Override
|
||||
public String invoke(String s) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
);
|
||||
JetNamedFunction functionWithReceiver =
|
||||
PsiTreeUtil.getParentOfType(tempFile.findElementAt(callable.getTextOffset()), JetNamedFunction.class);
|
||||
JetTypeReference receiverTypeRef = psiFactory.createType(newReceiverInfo.getCurrentTypeText());
|
||||
TypeRefHelpersPackage.setReceiverTypeReference(functionWithReceiver, receiverTypeRef);
|
||||
//noinspection ConstantConditions
|
||||
BindingContext newContext = ResolvePackage.analyze(functionWithReceiver.getBodyExpression());
|
||||
|
||||
//noinspection ConstantConditions
|
||||
int originalOffset = ((JetNamedFunction) callable).getBodyExpression().getTextOffset();
|
||||
JetExpression newBody = functionWithReceiver.getBodyExpression();
|
||||
for (Map.Entry<JetReferenceExpression, BindingContext> entry : noReceiverRefToContext.entrySet()) {
|
||||
JetReferenceExpression originalRef = entry.getKey();
|
||||
BindingContext originalContext = entry.getValue();
|
||||
//noinspection ConstantConditions
|
||||
JetReferenceExpression newRef = PsiTreeUtil.getParentOfType(
|
||||
newBody.findElementAt(originalRef.getTextOffset() - originalOffset),
|
||||
JetReferenceExpression.class
|
||||
);
|
||||
ResolvedCall<?> newResolvedCall = CallUtilPackage.getResolvedCall(newRef, newContext);
|
||||
if (newResolvedCall == null
|
||||
|| newResolvedCall.getExtensionReceiver().exists()
|
||||
|| newResolvedCall.getDispatchReceiver().exists()) {
|
||||
//noinspection ConstantConditions
|
||||
CallableDescriptor descriptor =
|
||||
CallUtilPackage.getResolvedCall(originalRef, originalContext).getCandidateDescriptor();
|
||||
PsiElement declaration = DescriptorToDeclarationUtil.INSTANCE$.getDeclaration(callable.getProject(), descriptor);
|
||||
String prefix = declaration != null ? RefactoringUIUtil.getDescription(declaration, true) : originalRef.getText();
|
||||
result.putValue(
|
||||
originalRef,
|
||||
KotlinPackage.capitalize(prefix + " will no longer be accessible after signature change")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<JetType> getFunctionParameterTypes(FunctionDescriptor descriptor) {
|
||||
return ContainerUtil.map(descriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
|
||||
@Override
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,8 @@ public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility
|
||||
val originalPrimaryFunction: JetFunctionDefinitionUsage<PsiElement>
|
||||
val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>>
|
||||
val affectedFunctions: Collection<UsageInfo>
|
||||
|
||||
val receiver: JetParameterInfo?
|
||||
}
|
||||
|
||||
val JetMethodDescriptor.isConstructor: Boolean
|
||||
@@ -39,3 +41,6 @@ val JetMethodDescriptor.isConstructor: Boolean
|
||||
|
||||
fun JetMethodDescriptor.renderOriginalReturnType(): String =
|
||||
baseDescriptor.getReturnType()?.let { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) } ?: ""
|
||||
|
||||
fun JetMethodDescriptor.renderOriginalReceiverType(): String? =
|
||||
baseDescriptor.getExtensionReceiverParameter()?.getType()?.let { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) }
|
||||
+91
-17
@@ -18,9 +18,19 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
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.idea.caches.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -29,42 +39,48 @@ import java.util.Map;
|
||||
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
|
||||
|
||||
public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
||||
private final JetFunctionDefinitionUsage callee;
|
||||
private final JetFunctionDefinitionUsage<?> callee;
|
||||
private final ResolvedCall<? extends CallableDescriptor> resolvedCall;
|
||||
|
||||
public JetFunctionCallUsage(@NotNull JetCallElement element, JetFunctionDefinitionUsage callee) {
|
||||
super(element);
|
||||
this.callee = callee;
|
||||
this.resolvedCall = CallUtilPackage.getResolvedCall(element, ResolvePackage.analyze(element));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processUsage(JetChangeInfo changeInfo, JetCallElement element) {
|
||||
JetValueArgumentList arguments = element.getValueArgumentList();
|
||||
|
||||
if (changeInfo.isNameChanged()) {
|
||||
JetExpression callee = element.getCalleeExpression();
|
||||
|
||||
if (callee instanceof JetSimpleNameExpression)
|
||||
if (callee instanceof JetSimpleNameExpression) {
|
||||
callee.replace(JetPsiFactory(getProject()).createSimpleName(changeInfo.getNewName()));
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments != null) {
|
||||
List<JetValueArgument> oldArguments = arguments.getArguments();
|
||||
|
||||
if (changeInfo.isParameterSetOrOrderChanged())
|
||||
arguments.replace(generateNewArgumentList(changeInfo, oldArguments));
|
||||
else
|
||||
changeArgumentNames(changeInfo, oldArguments);
|
||||
if (element.getValueArgumentList() != null) {
|
||||
if (changeInfo.isParameterSetOrOrderChanged()) {
|
||||
updateArgumentsAndReceiver(changeInfo, element);
|
||||
}
|
||||
else {
|
||||
changeArgumentNames(changeInfo, element);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private JetValueArgumentList generateNewArgumentList(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
||||
private void updateArgumentsAndReceiver(JetChangeInfo changeInfo, JetCallElement element) {
|
||||
JetValueArgumentList arguments = element.getValueArgumentList();
|
||||
assert arguments != null : "Argument list is expected: " + element.getText();
|
||||
List<JetValueArgument> oldArguments = arguments.getArguments();
|
||||
|
||||
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).getArgumentName() != null;
|
||||
StringBuilder parametersBuilder = new StringBuilder("(");
|
||||
boolean isFirst = true;
|
||||
|
||||
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
||||
List<JetParameterInfo> newSignatureParameters = changeInfo.getNonReceiverParameters();
|
||||
for (JetParameterInfo parameterInfo : newSignatureParameters) {
|
||||
if (isFirst)
|
||||
isFirst = false;
|
||||
else
|
||||
@@ -86,8 +102,35 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
||||
Map<Integer, JetValueArgument> argumentMap = getParamIndexToArgumentMap(changeInfo, oldArguments);
|
||||
int argIndex = 0;
|
||||
|
||||
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
|
||||
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
|
||||
|
||||
ReceiverValue extensionReceiver = resolvedCall != null ? resolvedCall.getExtensionReceiver() : ReceiverValue.NO_RECEIVER;
|
||||
ReceiverValue dispatchReceiver = resolvedCall != null ? resolvedCall.getDispatchReceiver() : ReceiverValue.NO_RECEIVER;
|
||||
|
||||
JetPsiFactory psiFactory = new JetPsiFactory(element.getProject());
|
||||
|
||||
PsiElement elementToReplace = element;
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent instanceof JetQualifiedExpression && ((JetQualifiedExpression) parent).getSelectorExpression() == element) {
|
||||
elementToReplace = parent;
|
||||
}
|
||||
|
||||
// Do not add extension receiver to calls with explicit dispatch receiver
|
||||
if (newReceiverInfo != null
|
||||
&& elementToReplace instanceof JetQualifiedExpression
|
||||
&& dispatchReceiver instanceof ExpressionReceiver) return;
|
||||
|
||||
for (JetValueArgument newArgument : newArguments.getArguments()) {
|
||||
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[argIndex++];
|
||||
JetParameterInfo parameterInfo = newSignatureParameters.get(argIndex++);
|
||||
if (parameterInfo == originalReceiverInfo) {
|
||||
JetExpression receiverExpression = getReceiverExpression(extensionReceiver, psiFactory);
|
||||
if (receiverExpression != null) {
|
||||
newArgument.replace(receiverExpression);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
JetValueArgument oldArgument = argumentMap.get(parameterInfo.getOldIndex());
|
||||
|
||||
if (oldArgument != null) {
|
||||
@@ -100,7 +143,38 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
||||
newArgument.delete();
|
||||
}
|
||||
|
||||
return newArguments;
|
||||
arguments.replace(newArguments);
|
||||
|
||||
if (newReceiverInfo == originalReceiverInfo) return;
|
||||
|
||||
PsiElement replacingElement = element;
|
||||
if (newReceiverInfo != null) {
|
||||
JetValueArgument receiverArgument = argumentMap.get(newReceiverInfo.getOldIndex());
|
||||
JetExpression extensionReceiverExpression = receiverArgument != null ? receiverArgument.getArgumentExpression() : null;
|
||||
String receiverText = extensionReceiverExpression != null
|
||||
? extensionReceiverExpression.getText()
|
||||
: newReceiverInfo.getDefaultValueForCall();
|
||||
if (receiverText.isEmpty()) {
|
||||
receiverText = "_";
|
||||
}
|
||||
|
||||
replacingElement = psiFactory.createExpression(receiverText + "." + element.getText());
|
||||
}
|
||||
|
||||
elementToReplace.replace(replacingElement);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetExpression getReceiverExpression(@NotNull ReceiverValue receiver, @NotNull JetPsiFactory psiFactory) {
|
||||
if (receiver instanceof ExpressionReceiver) {
|
||||
return ((ExpressionReceiver) receiver).getExpression();
|
||||
}
|
||||
else if (receiver instanceof ThisReceiver) {
|
||||
DeclarationDescriptor descriptor = ((ThisReceiver) receiver).getDeclarationDescriptor();
|
||||
String thisText = descriptor instanceof ClassDescriptor ? "this@" + descriptor.getName().asString() : "this";
|
||||
return psiFactory.createExpression(thisText);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Map<Integer, JetValueArgument> getParamIndexToArgumentMap(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
||||
@@ -125,8 +199,8 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
||||
return argumentMap;
|
||||
}
|
||||
|
||||
private void changeArgumentNames(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
||||
for (JetValueArgument argument : oldArguments) {
|
||||
private void changeArgumentNames(JetChangeInfo changeInfo, JetCallElement element) {
|
||||
for (ValueArgument argument : element.getValueArguments()) {
|
||||
JetValueArgumentName argumentName = argument.getArgumentName();
|
||||
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
||||
|
||||
|
||||
+21
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,11 +26,19 @@ import kotlin.KotlinPackage;
|
||||
import kotlin.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options;
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenPackage;
|
||||
@@ -39,12 +47,6 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignaturePack
|
||||
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.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -212,6 +214,16 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
||||
ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
|
||||
}
|
||||
|
||||
if (element instanceof JetFunction && changeInfo.isReceiverTypeChanged()) {
|
||||
//noinspection unchecked
|
||||
String receiverTypeText = changeInfo.renderReceiverType((JetFunctionDefinitionUsage<PsiElement>) this);
|
||||
JetTypeReference receiverTypeRef = receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null;
|
||||
JetTypeReference newReceiverTypeRef = TypeRefHelpersPackage.setReceiverTypeReference((JetFunction) element, receiverTypeRef);
|
||||
if (newReceiverTypeRef != null) {
|
||||
ShortenPackage.addToShorteningWaitSet(newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
if (changeInfo.isVisibilityChanged() && !JetPsiUtil.isLocal((JetDeclaration) element)) {
|
||||
changeVisibility(changeInfo, element);
|
||||
}
|
||||
@@ -225,7 +237,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
||||
JetParameterList parameterList,
|
||||
JetPsiFactory psiFactory
|
||||
) {
|
||||
int parametersCount = changeInfo.getNewParametersCount();
|
||||
int parametersCount = changeInfo.getNonReceiverParametersCount();
|
||||
boolean isLambda = element instanceof JetFunctionLiteral;
|
||||
boolean canReplaceEntireList = false;
|
||||
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages
|
||||
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.psi.JetQualifiedExpression
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||
|
||||
public abstract class JetImplicitReceiverUsage(callElement: JetElement): JetUsageInfo<JetElement>(callElement) {
|
||||
protected abstract fun getNewReceiverText(): String
|
||||
|
||||
protected open fun processReplacedElement(element: JetElement) {
|
||||
|
||||
}
|
||||
|
||||
override fun processUsage(changeInfo: JetChangeInfo, element: JetElement): Boolean {
|
||||
val newQualifiedCall = JetPsiFactory(element.getProject()).createExpression(
|
||||
"${getNewReceiverText()}.${element.getText()}"
|
||||
) as JetQualifiedExpression
|
||||
processReplacedElement(element.replace(newQualifiedCall) as JetElement)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public class JetImplicitThisToParameterUsage(
|
||||
callElement: JetElement,
|
||||
val parameterInfo: JetParameterInfo,
|
||||
val containingFunction: JetFunctionDefinitionUsage<*>
|
||||
): JetImplicitReceiverUsage(callElement) {
|
||||
override fun getNewReceiverText(): String = parameterInfo.getInheritedName(containingFunction)
|
||||
|
||||
override fun processReplacedElement(element: JetElement) {
|
||||
element.addToShorteningWaitSet(Options(removeThisLabels = true))
|
||||
}
|
||||
}
|
||||
|
||||
public class JetImplicitOuterThisToQualifiedThisUsage(
|
||||
callElement: JetElement,
|
||||
val targetDescriptor: DeclarationDescriptor
|
||||
): JetImplicitReceiverUsage(callElement) {
|
||||
override fun getNewReceiverText(): String = "this@${targetDescriptor.getName().asString()}"
|
||||
|
||||
override fun processReplacedElement(element: JetElement) {
|
||||
element.addToShorteningWaitSet(Options(removeThisLabels = true, removeThis = true))
|
||||
}
|
||||
}
|
||||
+42
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,15 +20,51 @@ import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.psi.JetQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import org.jetbrains.kotlin.psi.JetThisExpression
|
||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||
|
||||
// Explicit reference to function parameter or outer this
|
||||
public abstract class JetExplicitReferenceUsage<T: JetElement>(element: T) : JetUsageInfo<T>(element) {
|
||||
protected abstract fun getReplacementText(changeInfo: JetChangeInfo): String
|
||||
|
||||
protected open fun processReplacedElement(element: JetElement) {
|
||||
|
||||
}
|
||||
|
||||
override fun processUsage(changeInfo: JetChangeInfo, element: T): Boolean {
|
||||
val newElement = JetPsiFactory(element.getProject()).createExpression(getReplacementText(changeInfo))
|
||||
processReplacedElement(element.replace(newElement) as JetElement)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public class JetParameterUsage(
|
||||
element: JetSimpleNameExpression,
|
||||
private val parameterInfo: JetParameterInfo,
|
||||
private val containingFunction: JetFunctionDefinitionUsage<*>
|
||||
) : JetUsageInfo<JetSimpleNameExpression>(element) {
|
||||
override fun processUsage(changeInfo: JetChangeInfo, element: JetSimpleNameExpression): Boolean {
|
||||
val newName = parameterInfo.getInheritedName(containingFunction)
|
||||
element.replace(JetPsiFactory(element.getProject()).createSimpleName(newName))
|
||||
return false
|
||||
) : JetExplicitReferenceUsage<JetSimpleNameExpression>(element) {
|
||||
override fun processReplacedElement(element: JetElement) {
|
||||
val qualifiedExpression = element.getParent() as? JetQualifiedExpression
|
||||
if (qualifiedExpression?.getReceiverExpression() == element) {
|
||||
qualifiedExpression!!.addToShorteningWaitSet(Options(removeThis = true))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getReplacementText(changeInfo: JetChangeInfo): String =
|
||||
if (changeInfo.receiverParameterInfo != parameterInfo) parameterInfo.getInheritedName(containingFunction) else "this"
|
||||
}
|
||||
|
||||
public class JetNonQualifiedOuterThisUsage(
|
||||
element: JetThisExpression,
|
||||
val targetDescriptor: DeclarationDescriptor
|
||||
) : JetExplicitReferenceUsage<JetThisExpression>(element) {
|
||||
override fun processReplacedElement(element: JetElement) {
|
||||
element.addToShorteningWaitSet(Options(removeThisLabels = true))
|
||||
}
|
||||
|
||||
override fun getReplacementText(changeInfo: JetChangeInfo): String = "this@${targetDescriptor.getName().asString()}"
|
||||
}
|
||||
+8
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
||||
|
||||
public abstract class JetUsageInfo<T extends PsiElement> extends UsageInfo {
|
||||
@@ -31,5 +32,12 @@ public abstract class JetUsageInfo<T extends PsiElement> extends UsageInfo {
|
||||
super(reference);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public T getElement() {
|
||||
//noinspection unchecked
|
||||
return (T) super.getElement();
|
||||
}
|
||||
|
||||
public abstract boolean processUsage(JetChangeInfo changeInfo, T element);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun X.foo(s: String, k: Int): Boolean {
|
||||
return s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo("1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun <caret>foo(s: String, k: Int): Boolean {
|
||||
return s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fun length(): Int = 1
|
||||
|
||||
fun <caret>foo(k: Int): Boolean {
|
||||
return length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int) {
|
||||
fun length() = 2
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo(2)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Function length will no longer be accessible after signature change
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.foo(s: String, n: Int): Boolean {
|
||||
return s.length() * this@A.k - n.inc() + this@A.k > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo("1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun <caret>foo(s: String, n: Int): Boolean {
|
||||
return s.length() * this.k - n.inc() + k > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class A(val k: Int) {
|
||||
fun <caret>foo(s: String, n: Int): Boolean {
|
||||
return s.length()*this.k - n.inc() + k > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
A(3).foo("1", 2)
|
||||
with(A(3)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Explicit receiver is already present in call element: A(3).foo("1", 2)
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
interface J<A> extends T<A> {
|
||||
@Override
|
||||
<B> int foofoofoo(U<A> a, B b);
|
||||
}
|
||||
|
||||
abstract class J1<X> implements J<U<X>> {
|
||||
@Override
|
||||
public <C> int foofoofoo(U<U<X>> xu, C c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class J2 extends J1<String> {
|
||||
@Override
|
||||
public <C> int foofoofoo(U<U<String>> xu, C c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class U<A>
|
||||
|
||||
trait T<A> {
|
||||
fun U<A>.foofoofoo<B>(b: B): Int
|
||||
}
|
||||
|
||||
abstract class T1<X> : T<U<X>> {
|
||||
override fun <B> U<U<X>>.foofoofoo(b: B): Int {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class T2 : T1<String>() {
|
||||
override fun <C> U<U<String>>.foofoofoo(b: C): Int {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
interface J<A> extends T<A> {
|
||||
@Override
|
||||
<B> int foofoofoo(A a, B b);
|
||||
}
|
||||
|
||||
abstract class J1<X> implements J<U<X>> {
|
||||
@Override
|
||||
public <C> int foofoofoo(U<X> xu, C c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class J2 extends J1<String> {
|
||||
@Override
|
||||
public <C> int foofoofoo(U<String> xu, C c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class U<A>
|
||||
|
||||
trait T<A> {
|
||||
fun <caret>foofoofoo<B>(a: A, b: B): Int
|
||||
}
|
||||
|
||||
abstract class T1<X> : T<U<X>> {
|
||||
override fun <B> foofoofoo(a: U<X>, b: B): Int {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class T2 : T1<String>() {
|
||||
override fun <C> foofoofoo(a: U<String>, b: C): Int {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo("1", new X(0), 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun String.foo(x: X, k: Int): Boolean {
|
||||
return x.k + length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
"1".foo(X(0), 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo("1", new X(0), 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun String.foo(x: X, k: Int): Boolean {
|
||||
return x.k + length() - k + this@A.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
"1".foo(X(0), 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
"1".foo(X(0), 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k + this@A.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun X.foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||
return x.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun X.foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo("1", new X(0), 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun <caret>foo(s: String, x: X, k: Int): Boolean {
|
||||
return x.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun test() {
|
||||
foo("1", X(0), 2)
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k + this@A.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||
return x.k + s.length() - k + this.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k + this@A.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo("1", new X(0), 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun <caret>foo(s: String, x: X, k: Int): Boolean {
|
||||
return x.k + s.length() - k + this.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo("1", X(0), 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
foo("1", X(0), 2)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class A(val k: Int) {
|
||||
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||
return x.k + s.length() - k + this.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
A(3).foo(X(0), "1", 2)
|
||||
with(A(3)) {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
Explicit receiver is already present in call element: A(3).foo(X(0), "1", 2)
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||
return x.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
foo(X(0), "1", 2)
|
||||
with(X(0)) {
|
||||
foo(this, "1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
with(X(0)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo("1", new X(0), 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun <caret>foo(s: String, x: X, k: Int): Boolean {
|
||||
return x.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
foo("1", X(0), 2)
|
||||
with(X(0)) {
|
||||
foo("1", this, 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
with(X(0)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class X(val k: Int)
|
||||
|
||||
fun foo(abc: X, n: Int): Boolean {
|
||||
return abc.k > n
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class X(val k: Int)
|
||||
|
||||
fun X.<caret>foo(n: Int): Boolean {
|
||||
return this.k > n
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun foo(x: X, s: String, k: Int): Boolean {
|
||||
return x.k + s.length() - k + this.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
foo(X(0), "1", 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k + this@A.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo("1", new X(0), 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun foo(s: String, x: X, k: Int): Boolean {
|
||||
return x.k + s.length() - k + this.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo("1", X(0), 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
foo("1", X(0), 2)
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k + this@A.k/2 > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
val x1: Int
|
||||
|
||||
class X(val x: Int)
|
||||
|
||||
fun foo(x2: X, x: Int): Boolean {
|
||||
return x2.x + x > x1
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
val x1: Int
|
||||
|
||||
class X(val x: Int)
|
||||
|
||||
fun X.<caret>foo(x: Int): Boolean {
|
||||
return this.x + x > x1
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo("1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(X(0)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
_DefaultPackage.foo(new X(0), "1", 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||
return this.k + s.length() - k > 0
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(X(0)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(1, "2");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun foo(s: String, n: Int): Boolean {
|
||||
return s.length() * this.k - n.inc() + this@A.k > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
foo("1", 2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class J {
|
||||
void test() {
|
||||
new A(3).foo(new X(0), 1, "2");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class A(val k: Int) {
|
||||
fun X.<caret>foo(s: String, n: Int): Boolean {
|
||||
return s.length() * this.k - n.inc() + this@A.k > 0
|
||||
}
|
||||
|
||||
fun test() {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
|
||||
class X(val k: Int)
|
||||
|
||||
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||
|
||||
fun test() {
|
||||
with(A(3)) {
|
||||
X(0).foo("1", 2)
|
||||
}
|
||||
}
|
||||
+141
-1
@@ -318,7 +318,8 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
||||
public void testFunctionJavaUsagesAndOverridesAddParam() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.addParameter(new JetParameterInfo(-1, "s", KotlinBuiltIns.getInstance().getStringType(), null, "\"abc\"", null, null));
|
||||
changeInfo.addParameter(new JetParameterInfo(-1, "o", KotlinBuiltIns.getInstance().getNullableAnyType(), null, "\"def\"", null, null));
|
||||
changeInfo.addParameter(
|
||||
new JetParameterInfo(-1, "o", KotlinBuiltIns.getInstance().getNullableAnyType(), null, "\"def\"", null, null));
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
@@ -360,6 +361,16 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testAddReceiverToGenericsWithOverrides() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
|
||||
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[0];
|
||||
parameterInfo.setCurrentTypeText("U<A>");
|
||||
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testJavaMethodKotlinUsages() throws Exception {
|
||||
doJavaTest(
|
||||
new JavaRefactoringProvider() {
|
||||
@@ -582,6 +593,135 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testAddNewReceiver() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||
parameterInfo.setCurrentTypeText("X");
|
||||
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testAddNewReceiverForMember() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||
parameterInfo.setCurrentTypeText("X");
|
||||
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testAddNewReceiverForMemberConflict() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||
parameterInfo.setCurrentTypeText("X");
|
||||
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||
doTestConflict(changeInfo);
|
||||
}
|
||||
|
||||
public void testAddNewReceiverConflict() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||
parameterInfo.setCurrentTypeText("X");
|
||||
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||
doTestConflict(changeInfo);
|
||||
}
|
||||
|
||||
public void testRemoveReceiver() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.removeParameter(0);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testRemoveReceiverForMember() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.removeParameter(0);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertParameterToReceiver1() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[0]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertParameterToReceiver2() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertReceiverToParameter1() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(null);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertReceiverToParameter2() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(null);
|
||||
JetParameterInfo[] parameters = changeInfo.getNewParameters();
|
||||
changeInfo.setNewParameter(0, parameters[1]);
|
||||
changeInfo.setNewParameter(1, parameters[0]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertParameterToReceiverForMember1() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[0]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertParameterToReceiverForMember2() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertParameterToReceiverForMemberConflict() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[0]);
|
||||
doTestConflict(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertReceiverToParameterForMember1() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(null);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertReceiverToParameterForMember2() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(null);
|
||||
JetParameterInfo[] parameters = changeInfo.getNewParameters();
|
||||
changeInfo.setNewParameter(0, parameters[1]);
|
||||
changeInfo.setNewParameter(1, parameters[0]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertReceiverToParameterWithNameClash() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(null);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testConvertReceiverToParameterAndChangeName() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(null);
|
||||
changeInfo.getNewParameters()[0].setName("abc");
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testChangeReceiver() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
public void testChangeReceiverForMember() throws Exception {
|
||||
JetChangeInfo changeInfo = getChangeInfo();
|
||||
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||
doTest(changeInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
|
||||
Reference in New Issue
Block a user