diff --git a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementBuilder.kt b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementBuilder.kt index e8db0e34c64..bc4f7edeadb 100644 --- a/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementBuilder.kt +++ b/idea/idea-replacement-engine/src/org/jetbrains/kotlin/idea/replacement/ReplacementBuilder.kt @@ -39,6 +39,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import java.util.* @@ -49,13 +51,14 @@ class ReplacementBuilder( fun buildReplacementExpression( expression: KtExpression, resolutionScope: LexicalScope, + expectedType: KotlinType = TypeUtils.NO_EXPECTED_TYPE, importFqNames: Collection = emptyList(), copyExpression: Boolean = true ): ReplacementExpression { @Suppress("NAME_SHADOWING") var expression = if (copyExpression) expression.copied() else expression - var bindingContext = analyzeInContext(expression, resolutionScope) + var bindingContext = analyzeInContext(expression, resolutionScope, expectedType) val typeArgsToAdd = ArrayList>() expression.forEachDescendantOfType { @@ -70,7 +73,7 @@ class ReplacementBuilder( } // reanalyze expression - new usages of type parameters may be added - bindingContext = analyzeInContext(expression, resolutionScope) + bindingContext = analyzeInContext(expression, resolutionScope, expectedType) } val receiversToAdd = ArrayList>() @@ -122,8 +125,7 @@ class ReplacementBuilder( return ReplacementExpression(expression, resultImportFqNames) } - //TODO: there can be expected type and maybe something else - private fun analyzeInContext(expression: KtExpression, scope: LexicalScope): BindingContext { + private fun analyzeInContext(expression: KtExpression, scope: LexicalScope, expectedType: KotlinType): BindingContext { val module = scope.ownerDescriptor.module val frontendService = if (module.builtIns.builtInsModule == module) { // TODO: doubtful place, do we require this module or not? Built-ins module doesn't have some necessary components... @@ -132,6 +134,6 @@ class ReplacementBuilder( else { resolutionFacade.getFrontendService(module, ExpressionTypingServices::class.java) } - return expression.analyzeInContext(scope, expressionTypingServices = frontendService) + return expression.analyzeInContext(scope, expectedType = expectedType, expressionTypingServices = frontendService) } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt index 1ed3da50e34..0e61ce067d1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt @@ -76,7 +76,7 @@ object ReplaceWithAnnotationAnalyzer { listOf(explicitImportsScope) + defaultImportsScopes) ?: return null return ReplacementBuilder(symbolDescriptor, resolutionFacade) - .buildReplacementExpression(expression, scope, importFqNames(annotation), copyExpression = false) + .buildReplacementExpression(expression, scope, importFqNames = importFqNames(annotation), copyExpression = false) } fun analyzeClassReplacement( diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionHandler.kt index bee98ef69e9..44471308fb4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionHandler.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.replacement.ReplacementBuilder import org.jetbrains.kotlin.idea.replacement.replaceUsagesInWholeProject import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.types.TypeUtils class KotlinInlineFunctionHandler: InlineActionHandler() { override fun isEnabledForLanguage(language: Language) = language == KotlinLanguage.INSTANCE @@ -48,8 +49,12 @@ class KotlinInlineFunctionHandler: InlineActionHandler() { val descriptor = element.resolveToDescriptor() as SimpleFunctionDescriptor val bodyExpression = element.bodyExpression!! + val expectedType = if (element.hasDeclaredReturnType()) + descriptor.returnType ?: TypeUtils.NO_EXPECTED_TYPE + else + TypeUtils.NO_EXPECTED_TYPE val replacement = ReplacementBuilder(descriptor, element.getResolutionFacade()) - .buildReplacementExpression(bodyExpression, bodyExpression.getResolutionScope()) + .buildReplacementExpression(bodyExpression, bodyExpression.getResolutionScope(), expectedType) val commandName = RefactoringBundle.message("inline.command", element.name) CallableUsageReplacementStrategy(replacement) diff --git a/idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt b/idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt new file mode 100644 index 00000000000..18ac96df0e8 --- /dev/null +++ b/idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt @@ -0,0 +1,6 @@ +fun f(): List = emptyList() + +fun main(args: Array) { + val list1 = f() + val list2: List = f() +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt.after b/idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt.after new file mode 100644 index 00000000000..2a60b08ec7e --- /dev/null +++ b/idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + val list1 = emptyList() + val list2: List = emptyList() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java index 670c455c7ee..90fe8c7b215 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java @@ -69,6 +69,12 @@ public class InlineTestGenerated extends AbstractInlineTest { doTest(fileName); } + @TestMetadata("ExplicitReturnType.kt") + public void testExplicitReturnType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/expressionBody/ExplicitReturnType.kt"); + doTest(fileName); + } + @TestMetadata("FromUsage.kt") public void testFromUsage() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/function/expressionBody/FromUsage.kt");