From 4ef0096d46b4ac0ce423a5ba8e9cb65448832a93 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 4 Apr 2017 19:19:03 +0300 Subject: [PATCH] Refactoring: inline val / fun now use the common inliner This prevents their inconsistent work in some situations NB: breaks three tests if used alone --- ...or.kt => KotlinInlineCallableProcessor.kt} | 33 ++- .../inline/KotlinInlineFunctionDialog.kt | 3 +- .../inline/KotlinInlineValDialog.kt | 48 ++-- .../inline/KotlinInlineValHandler.kt | 228 +++--------------- .../explicateParameterTypes/It.kt.after | 2 +- .../ItMultiLine.kt.after | 2 +- .../Parenthesized.kt.after | 2 +- .../explicateParameterTypes/Simplest.kt.after | 2 +- .../property/InstanceProperty.kt.after | 1 + .../property/Library.kt | 5 + .../inline/InlineTestGenerated.java | 6 + 11 files changed, 111 insertions(+), 221 deletions(-) rename idea/src/org/jetbrains/kotlin/idea/refactoring/inline/{KotlinInlineFunctionProcessor.kt => KotlinInlineCallableProcessor.kt} (77%) create mode 100644 idea/testData/refactoring/inline/inlineVariableOrProperty/property/Library.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineCallableProcessor.kt similarity index 77% rename from idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionProcessor.kt rename to idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineCallableProcessor.kt index 69e778349a7..fe1f9ece66e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineCallableProcessor.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.refactoring.inline import com.intellij.lang.findUsages.DescriptiveNameUtil import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.refactoring.BaseRefactoringProcessor @@ -31,25 +32,34 @@ import org.jetbrains.kotlin.idea.codeInliner.replaceUsages import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtSimpleNameExpression -class KotlinInlineFunctionProcessor( +class KotlinInlineCallableProcessor( project: Project, private val replacementStrategy: CallableUsageReplacementStrategy, - private val function: KtNamedFunction, + private val declaration: KtCallableDeclaration, private val reference: KtSimpleNameReference?, private val inlineThisOnly: Boolean, - private val deleteAfter: Boolean + private val deleteAfter: Boolean, + private val assignments: Set = emptySet() ) : BaseRefactoringProcessor(project) { - private val commandName = "Inlining function ${DescriptiveNameUtil.getDescriptiveName(function)}" + private val kind = when (declaration) { + is KtNamedFunction -> "function" + is KtProperty -> if (declaration.isLocal) "local variable" else "property" + else -> "declaration" + } + + private val commandName = "Inlining $kind ${DescriptiveNameUtil.getDescriptiveName(declaration)}" override fun findUsages(): Array { if (inlineThisOnly && reference != null) return arrayOf(UsageInfo(reference)) val usages = runReadAction { val searchScope = KotlinSourceFilterScope.projectSources(GlobalSearchScope.projectScope(myProject), myProject) - ReferencesSearch.search(function, searchScope) + ReferencesSearch.search(declaration, searchScope) } return usages.map(::UsageInfo).toTypedArray() } @@ -58,20 +68,21 @@ class KotlinInlineFunctionProcessor( val simpleNameUsages = usages.mapNotNull { it.element as? KtSimpleNameExpression } replacementStrategy.replaceUsages( simpleNameUsages, - function, + declaration, myProject, commandName, { if (deleteAfter) { if (usages.size == simpleNameUsages.size) { - function.delete() + declaration.delete() + assignments.forEach(PsiElement::delete) } else { CommonRefactoringUtil.showErrorHint( - function.project, + declaration.project, null, "Cannot inline ${usages.size - simpleNameUsages.size}/${usages.size} usages", - "Inline Function", + "Inline $kind", null ) } @@ -90,9 +101,9 @@ class KotlinInlineFunctionProcessor( override fun getCodeReferencesText(usagesCount: Int, filesCount: Int) = RefactoringBundle.message("invocations.to.be.inlined", UsageViewBundle.getReferencesString(usagesCount, filesCount)) - override fun getElements() = arrayOf(function) + override fun getElements() = arrayOf(declaration) - override fun getProcessedElementsHeader() = "Function to inline" + override fun getProcessedElementsHeader() = "${kind.capitalize()} to inline" } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionDialog.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionDialog.kt index 9d8f5a30ef0..0e022bdeb8e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionDialog.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineFunctionDialog.kt @@ -20,7 +20,6 @@ import com.intellij.openapi.help.HelpManager import com.intellij.openapi.project.Project import com.intellij.refactoring.HelpID import com.intellij.refactoring.JavaRefactoringSettings -import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.inline.InlineOptionsDialog import org.jetbrains.kotlin.idea.codeInliner.CallableUsageReplacementStrategy import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getReturnTypeReference @@ -71,7 +70,7 @@ class KotlinInlineFunctionDialog( public override fun doAction() { invokeRefactoring( - KotlinInlineFunctionProcessor(project, replacementStrategy, function, reference, + KotlinInlineCallableProcessor(project, replacementStrategy, function, reference, inlineThisOnly = isInlineThisOnly || allowInlineThisOnly, deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration && !allowInlineThisOnly) ) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValDialog.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValDialog.kt index cb895c93e11..7f5d72cf9b4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValDialog.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValDialog.kt @@ -17,48 +17,64 @@ package org.jetbrains.kotlin.idea.refactoring.inline import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiReference +import com.intellij.psi.PsiElement import com.intellij.refactoring.JavaRefactoringSettings -import com.intellij.refactoring.inline.AbstractInlineLocalDialog +import com.intellij.refactoring.inline.InlineOptionsDialog +import org.jetbrains.kotlin.idea.codeInliner.CallableUsageReplacementStrategy +import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.psi.KtProperty class KotlinInlineValDialog( - element: KtProperty, - ref: PsiReference?, - private val occurrenceCount: Int -) : AbstractInlineLocalDialog(element.project, element, ref, occurrenceCount) { - private val property: KtProperty get() = myElement as KtProperty + private val property: KtProperty, + private val reference: KtSimpleNameReference?, + private val replacementStrategy: CallableUsageReplacementStrategy, + private val assignments: Set + ) : InlineOptionsDialog(property.project, true, property) { + + private var occurrenceCount = initOccurrencesNumber(property) private val kind = if (property.isLocal) "local variable" else "property" private val refactoringName = "Inline ${StringUtil.capitalizeWords(kind, true)}" init { - myInvokedOnReference = ref != null + myInvokedOnReference = reference != null title = refactoringName init() } + override fun allowInlineAll() = true + override fun getBorderTitle() = refactoringName override fun getNameLabelText() = "${kind.capitalize()} ${property.name}" - override fun getInlineAllText(): String? { - val occurrencesString = if (occurrenceCount >= 0) { - " (" + occurrenceCount + " occurrence" + (if (occurrenceCount == 1) ")" else "s)") - } else "" - return "Inline all references and remove the $kind" + occurrencesString - } + private val occurrencesString get() = if (occurrenceCount >= 0) { + " (" + occurrenceCount + " occurrence" + (if (occurrenceCount == 1) ")" else "s)") + } else "" + + override fun getInlineAllText() = + "Inline all references and remove the $kind" + occurrencesString + + override fun getKeepTheDeclarationText(): String? = + if (property.isWritable) "Inline all references and keep the $kind" + occurrencesString + else super.getKeepTheDeclarationText() override fun isInlineThis() = JavaRefactoringSettings.getInstance().INLINE_LOCAL_THIS override fun getInlineThisText() = "Inline this occurrence and leave the $kind" - override fun doAction() { + public override fun doAction() { + invokeRefactoring( + KotlinInlineCallableProcessor(project, replacementStrategy, property, reference, + inlineThisOnly = isInlineThisOnly, + deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration, + assignments = assignments) + ) + val settings = JavaRefactoringSettings.getInstance() if (myRbInlineThisOnly.isEnabled && myRbInlineAll.isEnabled) { settings.INLINE_LOCAL_THIS = isInlineThisOnly } - close(OK_EXIT_CODE) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt index 9881ae44181..70a1dd8bbda 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.kt @@ -16,51 +16,39 @@ package org.jetbrains.kotlin.idea.refactoring.inline -import com.google.common.collect.Sets +import com.intellij.codeInsight.TargetElementUtil import com.intellij.lang.Language import com.intellij.lang.refactoring.InlineActionHandler import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Editor -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable import com.intellij.openapi.project.Project import com.intellij.openapi.wm.WindowManager import com.intellij.psi.PsiElement -import com.intellij.psi.PsiReference -import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.refactoring.HelpID -import com.intellij.refactoring.JavaRefactoringSettings import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.analysis.analyzeInContext import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedRefactoringRequests -import org.jetbrains.kotlin.idea.core.ShortenReferences -import org.jetbrains.kotlin.idea.core.replaced -import org.jetbrains.kotlin.idea.refactoring.addTypeArgumentsIfNeeded +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.codeInliner.CallableUsageReplacementStrategy +import org.jetbrains.kotlin.idea.codeInliner.CodeToInlineBuilder +import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively -import org.jetbrains.kotlin.idea.refactoring.getQualifiedTypeArgumentList -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.resolve.ResolutionFacade -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.references.KtSimpleNameReference +import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.* +import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.utils.addIfNotNull -import org.jetbrains.kotlin.utils.sure -import java.util.* class KotlinInlineValHandler : InlineActionHandler() { - enum class InlineMode { - ALL, PRIMARY, NONE - } override fun isEnabledForLanguage(l: Language) = l == KotlinLanguage.INSTANCE @@ -69,46 +57,14 @@ class KotlinInlineValHandler : InlineActionHandler() { return element.getter == null && element.receiverTypeReference == null } - private fun doReplace(expression: KtExpression, replacement: KtExpression): List { - val parent = expression.parent - - if (parent is KtStringTemplateEntryWithExpression && - replacement is KtStringTemplateExpression && - // Do not mix raw and non-raw templates - parent.parent.firstChild.text == replacement.firstChild.text) { - val entriesToAdd = replacement.entries - val templateExpression = parent.parent as KtStringTemplateExpression - val inlinedExpressions = if (entriesToAdd.isNotEmpty()) { - val firstAddedEntry = templateExpression.addRangeBefore(entriesToAdd.first(), entriesToAdd.last(), parent) - val lastNewEntry = parent.prevSibling - val nextElement = parent.nextSibling - if (lastNewEntry is KtSimpleNameStringTemplateEntry && - lastNewEntry.expression != null && - !canPlaceAfterSimpleNameEntry(nextElement)) { - lastNewEntry.replace(KtPsiFactory(expression).createBlockStringTemplateEntry(lastNewEntry.expression!!)) - } - firstAddedEntry.siblings() - .take(entriesToAdd.size) - .mapNotNull { (it as? KtStringTemplateEntryWithExpression)?.expression } - .toList() - } - else emptyList() - - parent.delete() - return inlinedExpressions - } - - return listOf(expression.replaced(replacement)) - } - override fun inlineElement(project: Project, editor: Editor?, element: PsiElement) { val declaration = element as KtProperty val file = declaration.containingKtFile val name = declaration.name ?: return val references = ReferencesSearch.search(declaration) - val referenceExpressions = ArrayList() - val foreignUsages = ArrayList() + val referenceExpressions = mutableListOf() + val foreignUsages = mutableListOf() for (ref in references) { val refElement = ref.element ?: continue if (refElement !is KtElement) { @@ -123,7 +79,7 @@ class KotlinInlineValHandler : InlineActionHandler() { return showErrorHint(project, editor, "$kind '$name' is never used") } - val assignments = Sets.newHashSet() + val assignments = hashSetOf() referenceExpressions.forEach { expression -> val parent = expression.parent @@ -147,9 +103,6 @@ class KotlinInlineValHandler : InlineActionHandler() { ?: return reportAmbiguousAssignment(project, editor, name, assignments) } - val typeArgumentsForCall = getQualifiedTypeArgumentList(initializer) - val parametersForFunctionLiteral = getParametersForFunctionLiteral(initializer) - val referencesInOriginalFile = referenceExpressions.filter { it.containingFile == file } val isHighlighting = referencesInOriginalFile.isNotEmpty() highlightElements(project, editor, referencesInOriginalFile) @@ -158,61 +111,36 @@ class KotlinInlineValHandler : InlineActionHandler() { preProcessInternalUsages(initializer, referenceExpressions) } - fun performRefactoring() { - val primaryExpression = if (editor != null) { - val offset = editor.caretModel.offset - referenceExpressions.firstOrNull { it.textRange.contains(offset) } - } - else null - val primaryRef = primaryExpression?.mainReference + val descriptor = element.resolveToDescriptor() as VariableDescriptor + val expectedType = if (element.typeReference != null) + descriptor.returnType ?: TypeUtils.NO_EXPECTED_TYPE + else + TypeUtils.NO_EXPECTED_TYPE - val inlineMode = showDialog(declaration, primaryRef, referenceExpressions.size) - if (inlineMode == InlineMode.NONE) { - if (isHighlighting) { + val initializerCopy = initializer.copied() + fun analyzeInitializerCopy(): BindingContext { + return initializerCopy.analyzeInContext(initializer.getResolutionScope(), + contextExpression = initializer, + expectedType = expectedType) + } + + fun performRefactoring() { + val reference = editor?.let { TargetElementUtil.findReference(it, it.caretModel.offset) } as? KtSimpleNameReference + val replacementBuilder = CodeToInlineBuilder(descriptor, element.getResolutionFacade()) + val replacement = replacementBuilder.prepareCodeToInline(initializerCopy, emptyList(), ::analyzeInitializerCopy) + val replacementStrategy = CallableUsageReplacementStrategy(replacement) + + val dialog = KotlinInlineValDialog(declaration, reference, replacementStrategy, assignments) + + if (!ApplicationManager.getApplication().isUnitTestMode) { + dialog.show() + if (!dialog.isOK && isHighlighting) { val statusBar = WindowManager.getInstance().getStatusBar(project) statusBar?.info = RefactoringBundle.message("press.escape.to.remove.the.highlighting") } - return } - - val chosenExpressions = if (inlineMode == InlineMode.ALL) referenceExpressions else listOf(primaryExpression) - - project.executeWriteCommand(RefactoringBundle.message("inline.command", name)) { - val inlinedExpressions = chosenExpressions - .flatMap { referenceExpression -> - if (assignments.contains(referenceExpression!!.parent)) return@flatMap emptyList() - - val importDirective = referenceExpression.getStrictParentOfType() - if (importDirective != null) { - val reference = referenceExpression.getQualifiedElementSelector()?.mainReference - if (reference != null && reference.multiResolve(false).size <= 1) { - importDirective.delete() - } - - return@flatMap emptyList() - } - - doReplace(referenceExpression, initializer) - } - .mapNotNull { postProcessInternalReferences(it) } - - if (inlineMode == InlineMode.ALL) { - assignments.forEach { it.delete() } - declaration.delete() - } - - if (inlinedExpressions.isNotEmpty()) { - if (typeArgumentsForCall != null) { - inlinedExpressions.forEach { addTypeArgumentsIfNeeded(it, typeArgumentsForCall) } - } - - parametersForFunctionLiteral?.let { addFunctionLiteralParameterTypes(it, inlinedExpressions) } - - if (isHighlighting) { - highlightElements(project, editor, inlinedExpressions) - } - } - performDelayedRefactoringRequests(project) + else { + dialog.doAction() } } @@ -238,80 +166,4 @@ class KotlinInlineValHandler : InlineActionHandler() { CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("inline.variable.title"), HelpID.INLINE_VARIABLE) } - private fun showDialog(property: KtProperty, ref: PsiReference?, occurrenceCount: Int): InlineMode { - if (ApplicationManager.getApplication().isUnitTestMode) return InlineMode.ALL - if ((ref == null || occurrenceCount <= 1) && !EditorSettingsExternalizable.getInstance().isShowInlineLocalDialog) return InlineMode.ALL - - val dialog = KotlinInlineValDialog(property, ref, occurrenceCount) - if (!dialog.showAndGet()) return InlineMode.NONE - return if (JavaRefactoringSettings.getInstance().INLINE_LOCAL_THIS) InlineMode.PRIMARY else InlineMode.ALL - } - - private fun getParametersForFunctionLiteral(initializer: KtExpression): String? { - val functionLiteralExpression = initializer.unpackFunctionLiteral(true) ?: return null - val context = initializer.analyze(BodyResolveMode.PARTIAL) - val lambdaDescriptor = context.get(BindingContext.FUNCTION, functionLiteralExpression.functionLiteral) - if (lambdaDescriptor == null || ErrorUtils.containsErrorType(lambdaDescriptor)) return null - return lambdaDescriptor.valueParameters.joinToString { - it.name.asString() + ": " + IdeDescriptorRenderers.SOURCE_CODE.renderType(it.type) - } - } - - private fun addFunctionLiteralParameterTypes(parameters: String, inlinedExpressions: List) { - val containingFile = inlinedExpressions.first().containingKtFile - val resolutionFacade = containingFile.getResolutionFacade() - - val functionsToAddParameters = inlinedExpressions.mapNotNull { - val lambdaExpr = it.unpackFunctionLiteral(true).sure { "can't find function literal expression for " + it.text } - if (needToAddParameterTypes(lambdaExpr, resolutionFacade)) lambdaExpr else null - } - - val psiFactory = KtPsiFactory(containingFile) - for (lambdaExpr in functionsToAddParameters) { - val lambda = lambdaExpr.functionLiteral - - val currentParameterList = lambda.valueParameterList - val newParameterList = psiFactory.createParameterList("($parameters)") - if (currentParameterList != null) { - currentParameterList.replace(newParameterList) - } - else { - // TODO: Ugly code, need refactoring - val openBraceElement = lambda.lBrace - - val nextSibling = openBraceElement.nextSibling - val whitespaceToAdd = if (nextSibling is PsiWhiteSpace && nextSibling.text.contains("\n")) - nextSibling.copy() - else - null - - val whitespaceAndArrow = psiFactory.createWhitespaceAndArrow() - lambda.addRangeAfter(whitespaceAndArrow.first, whitespaceAndArrow.second, openBraceElement) - - lambda.addAfter(newParameterList, openBraceElement) - if (whitespaceToAdd != null) { - lambda.addAfter(whitespaceToAdd, openBraceElement) - } - } - ShortenReferences.DEFAULT.process(lambdaExpr.valueParameters) - } - } - - private fun needToAddParameterTypes( - lambdaExpression: KtLambdaExpression, - resolutionFacade: ResolutionFacade - ): Boolean { - val functionLiteral = lambdaExpression.functionLiteral - val context = resolutionFacade.analyze(lambdaExpression, BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) - return context.diagnostics.any { diagnostic -> - val factory = diagnostic.factory - val element = diagnostic.psiElement - val hasCantInferParameter = factory == Errors.CANNOT_INFER_PARAMETER_TYPE && - element.parent.parent == functionLiteral - val hasUnresolvedItOrThis = factory == Errors.UNRESOLVED_REFERENCE && - element.text == "it" && - element.getStrictParentOfType() == functionLiteral - hasCantInferParameter || hasUnresolvedItOrThis - } - } } diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/It.kt.after b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/It.kt.after index 12320844a7a..c4ee7c0917a 100644 --- a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/It.kt.after +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/It.kt.after @@ -1,3 +1,3 @@ fun foo() { - val ff = {(it: Int) -> it } + val ff = { it: Int -> it } } diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/ItMultiLine.kt.after b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/ItMultiLine.kt.after index 9789c6abf2c..9a673a154e4 100644 --- a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/ItMultiLine.kt.after +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/ItMultiLine.kt.after @@ -1,6 +1,6 @@ fun foo() { val ff = { - (it: Int) -> + it: Int -> it } } diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Parenthesized.kt.after b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Parenthesized.kt.after index da62790d86b..458dd5ffd83 100644 --- a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Parenthesized.kt.after +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Parenthesized.kt.after @@ -1,3 +1,3 @@ fun foo() { - val ff = (({(x: Int) -> x })) + val ff = (({ x: Int -> x })) } diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Simplest.kt.after b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Simplest.kt.after index 1f2ba71b0ad..ffa522dd18e 100644 --- a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Simplest.kt.after +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateParameterTypes/Simplest.kt.after @@ -1,3 +1,3 @@ fun foo() { - val ff = {(x: Int) -> x } + val ff = { x: Int -> x } } diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/property/InstanceProperty.kt.after b/idea/testData/refactoring/inline/inlineVariableOrProperty/property/InstanceProperty.kt.after index 7090a4747dc..8f04c53d79c 100644 --- a/idea/testData/refactoring/inline/inlineVariableOrProperty/property/InstanceProperty.kt.after +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/property/InstanceProperty.kt.after @@ -6,5 +6,6 @@ class Class { } fun f() { + Class() println(239) } \ No newline at end of file diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/property/Library.kt b/idea/testData/refactoring/inline/inlineVariableOrProperty/property/Library.kt new file mode 100644 index 00000000000..5305a705050 --- /dev/null +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/property/Library.kt @@ -0,0 +1,5 @@ +// ERROR: Cannot perform refactoring.\nVariable length has no initializer + +fun foo(s: String) { + val l = s.length +} \ 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 7b97dec6411..acc03bdaa8e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java @@ -982,6 +982,12 @@ public class InlineTestGenerated extends AbstractInlineTest { doTest(fileName); } + @TestMetadata("Library.kt") + public void testLibrary() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/inlineVariableOrProperty/property/Library.kt"); + doTest(fileName); + } + @TestMetadata("multiplePackages.kt") public void testMultiplePackages() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/inlineVariableOrProperty/property/multiplePackages.kt");