diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.kt b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.kt index 8927eeebe1d..dea4ee8a664 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.kt @@ -234,6 +234,10 @@ public class JetPsiFactory(private val project: Project) { return createFunction("fun foo$text{}").getValueParameterList()!! } + public fun createFunctionLiteralParameterList(text: String): JetParameterList { + return (createExpression("{ $text -> 0}") as JetFunctionLiteralExpression).getFunctionLiteral().getValueParameterList() + } + public fun createEnumEntry(text: String): JetEnumEntry { return createDeclaration("enum class E {$text}").getDeclarations()[0] as JetEnumEntry } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeInfo.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeInfo.java index c52998a9958..748717757f1 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeInfo.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeInfo.java @@ -37,12 +37,15 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.Visibilities; import org.jetbrains.jet.lang.descriptors.Visibility; +import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; +import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers; import java.util.Collection; import java.util.HashMap; @@ -93,7 +96,7 @@ public class JetChangeInfo implements ChangeInfo { return KotlinPackage.firstOrNull(psiMethods); } - public String getNewSignature(@Nullable JetFunction inheritedFunction, boolean isInherited) { + public String getNewSignature(@Nullable FunctionDescriptor inheritedFunctionDescriptor, boolean isInherited) { StringBuilder buffer = new StringBuilder(); if (isConstructor()) { @@ -109,7 +112,7 @@ public class JetChangeInfo implements ChangeInfo { buffer.append(JetTokens.FUN_KEYWORD).append(' ').append(newName); } - buffer.append(getNewParametersSignature(inheritedFunction, isInherited, buffer.length())); + buffer.append(getNewParametersSignature(inheritedFunctionDescriptor, isInherited, false, buffer.length())); if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && !isConstructor()) buffer.append(": ").append(newReturnTypeText); @@ -117,7 +120,24 @@ public class JetChangeInfo implements ChangeInfo { return buffer.toString(); } - public String getNewParametersSignature(PsiElement inheritedFunction, boolean isInherited, int indentLength) { + public boolean isRefactoringTarget(FunctionDescriptor inheritedFunctionDescriptor) { + return inheritedFunctionDescriptor != null && + getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedFunctionDescriptor); + } + + public String getNewParametersSignature( + @Nullable FunctionDescriptor inheritedFunctionDescriptor, + boolean isInherited, + boolean hasExpectedType, + int indentLength + ) { + hasExpectedType = hasExpectedType && !isRefactoringTarget(inheritedFunctionDescriptor); + + boolean isLambda = inheritedFunctionDescriptor instanceof AnonymousFunctionDescriptor; + if (isLambda && newParameters.size() == 1 && !newParameters.get(0).requiresExplicitType(inheritedFunctionDescriptor, hasExpectedType)) { + return newParameters.get(0).getDeclarationSignature(isInherited, hasExpectedType, inheritedFunctionDescriptor, oldDescriptor); + } + StringBuilder buffer = new StringBuilder("("); String indent = StringUtil.repeatSymbol(' ', indentLength + 1); @@ -128,7 +148,7 @@ public class JetChangeInfo implements ChangeInfo { buffer.append(indent); } - buffer.append(parameterInfo.getDeclarationSignature(isInherited, inheritedFunction, oldDescriptor)); + buffer.append(parameterInfo.getDeclarationSignature(isInherited, hasExpectedType, inheritedFunctionDescriptor, oldDescriptor)); } buffer.append(")"); @@ -163,6 +183,10 @@ public class JetChangeInfo implements ChangeInfo { return map; } + public int getNewParametersCount() { + return newParameters.size(); + } + @NotNull @Override public JetParameterInfo[] getNewParameters() { @@ -346,32 +370,41 @@ public class JetChangeInfo implements ChangeInfo { PsiMethod method = (PsiMethod) javaChangeInfo.getMethod(); FunctionDescriptor functionDescriptor = ResolvePackage.getJavaMethodDescriptor(method); - final List parameterDescriptors = functionDescriptor.getValueParameters(); + + //noinspection ConstantConditions + final List originalParameterDescriptors = + originalChangeSignatureDescriptor.getDescriptor().getValueParameters(); + + List newParameters = KotlinPackage.map( KotlinPackage.withIndices(javaChangeInfo.getNewParameters()), new Function1, JetParameterInfo>() { @Override public JetParameterInfo invoke(Pair pair) { ParameterInfo info = pair.getSecond(); - JetParameterInfo jetParameterInfo = new JetParameterInfo( - info.getOldIndex(), - info.getName(), - parameterDescriptors.get(pair.getFirst()).getType(), - null, - null - ); + int oldIndex = info.getOldIndex(); + JetType currentType = parameterDescriptors.get(pair.getFirst()).getType(); + JetType originalType = oldIndex >= 0 + ? originalParameterDescriptors.get(oldIndex).getType() + : currentType; + + JetParameterInfo jetParameterInfo = new JetParameterInfo(oldIndex, info.getName(), originalType, null, null); jetParameterInfo.setDefaultValueText(info.getDefaultValue()); + jetParameterInfo.setTypeText(IdeDescriptorRenderers.SOURCE_CODE.renderType(currentType)); return jetParameterInfo; } } ); + JetType returnType = functionDescriptor.getReturnType(); + String returnTypeText = returnType != null ? IdeDescriptorRenderers.SOURCE_CODE.renderType(returnType) : ""; + return new JetChangeInfo( originalChangeSignatureDescriptor, javaChangeInfo.getNewName(), - functionDescriptor.getReturnType(), - "", + returnType, + returnTypeText, functionDescriptor.getVisibility(), newParameters, method, diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureData.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureData.java index 31f11d29bea..609b863edbd 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureData.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureData.java @@ -108,13 +108,13 @@ public final class JetChangeSignatureData implements JetMethodDescriptor { new HashSet(), new Function1>() { @Override - public Iterable invoke(FunctionDescriptor descriptor) { + public Iterable invoke(final FunctionDescriptor descriptor) { PsiElement declaration = DescriptorToDeclarationUtil.INSTANCE$.getDeclaration(baseDeclaration.getProject(), descriptor); assert declaration != null : "No declaration found for " + descriptor; Set result = Sets.newHashSet(); - result.add(new JetFunctionDefinitionUsage(declaration, false)); + result.add(new JetFunctionDefinitionUsage(declaration, descriptor, false)); if (!(declaration instanceof JetNamedFunction)) return result; @@ -130,7 +130,9 @@ public final class JetChangeSignatureData implements JetMethodDescriptor { public UsageInfo invoke(PsiMethod method) { if (method instanceof KotlinLightMethod) { JetDeclaration declaration = ((KotlinLightMethod) method).getOrigin(); - return declaration != null ? new JetFunctionDefinitionUsage(declaration, true) : null; + return declaration != null + ? new JetFunctionDefinitionUsage(declaration, descriptor, true) + : null; } return new OverriderUsageInfo(method, baseLightMethod, true, true, true); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java index 93f2fe8ab5e..9f26ce851c7 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; @@ -34,16 +35,17 @@ import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.asJava.KotlinLightMethod; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; +import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; +import org.jetbrains.jet.plugin.refactoring.RefactoringPackage; import org.jetbrains.jet.plugin.refactoring.changeSignature.usages.*; import org.jetbrains.jet.plugin.references.JetSimpleNameReference; import org.jetbrains.jet.renderer.DescriptorRenderer; @@ -60,6 +62,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro if (info instanceof JetChangeInfo) { findAllMethodUsages((JetChangeInfo) info, result); } + else { + findSAMUsages(info, result); + } return result.toArray(new UsageInfo[result.size()]); } @@ -94,12 +99,12 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro PsiElement parent = element.getParent(); if (parent instanceof JetCallExpression) - result.add(new JetFunctionCallUsage((JetCallExpression) parent, functionPsi, isInherited)); + result.add(new JetFunctionCallUsage((JetCallExpression) parent, functionUsageInfo.getFunctionDescriptor(), isInherited)); else if (parent instanceof JetUserType && parent.getParent() instanceof JetTypeReference) { parent = parent.getParent().getParent(); if (parent instanceof JetConstructorCalleeExpression && parent.getParent() instanceof JetDelegatorToSuperCall) - result.add(new JetFunctionCallUsage((JetDelegatorToSuperCall)parent.getParent(), functionPsi, isInherited)); + result.add(new JetFunctionCallUsage((JetDelegatorToSuperCall)parent.getParent(), functionUsageInfo.getFunctionDescriptor(), isInherited)); } } } @@ -124,7 +129,15 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetValueArgumentName)) // Usages in named arguments of the calls usage will be changed when the function call is changed - result.add(new JetParameterUsage((JetSimpleNameExpression) element, parameterInfo, functionPsi, isInherited)); + { + JetParameterUsage parameterUsage = new JetParameterUsage( + (JetSimpleNameExpression) element, + parameterInfo, + functionUsageInfo.getFunctionDescriptor(), + isInherited + ); + result.add(parameterUsage); + } } } } @@ -139,6 +152,41 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } } + private static void findSAMUsages(ChangeInfo changeInfo, Set result) { + PsiElement method = changeInfo.getMethod(); + if (!RefactoringPackage.isTrueJavaMethod(method)) return; + + FunctionDescriptor methodDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) method); + + DeclarationDescriptor containingDescriptor = methodDescriptor.getContainingDeclaration(); + if (!(containingDescriptor instanceof JavaClassDescriptor)) return; + + if (((JavaClassDescriptor) containingDescriptor).getFunctionTypeForSamInterface() == null) return; + + PsiClass samClass = ((PsiMethod) method).getContainingClass(); + if (samClass == null) return; + + for (PsiReference ref : ReferencesSearch.search(samClass)) { + if (!(ref instanceof JetSimpleNameReference)) continue; + + JetSimpleNameExpression callee = ((JetSimpleNameReference) ref).getExpression(); + JetCallExpression callExpression = PsiTreeUtil.getParentOfType(callee, JetCallExpression.class); + if (callExpression == null || callExpression.getCalleeExpression() != callee) continue; + + List arguments = callExpression.getValueArguments(); + if (arguments.size() != 1) continue; + + JetExpression argExpression = arguments.get(0).getArgumentExpression(); + if (!(argExpression instanceof JetFunctionLiteralExpression)) continue; + + JetFunctionLiteral functionLiteral = ((JetFunctionLiteralExpression) argExpression).getFunctionLiteral(); + FunctionDescriptor functionDescriptor = + ResolvePackage.analyze(functionLiteral).get(BindingContext.FUNCTION, functionLiteral); + assert functionDescriptor != null : "No descriptor for " + functionLiteral.getText(); + result.add(new KotlinSAMUsage(functionLiteral, functionDescriptor)); + } + } + @Override public MultiMap findConflicts(ChangeInfo info, Ref refUsages) { MultiMap result = new MultiMap(); @@ -247,16 +295,24 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro private JetMethodDescriptor originalJavaMethodDescriptor; private static boolean isJavaMethodUsage(UsageInfo usageInfo) { - if (!(usageInfo instanceof MoveRenameUsageInfo)) return false; - PsiElement referencedElement = ((MoveRenameUsageInfo) usageInfo).getReferencedElement(); - return referencedElement instanceof PsiMethod && !(referencedElement instanceof KotlinLightMethod); + if (usageInfo instanceof KotlinSAMUsage) return true; + + // MoveRenameUsageInfo corresponds to non-Java usage of Java method + return usageInfo instanceof MoveRenameUsageInfo + && RefactoringPackage.isTrueJavaMethod(((MoveRenameUsageInfo) usageInfo).getReferencedElement()); } @Nullable - private static UsageInfo createFunctionCallUsage( + private static UsageInfo createReplacementUsage( UsageInfo originalUsageInfo, JetChangeInfo javaMethodChangeInfo ) { + if (originalUsageInfo instanceof KotlinSAMUsage) { + JetFunctionLiteral functionLiteral = ((KotlinSAMUsage) originalUsageInfo).getFunctionLiteral(); + FunctionDescriptor functionDescriptor = ((KotlinSAMUsage) originalUsageInfo).getFunctionDescriptor(); + return new JavaMethodKotlinDerivedDefinitionUsage(functionLiteral, functionDescriptor, javaMethodChangeInfo); + } + JetCallElement callElement = PsiTreeUtil.getParentOfType(originalUsageInfo.getElement(), JetCallElement.class); return callElement != null ? new JavaMethodKotlinCallUsage(callElement, javaMethodChangeInfo) : null; } @@ -308,7 +364,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro UsageInfo oldUsageInfo = usages[i]; if (!isJavaMethodUsage(oldUsageInfo)) continue; - UsageInfo newUsageInfo = createFunctionCallUsage(oldUsageInfo, javaMethodChangeInfo); + UsageInfo newUsageInfo = createReplacementUsage(oldUsageInfo, javaMethodChangeInfo); if (newUsageInfo != null) { usages[i] = newUsageInfo; if (oldUsageInfo == usageInfo) { @@ -318,8 +374,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } } - if (usageInfo instanceof JavaMethodKotlinCallUsage) { - return ((JavaMethodKotlinCallUsage) usageInfo).processUsage(); + if (usageInfo instanceof JavaMethodKotlinUsageWithDelegate) { + return ((JavaMethodKotlinUsageWithDelegate) usageInfo).processUsage(); } if (usageInfo instanceof MoveRenameUsageInfo && isJavaMethodUsage) { diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetParameterInfo.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetParameterInfo.java index 31b0a170a1a..e458b5bd449 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetParameterInfo.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/JetParameterInfo.java @@ -17,17 +17,18 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.refactoring.changeSignature.ParameterInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetParameter; +import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.renderer.DescriptorRenderer; +import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers; import java.util.List; @@ -72,21 +73,25 @@ public class JetParameterInfo implements ParameterInfo { return name; } - public String getInheritedName(boolean isInherited, @Nullable PsiElement inheritedFunction, @NotNull JetMethodDescriptor baseFunction) { - if (!(isInherited && inheritedFunction instanceof JetFunction)) return name; + public String getInheritedName( + boolean isInherited, + @Nullable FunctionDescriptor inheritedFunctionDescriptor, + @NotNull JetMethodDescriptor baseFunction + ) { + if (!isInherited || inheritedFunctionDescriptor == null) return name; FunctionDescriptor baseFunctionDescriptor = baseFunction.getDescriptor(); assert baseFunctionDescriptor != null : "No descriptor for " + baseFunction.getMethod().getText(); - JetFunction inheritedJetFunction = (JetFunction) inheritedFunction; - List inheritedParameters = inheritedJetFunction.getValueParameters(); + List inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters(); + if (oldIndex < 0 || oldIndex >= baseFunction.getParametersCount() || oldIndex >= inheritedParameterDescriptors.size()) return name; - if (oldIndex < 0 || oldIndex >= baseFunction.getParametersCount() || oldIndex >= inheritedParameters.size()) return name; - - String inheritedParamName = inheritedParameters.get(oldIndex).getName(); + String inheritedParamName = inheritedParameterDescriptors.get(oldIndex).getName().asString(); String oldParamName = baseFunctionDescriptor.getValueParameters().get(oldIndex).getName().asString(); - return oldParamName.equals(inheritedParamName) ? name : inheritedParamName; + return oldParamName.equals(inheritedParamName) && !(inheritedFunctionDescriptor instanceof AnonymousFunctionDescriptor) + ? name + : inheritedParamName; } @Override @@ -120,7 +125,7 @@ public class JetParameterInfo implements ParameterInfo { } private String getOldTypeText() { - return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); + return IdeDescriptorRenderers.SOURCE_CODE.renderType(type); } @Override @@ -156,7 +161,23 @@ public class JetParameterInfo implements ParameterInfo { return type; } - public String getDeclarationSignature(boolean isInherited, PsiElement inheritedFunction, JetMethodDescriptor baseFunction) { + public boolean requiresExplicitType(@Nullable FunctionDescriptor inheritedFunctionDescriptor, boolean hasExpectedType) { + if (inheritedFunctionDescriptor == null || !(inheritedFunctionDescriptor instanceof AnonymousFunctionDescriptor)) return true; + + if (oldIndex < 0) return !hasExpectedType; + + ValueParameterDescriptor inheritedParameterDescriptor = inheritedFunctionDescriptor.getValueParameters().get(oldIndex); + JetParameter parameter = (JetParameter) DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor); + if (parameter == null) return false; + + return parameter.getTypeReference() != null; + } + + public String getDeclarationSignature( + boolean isInherited, + boolean hasExpectedType, + @Nullable FunctionDescriptor inheritedFunctionDescriptor, + JetMethodDescriptor baseFunction) { StringBuilder buffer = new StringBuilder(); JetValVar valVar = getValOrVar(); @@ -164,8 +185,11 @@ public class JetParameterInfo implements ParameterInfo { buffer.append(valVar.toString()).append(' '); } - buffer.append(getInheritedName(isInherited, inheritedFunction, baseFunction)); - buffer.append(": ").append(getTypeText()); + buffer.append(getInheritedName(isInherited, inheritedFunctionDescriptor, baseFunction)); + + if (requiresExplicitType(inheritedFunctionDescriptor, hasExpectedType)) { + buffer.append(": ").append(getTypeText()); + } if (defaultValue != null && !isInherited) { buffer.append(" = ").append(defaultValue.getText()); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JavaMethodKotlinUsageWithDelegate.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JavaMethodKotlinUsageWithDelegate.kt new file mode 100644 index 00000000000..4fb30b8cedb --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JavaMethodKotlinUsageWithDelegate.kt @@ -0,0 +1,47 @@ +/* + * 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.jet.plugin.refactoring.changeSignature.usages + +import org.jetbrains.jet.lang.psi.JetCallElement +import com.intellij.psi.PsiElement +import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeInfo +import com.intellij.usageView.UsageInfo +import org.jetbrains.jet.lang.psi.JetElement +import org.jetbrains.jet.lang.psi.JetFunction +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor + +public abstract class JavaMethodKotlinUsageWithDelegate( + val jetElement: T, + val javaMethodChangeInfo: JetChangeInfo): UsageInfo(javaMethodChangeInfo.getMethod()) { + protected abstract val delegateUsage: JetUsageInfo + + fun processUsage(): Boolean = delegateUsage.processUsage(javaMethodChangeInfo, jetElement) +} + +public class JavaMethodKotlinCallUsage( + callElement: JetCallElement, + javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate(callElement, javaMethodChangeInfo) { + override protected val delegateUsage = JetFunctionCallUsage(jetElement, javaMethodChangeInfo.getFunctionDescriptor().getDescriptor(), false) +} + +public class JavaMethodKotlinDerivedDefinitionUsage( + function: JetFunction, + functionDescriptor: FunctionDescriptor, + javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate(function, javaMethodChangeInfo) { + [suppress("CAST_NEVER_SUCCEEDS")] + override protected val delegateUsage = JetFunctionDefinitionUsage(jetElement, functionDescriptor, true) as JetUsageInfo +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetEnumEntryWithoutSuperCallUsage.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetEnumEntryWithoutSuperCallUsage.kt index 2bfaacd068c..07272f24b58 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetEnumEntryWithoutSuperCallUsage.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetEnumEntryWithoutSuperCallUsage.kt @@ -37,7 +37,8 @@ public class JetEnumEntryWithoutSuperCallUsage(enumEntry: JetEnumEntry) : JetUsa ) as JetDelegatorToSuperCall element.addBefore(psiFactory.createColon(), delegatorToSuperCall) - return JetFunctionCallUsage(delegatorToSuperCall, enumClass, false).processUsage(changeInfo, delegatorToSuperCall) + return JetFunctionCallUsage(delegatorToSuperCall, changeInfo.getFunctionDescriptor().getDescriptor(), false) + .processUsage(changeInfo, delegatorToSuperCall) } return true diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionCallUsage.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionCallUsage.java index ab951ee27d6..a7ff6b89d80 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionCallUsage.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionCallUsage.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature.usages; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeInfo; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetParameterInfo; @@ -29,12 +30,12 @@ import java.util.Map; import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory; public class JetFunctionCallUsage extends JetUsageInfo { - private final PsiElement function; + private final FunctionDescriptor functionDescriptor; private final boolean isInherited; - public JetFunctionCallUsage(@NotNull JetCallElement element, @NotNull PsiElement function, boolean isInherited) { + public JetFunctionCallUsage(@NotNull JetCallElement element, @NotNull FunctionDescriptor functionDescriptor, boolean isInherited) { super(element); - this.function = function; + this.functionDescriptor = functionDescriptor; this.isInherited = isInherited; } @@ -75,7 +76,7 @@ public class JetFunctionCallUsage extends JetUsageInfo { String defaultValueText = parameterInfo.getDefaultValueText(); if (isNamedCall) { - String newName = parameterInfo.getInheritedName(isInherited, function, changeInfo.getFunctionDescriptor()); + String newName = parameterInfo.getInheritedName(isInherited, functionDescriptor, changeInfo.getFunctionDescriptor()); parametersBuilder.append(newName).append('='); } @@ -147,7 +148,7 @@ public class JetFunctionCallUsage extends JetUsageInfo { PsiElement identifier = argumentNameExpression != null ? argumentNameExpression.getIdentifier() : null; if (identifier != null) { - String newName = parameterInfo.getInheritedName(isInherited, function, changeInfo.getFunctionDescriptor()); + String newName = parameterInfo.getInheritedName(isInherited, functionDescriptor, changeInfo.getFunctionDescriptor()); identifier.replace(JetPsiFactory(getProject()).createIdentifier(newName)); } } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java index d9f2935cf2b..8b34b76fa16 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java @@ -18,10 +18,17 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature.usages; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import kotlin.Pair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetModifierKeywordToken; +import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; +import org.jetbrains.jet.plugin.codeInsight.shorten.ShortenPackage; import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeInfo; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetParameterInfo; @@ -31,16 +38,41 @@ import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory; public class JetFunctionDefinitionUsage extends JetUsageInfo { private final boolean isInherited; + private final FunctionDescriptor functionDescriptor; + private final boolean hasExpectedType; - public JetFunctionDefinitionUsage(@NotNull PsiElement function, boolean isInherited) { + public JetFunctionDefinitionUsage( + @NotNull PsiElement function, + @NotNull FunctionDescriptor functionDescriptor, + boolean isInherited) { super(function); this.isInherited = isInherited; + this.functionDescriptor = functionDescriptor; + this.hasExpectedType = checkIfHasExpectedType(functionDescriptor); + } + + private static boolean checkIfHasExpectedType(@NotNull FunctionDescriptor functionDescriptor) { + if (!(functionDescriptor instanceof AnonymousFunctionDescriptor)) return false; + + JetFunctionLiteral functionLiteral = + (JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); + assert functionLiteral != null : "No declaration found for " + functionDescriptor; + + PsiElement parent = functionLiteral.getParent(); + if (!(parent instanceof JetFunctionLiteralExpression)) return false; + + JetFunctionLiteralExpression expression = (JetFunctionLiteralExpression) parent; + return ResolvePackage.analyze(expression).get(BindingContext.EXPECTED_EXPRESSION_TYPE, expression) != null; } public final boolean isInherited() { return isInherited; } + public final FunctionDescriptor getFunctionDescriptor() { + return functionDescriptor; + } + @Override public boolean processUsage(JetChangeInfo changeInfo, PsiElement element) { JetParameterList parameterList; @@ -57,13 +89,17 @@ public class JetFunctionDefinitionUsage extends JetUsageInfo { identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName())); } } - if (changeInfo.isReturnTypeChanged()) { + + boolean returnTypeIsNeeded = changeInfo.isRefactoringTarget(functionDescriptor) + || !(function instanceof JetFunctionLiteral) + || function.getTypeReference() != null; + if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) { function.setTypeReference(null); String returnTypeText = changeInfo.getNewReturnTypeText(); //TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready if (!KotlinBuiltIns.getInstance().getUnitType().toString().equals(returnTypeText)) { - function.setTypeReference(JetPsiFactory(function).createType(returnTypeText)); + ShortenPackage.addToShorteningWaitSet(function.setTypeReference(JetPsiFactory(function).createType(returnTypeText))); } } } @@ -72,30 +108,69 @@ public class JetFunctionDefinitionUsage extends JetUsageInfo { } if (changeInfo.isParameterSetOrOrderChanged()) { - String parametersText = changeInfo.getNewParametersSignature(element, isInherited, 0); - JetParameterList newParameterList = psiFactory.createParameterList(parametersText); + int parametersCount = changeInfo.getNewParametersCount(); + boolean isLambda = element instanceof JetFunctionLiteral; - if (parameterList != null) { - parameterList.replace(newParameterList); + JetParameterList newParameterList = null; + if (isLambda) { + if (parametersCount == 0 && ((JetFunctionLiteral) element).getTypeReference() == null) { + if (parameterList != null) { + parameterList.delete(); + ASTNode arrowNode = ((JetFunctionLiteral)element).getArrowNode(); + if (arrowNode != null) { + arrowNode.getPsi().delete(); + } + } + } + else { + newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignature(functionDescriptor, isInherited, hasExpectedType, 0)); + } + } + else { + newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature(functionDescriptor, isInherited, hasExpectedType, 0)); } - else if (element instanceof JetClass) { - PsiElement anchor = ((JetClass) element).getTypeParameterList(); - if (anchor == null) { - anchor = ((JetClass) element).getNameIdentifier(); + if (newParameterList != null) { + if (parameterList != null) { + newParameterList = (JetParameterList) parameterList.replace(newParameterList); } - if (anchor != null) { - element.addAfter(newParameterList, anchor); + else { + if (element instanceof JetClass) { + PsiElement anchor = ((JetClass) element).getTypeParameterList(); + + if (anchor == null) { + anchor = ((JetClass) element).getNameIdentifier(); + } + if (anchor != null) { + newParameterList = (JetParameterList) element.addAfter(newParameterList, anchor); + } + } + else if (isLambda) { + //noinspection ConstantConditions + JetFunctionLiteral functionLiteral = (JetFunctionLiteral) element; + PsiElement anchor = functionLiteral.getLBrace(); + newParameterList = (JetParameterList) element.addAfter(newParameterList, anchor); + if (functionLiteral.getArrowNode() == null) { + Pair whitespaceAndArrow = psiFactory.createWhitespaceAndArrow(); + element.addRangeAfter(whitespaceAndArrow.getFirst(), whitespaceAndArrow.getSecond(), newParameterList); + } + } } } + + if (newParameterList != null) { + ShortenPackage.addToShorteningWaitSet(newParameterList); + } } else if (parameterList != null) { int paramIndex = 0; for (JetParameter parameter : parameterList.getParameters()) { JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex++]; - changeParameter(changeInfo, element, parameter, parameterInfo); + changeParameter(changeInfo, parameter, parameterInfo); } + + ShortenPackage.addToShorteningWaitSet(parameterList); } if (changeInfo.isVisibilityChanged() && !JetPsiUtil.isLocal((JetDeclaration) element)) { @@ -116,7 +191,7 @@ public class JetFunctionDefinitionUsage extends JetUsageInfo { } } - private void changeParameter(JetChangeInfo changeInfo, PsiElement element, JetParameter parameter, JetParameterInfo parameterInfo) { + private void changeParameter(JetChangeInfo changeInfo, JetParameter parameter, JetParameterInfo parameterInfo) { ASTNode valOrVarAstNode = parameter.getValOrVarNode(); PsiElement valOrVarNode = valOrVarAstNode != null ? valOrVarAstNode.getPsi() : null; JetValVar valOrVar = parameterInfo.getValOrVar(); @@ -136,7 +211,7 @@ public class JetFunctionDefinitionUsage extends JetUsageInfo { parameter.addBefore(psiFactory.createWhiteSpace(), firstChild); } - if (parameterInfo.isTypeChanged()) { + if (parameterInfo.isTypeChanged() && parameter.getTypeReference() != null) { JetTypeReference newTypeRef = psiFactory.createType(parameterInfo.getTypeText()); parameter.setTypeReference(newTypeRef); } @@ -144,7 +219,7 @@ public class JetFunctionDefinitionUsage extends JetUsageInfo { PsiElement identifier = parameter.getNameIdentifier(); if (identifier != null) { - String newName = parameterInfo.getInheritedName(isInherited, element, changeInfo.getFunctionDescriptor()); + String newName = parameterInfo.getInheritedName(isInherited, functionDescriptor, changeInfo.getFunctionDescriptor()); identifier.replace(psiFactory.createIdentifier(newName)); } } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetParameterUsage.java b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetParameterUsage.java index 71bd8863117..8f2a7328e74 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetParameterUsage.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JetParameterUsage.java @@ -16,8 +16,8 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature.usages; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeInfo; import org.jetbrains.jet.plugin.refactoring.changeSignature.JetParameterInfo; @@ -26,19 +26,24 @@ import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory; public class JetParameterUsage extends JetUsageInfo { private final JetParameterInfo parameterInfo; - private final PsiElement function; + private final FunctionDescriptor functionDescriptor; private final boolean isInherited; - public JetParameterUsage(@NotNull JetSimpleNameExpression element, JetParameterInfo parameterInfo, PsiElement function, boolean inherited) { + public JetParameterUsage( + @NotNull JetSimpleNameExpression element, + JetParameterInfo parameterInfo, + FunctionDescriptor functionDescriptor, + boolean inherited + ) { super(element); this.parameterInfo = parameterInfo; - this.function = function; + this.functionDescriptor = functionDescriptor; isInherited = inherited; } @Override public boolean processUsage(JetChangeInfo changeInfo, JetSimpleNameExpression element) { - String newName = parameterInfo.getInheritedName(isInherited, function, changeInfo.getFunctionDescriptor()); + String newName = parameterInfo.getInheritedName(isInherited, functionDescriptor, changeInfo.getFunctionDescriptor()); element.replace(JetPsiFactory(element.getProject()).createSimpleName(newName)); return false; } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JavaMethodKotlinCallUsage.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/KotlinSAMUsage.kt similarity index 56% rename from idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JavaMethodKotlinCallUsage.kt rename to idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/KotlinSAMUsage.kt index 93d920b92dd..2903af3107a 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/JavaMethodKotlinCallUsage.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/changeSignature/usages/KotlinSAMUsage.kt @@ -16,15 +16,11 @@ package org.jetbrains.jet.plugin.refactoring.changeSignature.usages -import org.jetbrains.jet.lang.psi.JetCallElement -import com.intellij.psi.PsiElement -import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeInfo import com.intellij.usageView.UsageInfo +import org.jetbrains.jet.lang.psi.JetFunctionLiteral +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor -public class JavaMethodKotlinCallUsage( - val callElement: JetCallElement, - val javaMethodChangeInfo: JetChangeInfo): UsageInfo(javaMethodChangeInfo.getMethod()) { - private val delegateUsage = JetFunctionCallUsage(callElement, javaMethodChangeInfo.getMethod(), false) - - fun processUsage(): Boolean = delegateUsage.processUsage(javaMethodChangeInfo, callElement) -} +public class KotlinSAMUsage( + val functionLiteral: JetFunctionLiteral, + val functionDescriptor: FunctionDescriptor +): UsageInfo(functionLiteral) diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/jetRefactoringUtil.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/jetRefactoringUtil.kt index 4da6e646544..b580d10e06d 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/jetRefactoringUtil.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/jetRefactoringUtil.kt @@ -63,6 +63,8 @@ import org.jetbrains.jet.renderer.DescriptorRenderer import com.intellij.openapi.util.text.StringUtil import javax.swing.Icon import org.jetbrains.jet.plugin.util.string.collapseSpaces +import org.jetbrains.jet.asJava.KotlinLightMethod +import com.intellij.psi.PsiMethod import org.jetbrains.jet.plugin.caches.resolve.analyze import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.descriptors.CallableDescriptor @@ -364,6 +366,8 @@ public fun chooseContainerElementIfNecessary( } } +public fun PsiElement.isTrueJavaMethod(): Boolean = this is PsiMethod && this !is KotlinLightMethod + fun compareDescriptors(d1: DeclarationDescriptor?, d2: DeclarationDescriptor?): Boolean { return d1 == d2 || (d1 != null && d2 != null && diff --git a/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListAfter.1.kt new file mode 100644 index 00000000000..73a2c6aca6a --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListAfter.1.kt @@ -0,0 +1,5 @@ +fun test() { + JTest.samTest(SAM { s -> " " }) + JTest.samTest(SAM { s -> " " }) + JTest.samTest(SAM { s -> " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListAfter.java b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListAfter.java new file mode 100644 index 00000000000..012dec6b83a --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListBefore.1.kt new file mode 100644 index 00000000000..a2b3563f7f3 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListBefore.1.kt @@ -0,0 +1,5 @@ +fun test() { + JTest.samTest(SAM { " " }) + JTest.samTest(SAM { () -> " " }) + JTest.samTest(SAM { -> " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListBefore.java b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListBefore.java new file mode 100644 index 00000000000..b40b374f7f6 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToEmptyParamListBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListAfter.1.kt new file mode 100644 index 00000000000..aa4ca782cc2 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListAfter.1.kt @@ -0,0 +1,3 @@ +fun test() { + JTest.samTest(SAM {(s, n, o) -> s + " " + n }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListAfter.java b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListAfter.java new file mode 100644 index 00000000000..64d94cd0921 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n, Object o); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListBefore.1.kt new file mode 100644 index 00000000000..95a93c212dc --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListBefore.1.kt @@ -0,0 +1,3 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " + n }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListBefore.java b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListBefore.java new file mode 100644 index 00000000000..53078b39004 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToNonEmptyParamListBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListAfter.1.kt new file mode 100644 index 00000000000..b369af61c4f --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListAfter.1.kt @@ -0,0 +1,5 @@ +fun test() { + JTest.samTest(SAM {(n, s) -> s + " " }) + JTest.samTest(SAM {(n, s) -> s + " " }) + JTest.samTest(SAM {(n, it) -> it + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListAfter.java b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListAfter.java new file mode 100644 index 00000000000..c2312bb3354 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(int n, String s); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListBefore.1.kt new file mode 100644 index 00000000000..6f7a69ac4f6 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListBefore.1.kt @@ -0,0 +1,5 @@ +fun test() { + JTest.samTest(SAM { s -> s + " " }) + JTest.samTest(SAM { (s) -> s + " " }) + JTest.samTest(SAM { it + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListBefore.java b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListBefore.java new file mode 100644 index 00000000000..48e097afbb2 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMAddToSingletonParamListBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeAfter.1.kt new file mode 100644 index 00000000000..8d622ae21b4 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeAfter.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (s, n): Any? -> s + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeAfter.java b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeAfter.java new file mode 100644 index 00000000000..ed481b6ea1a --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeAfter.java @@ -0,0 +1,7 @@ +interface SAM { + Object foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeBefore.1.kt new file mode 100644 index 00000000000..09de97025b5 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeBefore.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (s, n): String -> s + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeBefore.java b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeBefore.java new file mode 100644 index 00000000000..53078b39004 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeMethodReturnTypeBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeParamTypeAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeAfter.1.kt new file mode 100644 index 00000000000..4dd3f7e6524 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeAfter.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (s: Any?, n: Int) -> x + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeParamTypeAfter.java b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeAfter.java new file mode 100644 index 00000000000..a9bbc2773a8 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(Object s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeParamTypeBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeBefore.1.kt new file mode 100644 index 00000000000..ed09e73f976 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeBefore.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (s: String, n: Int) -> x + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMChangeParamTypeBefore.java b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeBefore.java new file mode 100644 index 00000000000..53078b39004 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMChangeParamTypeBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveParamAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMRemoveParamAfter.1.kt new file mode 100644 index 00000000000..8cea4b593f4 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveParamAfter.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { n -> s + " " }) + JTest.samTest(SAM { y -> x + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveParamAfter.java b/idea/testData/refactoring/changeSignature/SAMRemoveParamAfter.java new file mode 100644 index 00000000000..0fcfb7f2550 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveParamAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveParamBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMRemoveParamBefore.1.kt new file mode 100644 index 00000000000..7b9695cb6f5 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveParamBefore.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (x, y) -> x + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveParamBefore.java b/idea/testData/refactoring/changeSignature/SAMRemoveParamBefore.java new file mode 100644 index 00000000000..53078b39004 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveParamBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListAfter.1.kt new file mode 100644 index 00000000000..d108ed3fd81 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListAfter.1.kt @@ -0,0 +1,5 @@ +fun test() { + JTest.samTest(SAM { s + " " }) + JTest.samTest(SAM { s + " " }) + JTest.samTest(SAM { it + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListAfter.java b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListAfter.java new file mode 100644 index 00000000000..5cf721eab83 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListBefore.1.kt new file mode 100644 index 00000000000..6f7a69ac4f6 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListBefore.1.kt @@ -0,0 +1,5 @@ +fun test() { + JTest.samTest(SAM { s -> s + " " }) + JTest.samTest(SAM { (s) -> s + " " }) + JTest.samTest(SAM { it + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListBefore.java b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListBefore.java new file mode 100644 index 00000000000..48e097afbb2 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRemoveSingletonParamListBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameMethodAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMRenameMethodAfter.1.kt new file mode 100644 index 00000000000..d299446e880 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameMethodAfter.1.kt @@ -0,0 +1,3 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameMethodAfter.java b/idea/testData/refactoring/changeSignature/SAMRenameMethodAfter.java new file mode 100644 index 00000000000..02b821252fb --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameMethodAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String bar(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameMethodBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMRenameMethodBefore.1.kt new file mode 100644 index 00000000000..d299446e880 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameMethodBefore.1.kt @@ -0,0 +1,3 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameMethodBefore.java b/idea/testData/refactoring/changeSignature/SAMRenameMethodBefore.java new file mode 100644 index 00000000000..53078b39004 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameMethodBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameParamAfter.1.kt b/idea/testData/refactoring/changeSignature/SAMRenameParamAfter.1.kt new file mode 100644 index 00000000000..7b9695cb6f5 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameParamAfter.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (x, y) -> x + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameParamAfter.java b/idea/testData/refactoring/changeSignature/SAMRenameParamAfter.java new file mode 100644 index 00000000000..ca31a7f5608 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameParamAfter.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String p, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameParamBefore.1.kt b/idea/testData/refactoring/changeSignature/SAMRenameParamBefore.1.kt new file mode 100644 index 00000000000..7b9695cb6f5 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameParamBefore.1.kt @@ -0,0 +1,4 @@ +fun test() { + JTest.samTest(SAM { (s, n) -> s + " " }) + JTest.samTest(SAM { (x, y) -> x + " " }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/SAMRenameParamBefore.java b/idea/testData/refactoring/changeSignature/SAMRenameParamBefore.java new file mode 100644 index 00000000000..53078b39004 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/SAMRenameParamBefore.java @@ -0,0 +1,7 @@ +interface SAM { + String foo(String s, int n); +} + +class JTest { + static void samTest(SAM sam) { } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java index 0da5789cbbb..085f11c6275 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/changeSignature/JetChangeSignatureTest.java @@ -23,6 +23,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; @@ -44,10 +45,7 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle; import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory; import static org.jetbrains.jet.plugin.refactoring.changeSignature.ChangeSignaturePackage.getChangeSignatureDialog; @@ -359,6 +357,129 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase { ); } + public void testSAMAddToEmptyParamList() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + PsiType paramType = PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())); + return new ParameterInfoImpl[] { new ParameterInfoImpl(-1, "s", paramType) }; + } + } + ); + } + + public void testSAMAddToSingletonParamList() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + PsiParameter parameter = method.getParameterList().getParameters()[0]; + ParameterInfoImpl originalParameter = new ParameterInfoImpl(0, parameter.getName(), parameter.getType()); + ParameterInfoImpl newParameter = new ParameterInfoImpl(-1, "n", PsiType.INT); + + return new ParameterInfoImpl[] {newParameter, originalParameter}; + } + } + ); + } + + public void testSAMAddToNonEmptyParamList() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + ParameterInfoImpl[] originalParameters = super.getNewParameters(method); + ParameterInfoImpl[] newParameters = Arrays.copyOf(originalParameters, originalParameters.length + 1); + + PsiType paramType = PsiType.getJavaLangObject(getPsiManager(), GlobalSearchScope.allScope(getProject())); + newParameters[originalParameters.length] = new ParameterInfoImpl(-1, "o", paramType); + + return newParameters; + } + } + ); + } + + public void testSAMRemoveSingletonParamList() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + return new ParameterInfoImpl[0]; + } + } + ); + } + + public void testSAMRemoveParam() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + return ArrayUtil.remove(super.getNewParameters(method), 0); + } + } + ); + } + + public void testSAMRenameParam() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + ParameterInfoImpl[] newParameters = super.getNewParameters(method); + newParameters[0].setName("p"); + return newParameters; + } + } + ); + } + + public void testSAMChangeParamType() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + ParameterInfoImpl[] newParameters = super.getNewParameters(method); + newParameters[0].setType(PsiType.getJavaLangObject(getPsiManager(), GlobalSearchScope.allScope(getProject()))); + return newParameters; + } + } + ); + } + + public void testSAMRenameMethod() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @NotNull + @Override + String getNewName(@NotNull PsiMethod method) { + return "bar"; + } + } + ); + } + + public void testSAMChangeMethodReturnType() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @Nullable + @Override + PsiType getNewReturnType(@NotNull PsiMethod method) { + return PsiType.getJavaLangObject(getPsiManager(), GlobalSearchScope.allScope(getProject())); + } + } + ); + } + public void testFunctionRenameJavaUsages() throws Exception { JetChangeInfo changeInfo = getChangeInfo(); changeInfo.setNewName("bar");