diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt index 3e9745278ad..1410bdacc63 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiFactory.kt @@ -359,6 +359,11 @@ public class JetPsiFactory(private val project: Project) { return createClass("class A: $text").getDelegationSpecifiers().first() as JetDelegatorToSuperCall } + public fun createConstructorDelegationCall(text: String): JetConstructorDelegationCall { + val colonOrEmpty = if (text.isEmpty()) "" else ": " + return createClass("class A { constructor()$colonOrEmpty$text {}").getSecondaryConstructors().first().getDelegationCall()!! + } + public inner class IfChainBuilder() { private val sb = StringBuilder() private var first = true diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java index 5a17d39bd56..83e173730d7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetSecondaryConstructor.java @@ -83,7 +83,7 @@ public class JetSecondaryConstructor extends JetDeclarationStub() == unwrappedCandidate } } + else { + if (targets.any { unwrappedCandidate.isConstructorOf(it) }) return true + } if (this is PsiReferenceExpression && candidateTarget is JetObjectDeclaration && unwrappedTargets.size() == 1) { val referredClass = unwrappedTargets.first() if (referredClass is JetClass && candidateTarget in referredClass.getCompanionObjects()) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt index c7a0a6ce1c4..5d59976cc44 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt @@ -17,24 +17,34 @@ package org.jetbrains.kotlin.idea.search.usagesSearch import com.intellij.psi.PsiConstructorCall +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import com.intellij.psi.PsiReference +import com.intellij.psi.search.SearchScope import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.codegen.PropertyCodegen import org.jetbrains.kotlin.asJava.KotlinLightMethod +import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.resolve.OverrideResolver import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.idea.references.* import org.jetbrains.kotlin.idea.findUsages.UsageTypeUtils import org.jetbrains.kotlin.idea.findUsages.UsageTypeEnum import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor +import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest +import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors val JetDeclaration.descriptor: DeclarationDescriptor? get() = this.analyze().get(BindingContext.DECLARATION_TO_DESCRIPTOR, this) +val JetDeclaration.constructor: ConstructorDescriptor? + get() = this.analyze().get(BindingContext.CONSTRUCTOR, this) + val JetParameter.propertyDescriptor: PropertyDescriptor? get() = this.analyze().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, this) @@ -57,23 +67,6 @@ fun PsiReference.isImportUsage(): Boolean = getElement()!!.getNonStrictParentOfType() != null fun PsiReference.isConstructorUsage(jetClassOrObject: JetClassOrObject): Boolean = with (getElement()!!) { - fun getCallDescriptor(bindingContext: BindingContext): DeclarationDescriptor? { - val constructorCalleeExpression = getNonStrictParentOfType() - if (constructorCalleeExpression != null) { - return bindingContext.get(BindingContext.REFERENCE_TARGET, constructorCalleeExpression.getConstructorReferenceExpression()) - } - - val callExpression = getNonStrictParentOfType() - if (callExpression != null) { - val callee = callExpression.getCalleeExpression() - if (callee is JetReferenceExpression) { - return bindingContext.get(BindingContext.REFERENCE_TARGET, callee) - } - } - - return null - } - fun checkJavaUsage(): Boolean { val call = getNonStrictParentOfType() return call == getParent() && call?.resolveConstructor()?.getContainingClass()?.getNavigationElement() == jetClassOrObject @@ -82,9 +75,7 @@ fun PsiReference.isConstructorUsage(jetClassOrObject: JetClassOrObject): Boolean fun checkKotlinUsage(): Boolean { if (this !is JetElement) return false - val bindingContext = this.analyze() - - val descriptor = getCallDescriptor(bindingContext) + val descriptor = getConstructorCallDescriptor() if (descriptor !is ConstructorDescriptor) return false return DescriptorToSourceUtils.descriptorToDeclaration(descriptor.getContainingDeclaration()) == jetClassOrObject @@ -93,6 +84,76 @@ fun PsiReference.isConstructorUsage(jetClassOrObject: JetClassOrObject): Boolean checkJavaUsage() || checkKotlinUsage() } +private fun JetElement.getConstructorCallDescriptor(): DeclarationDescriptor? { + val bindingContext = this.analyze() + val constructorCalleeExpression = getNonStrictParentOfType() + if (constructorCalleeExpression != null) { + return bindingContext.get(BindingContext.REFERENCE_TARGET, constructorCalleeExpression.getConstructorReferenceExpression()) + } + + val callExpression = getNonStrictParentOfType() + if (callExpression != null) { + val callee = callExpression.getCalleeExpression() + if (callee is JetReferenceExpression) { + return bindingContext.get(BindingContext.REFERENCE_TARGET, callee) + } + } + + return null +} + +public fun PsiElement.processDelegationCallConstructorUsages(scope: SearchScope, process: (JetConstructorDelegationCall) -> Unit) { + processDelegationCallKotlinConstructorUsages(scope, process) + processDelegationCallJavaConstructorUsages(scope, process) +} + +private fun PsiElement.processDelegationCallKotlinConstructorUsages(scope: SearchScope, process: (JetConstructorDelegationCall) -> Unit) { + val klass = when (this) { + is JetSecondaryConstructor -> getClassOrObject() + is JetClass -> this + else -> return + } + + if (klass !is JetClass || this !is JetDeclaration) return + val descriptor = constructor ?: return + + processClassDelegationCallsToSpecifiedConstructor(klass, descriptor, process) + processInheritorsDelegatingCallToSpecifiedConstructor(klass, scope, descriptor, process) +} + +private fun PsiElement.processDelegationCallJavaConstructorUsages(scope: SearchScope, process: (JetConstructorDelegationCall) -> Unit) { + if (!(this is PsiMethod && isConstructor())) return + val klass = getContainingClass() ?: return + val descriptor = getJavaMethodDescriptor() as? ConstructorDescriptor ?: return + processInheritorsDelegatingCallToSpecifiedConstructor(klass, scope, descriptor, process) +} + + +private fun processInheritorsDelegatingCallToSpecifiedConstructor( + klass: PsiElement, + scope: SearchScope, + descriptor: ConstructorDescriptor, + process: (JetConstructorDelegationCall) -> Unit +) { + HierarchySearchRequest(klass, scope, false).searchInheritors().forEach() { + val unwrapped = it.unwrapped + if (unwrapped is JetClass) { + processClassDelegationCallsToSpecifiedConstructor(unwrapped, descriptor, process) + } + } +} + +private fun processClassDelegationCallsToSpecifiedConstructor( + klass: JetClass, constructor: DeclarationDescriptor, process: (JetConstructorDelegationCall) -> Unit +) { + for (secondaryConstructor in klass.getSecondaryConstructors()) { + val delegationCallDescriptor = secondaryConstructor.getDelegationCall()?.getConstructorCallDescriptor() + if (constructor == delegationCallDescriptor) { + process(secondaryConstructor.getDelegationCall()!!) + } + } +} + // Check if reference resolves to extension function whose receiver is the same as declaration's parent (or its superclass) // Used in extension search fun PsiReference.isExtensionOfDeclarationClassUsage(declaration: JetNamedDeclaration): Boolean = diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/JetElementDescriptionProvider.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/JetElementDescriptionProvider.kt index 5354232824b..7543cd4d99b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/JetElementDescriptionProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/JetElementDescriptionProvider.kt @@ -36,6 +36,7 @@ public class JetElementDescriptionProvider : ElementDescriptionProvider { is JetClass -> if (targetElement.isTrait()) "trait" else "class" is JetObjectDeclaration -> "object" is JetNamedFunction -> "function" + is JetSecondaryConstructor -> "constructor" is JetProperty -> "property" is JetTypeParameter -> "type parameter" is JetParameter -> "parameter" diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt index c3bc278c9dd..ebd02a0103e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt @@ -20,21 +20,16 @@ import com.intellij.find.findUsages.FindUsagesHandler import com.intellij.find.findUsages.FindUsagesHandlerFactory import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.JetNamedFunction import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindMemberUsagesHandler import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil -import org.jetbrains.kotlin.psi.JetProperty import com.intellij.find.findUsages.FindUsagesOptions -import org.jetbrains.kotlin.psi.JetTypeParameter import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinTypeParameterFindUsagesHandler -import org.jetbrains.kotlin.psi.JetParameter -import org.jetbrains.kotlin.psi.JetNamedDeclaration -import org.jetbrains.kotlin.psi.JetClassOrObject import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory import org.jetbrains.kotlin.idea.findUsages.handlers.DelegatingFindMemberUsagesHandler import org.jetbrains.kotlin.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator import com.intellij.openapi.extensions.Extensions +import org.jetbrains.kotlin.psi.* public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactory() { val javaHandlerFactory = JavaFindUsagesHandlerFactory(project) @@ -49,14 +44,15 @@ public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandle element is JetNamedFunction || element is JetProperty || element is JetParameter || - element is JetTypeParameter + element is JetTypeParameter || + element is JetSecondaryConstructor public override fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean): FindUsagesHandler? { val handler = when (element) { is JetClassOrObject -> KotlinFindClassUsagesHandler(element, this) - is JetNamedFunction, is JetProperty, is JetParameter -> { + is JetNamedFunction, is JetProperty, is JetParameter, is JetSecondaryConstructor -> { val declaration = element as JetNamedDeclaration if (forHighlightUsages) return KotlinFindMemberUsagesHandler.getInstance(declaration, this) diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.java b/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.java index 2a7cb988519..843e76a4c9b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.java +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.java @@ -26,11 +26,17 @@ import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; +import com.intellij.psi.search.SearchScope; import com.intellij.usageView.UsageInfo; import com.intellij.util.Processor; +import jet.runtime.typeinfo.JetValueParameter; +import kotlin.Function1; +import kotlin.Unit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.asJava.LightClassUtil; +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor; +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.idea.findUsages.*; import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindFunctionUsagesDialog; import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindPropertyUsagesDialog; @@ -38,6 +44,7 @@ import org.jetbrains.kotlin.idea.search.declarationsSearch.DeclarationsSearchPac import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest; import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearch; import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchHelper; +import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchPackage; import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchRequest; import org.jetbrains.kotlin.psi.*; @@ -155,6 +162,16 @@ public abstract class KotlinFindMemberUsagesHandler() { + @Override + public Unit invoke(PsiElement element) { + processUsage(processor, element); + return null; + } + }); + } + if (kotlinOptions.getSearchOverrides()) { DeclarationsSearchPackage.searchOverriders( new HierarchySearchRequest(element, options.searchScope, true) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureHandler.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureHandler.java index e7a7e4fdf64..1071ad0d7ec 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureHandler.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureHandler.java @@ -71,6 +71,10 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler { if (elementParent instanceof JetClass && ((JetClass) elementParent).getNameIdentifier() == element) { return elementParent; } + if (elementParent instanceof JetSecondaryConstructor && + ((JetSecondaryConstructor) elementParent).getConstructorKeyword() == element) { + return elementParent; + } JetCallElement call = PsiTreeUtil.getParentOfType(element, JetCallExpression.class, JetDelegatorToSuperCall.class); if (call == null) { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java index 0d8d7b8fd44..8ce2603a0ee 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java @@ -36,6 +36,7 @@ import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import kotlin.Function1; import kotlin.KotlinPackage; +import kotlin.Unit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; @@ -45,6 +46,7 @@ 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.idea.search.usagesSearch.UsagesSearchPackage; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; @@ -74,6 +76,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } else { findSAMUsages(info, result); + findConstructorDelegationUsages(info, result); } return result.toArray(new UsageInfo[result.size()]); @@ -93,7 +96,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro private static void findOneMethodUsages( @NotNull JetFunctionDefinitionUsage functionUsageInfo, JetChangeInfo changeInfo, - Set result + final Set result ) { boolean isInherited = functionUsageInfo.isInherited(); @@ -164,6 +167,16 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } } } + + UsagesSearchPackage.processDelegationCallConstructorUsages(functionPsi, functionPsi.getUseScope(), + new Function1() { + @Override + public Unit invoke(JetConstructorDelegationCall element) { + result.add(new JetConstructorDelegationCallUsage(element)); + return null; + } + }); + } private static void processInternalReferences( @@ -286,10 +299,30 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro JetType samCallType = context.get(BindingContext.EXPRESSION_TYPE, callExpression); if (samCallType == null) continue; - result.add(new KotlinSAMUsage(functionLiteral, functionDescriptor, samCallType)); + result.add(new DeferredSAMUsage(functionLiteral, functionDescriptor, samCallType)); } } + private static void findConstructorDelegationUsages(@NotNull ChangeInfo changeInfo, @NotNull final Set result) { + PsiElement method = changeInfo.getMethod(); + if (!(RefactoringPackage.isTrueJavaMethod(method))) return; + + PsiMethod psiMethod = (PsiMethod) method; + if (!psiMethod.isConstructor()) return; + + UsagesSearchPackage.processDelegationCallConstructorUsages( + psiMethod, + psiMethod.getUseScope(), + new Function1() { + @Override + public Unit invoke(JetConstructorDelegationCall element) { + result.add(new JavaConstructorDeferredUsageInDelegationCall(element)); + return null; + } + } + ); + } + @Override public MultiMap findConflicts(ChangeInfo info, Ref refUsages) { MultiMap result = new MultiMap(); @@ -467,7 +500,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro private JetMethodDescriptor originalJavaMethodDescriptor; private static boolean isJavaMethodUsage(UsageInfo usageInfo) { - if (usageInfo instanceof KotlinSAMUsage) return true; + if (usageInfo instanceof JavaMethodDeferredKotlinUsage) return true; // MoveRenameUsageInfo corresponds to non-Java usage of Java method return usageInfo instanceof MoveRenameUsageInfo @@ -475,26 +508,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } @Nullable - private static UsageInfo createReplacementUsage( - UsageInfo originalUsageInfo, - final JetChangeInfo javaMethodChangeInfo - ) { - if (originalUsageInfo instanceof KotlinSAMUsage) { - final KotlinSAMUsage samUsage = (KotlinSAMUsage) originalUsageInfo; - return new JavaMethodKotlinUsageWithDelegate(samUsage.getFunctionLiteral(), javaMethodChangeInfo) { - private final JetFunctionDefinitionUsage delegateUsage = new JetFunctionDefinitionUsage( - samUsage.getFunctionLiteral(), - samUsage.getFunctionDescriptor(), - javaMethodChangeInfo.getMethodDescriptor().getOriginalPrimaryFunction(), - samUsage.getSamCallType() - ); - - @NotNull - @Override - protected JetUsageInfo getDelegateUsage() { - return delegateUsage; - } - }; + private static UsageInfo createReplacementUsage(UsageInfo originalUsageInfo, JetChangeInfo javaMethodChangeInfo) { + if (originalUsageInfo instanceof JavaMethodDeferredKotlinUsage) { + return ((JavaMethodDeferredKotlinUsage) originalUsageInfo).resolve(javaMethodChangeInfo); } JetCallElement callElement = PsiTreeUtil.getParentOfType(originalUsageInfo.getElement(), JetCallElement.class); diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt new file mode 100644 index 00000000000..aefcb07b8a4 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2015 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 com.intellij.psi.PsiElement +import com.intellij.usageView.UsageInfo +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo +import org.jetbrains.kotlin.psi.JetConstructorDelegationCall +import org.jetbrains.kotlin.psi.JetFunction +import org.jetbrains.kotlin.psi.JetFunctionLiteral +import org.jetbrains.kotlin.types.JetType + +public abstract class JavaMethodDeferredKotlinUsage(element: T): UsageInfo(element) { + abstract fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate +} + +public class DeferredSAMUsage( + val functionLiteral: JetFunctionLiteral, + val functionDescriptor: FunctionDescriptor, + val samCallType: JetType +): JavaMethodDeferredKotlinUsage(functionLiteral) { + override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate { + return object : JavaMethodKotlinUsageWithDelegate(functionLiteral, javaMethodChangeInfo) { + override val delegateUsage = JetFunctionDefinitionUsage( + functionLiteral, + functionDescriptor, + javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction, samCallType + ) + } + } +} + +public class JavaConstructorDeferredUsageInDelegationCall( + val delegationCall: JetConstructorDelegationCall +): JavaMethodDeferredKotlinUsage(delegationCall) { + override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate { + return object : JavaMethodKotlinUsageWithDelegate(delegationCall, javaMethodChangeInfo) { + override val delegateUsage = JetConstructorDelegationCallUsage(delegationCall) + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetConstructorDelegationCallUsage.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetConstructorDelegationCallUsage.kt new file mode 100644 index 00000000000..863a9e48089 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetConstructorDelegationCallUsage.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2015 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 com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo +import org.jetbrains.kotlin.lexer.JetTokens +import org.jetbrains.kotlin.psi.JetConstructorDelegationCall +import org.jetbrains.kotlin.psi.JetPsiFactory +import org.jetbrains.kotlin.psi.JetSecondaryConstructor + +public class JetConstructorDelegationCallUsage(call: JetConstructorDelegationCall) : JetUsageInfo(call) { + override fun processUsage(changeInfo: JetChangeInfo, element: JetConstructorDelegationCall): Boolean { + val isThisCall = element.getCalleeExpression()!!.isThis() + + val psiFactory = JetPsiFactory(element) + var elementToWorkWith = element + if (changeInfo.getNewParametersCount() > 0 && element.getCalleeExpression()!!.isEmpty()) { + val delegationKindName = if (isThisCall) "this" else "super" + elementToWorkWith = + element.replace(psiFactory.createConstructorDelegationCall("$delegationKindName()")) as JetConstructorDelegationCall + elementToWorkWith.getParent()!!.addBefore(psiFactory.createColon(), elementToWorkWith) + } + + val result = JetFunctionCallUsage( + elementToWorkWith, changeInfo.methodDescriptor.originalPrimaryFunction).processUsage(changeInfo, elementToWorkWith) + + if (changeInfo.getNewParametersCount() == 0 && !isThisCall && !elementToWorkWith.getCalleeExpression()!!.isEmpty()) { + (elementToWorkWith.getParent() as? JetSecondaryConstructor)?.getColon()?.delete() + elementToWorkWith.replace(psiFactory.createConstructorDelegationCall("")) + } + + return result + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java index f67ac60f5a9..08556d97c0c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JetFunctionDefinitionUsage.java @@ -179,9 +179,10 @@ public class JetFunctionDefinitionUsage extends JetUsageIn } } - boolean returnTypeIsNeeded = changeInfo.isRefactoringTarget(originalFunctionDescriptor) + boolean returnTypeIsNeeded = (changeInfo.isRefactoringTarget(originalFunctionDescriptor) || !(function instanceof JetFunctionLiteral) - || function.getTypeReference() != null; + || function.getTypeReference() != null) && + !(function instanceof JetSecondaryConstructor); if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) { function.setTypeReference(null); String returnTypeText = changeInfo.renderReturnType((JetFunctionDefinitionUsage) this); diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinSAMUsage.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinSAMUsage.kt deleted file mode 100644 index 736532fdc5e..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/KotlinSAMUsage.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2010-2015 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 com.intellij.usageView.UsageInfo -import org.jetbrains.kotlin.psi.JetFunctionLiteral -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.types.JetType - -public class KotlinSAMUsage( - val functionLiteral: JetFunctionLiteral, - val functionDescriptor: FunctionDescriptor, - val samCallType: JetType -): UsageInfo(functionLiteral)