Refactoring

This commit is contained in:
Valentin Kipyatkov
2017-05-24 23:16:45 +03:00
parent d53aa28ddf
commit 986eaeb7ea
3 changed files with 31 additions and 41 deletions
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.codeInliner.CallableUsageReplacementStrategy
import org.jetbrains.kotlin.idea.codeInliner.PropertyUsageReplacementStrategy
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -64,7 +63,14 @@ class KotlinInlineFunctionHandler: InlineActionHandler() {
}
val descriptor = element.resolveToDescriptor() as SimpleFunctionDescriptor
val codeToInline = buildCodeToInline(element, descriptor.returnType, editor) ?: return
val codeToInline = buildCodeToInline(
element,
descriptor.returnType,
element.hasDeclaredReturnType(),
element.bodyExpression!!,
element.hasBlockBody(),
editor
) ?: return
val replacementStrategy = CallableUsageReplacementStrategy(codeToInline)
@@ -29,22 +29,16 @@ import com.intellij.refactoring.HelpID
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.codeInliner.CodeToInline
import org.jetbrains.kotlin.idea.codeInliner.CodeToInlineBuilder
import org.jetbrains.kotlin.idea.codeInliner.PropertyUsageReplacementStrategy
import org.jetbrains.kotlin.idea.core.copied
import org.jetbrains.kotlin.idea.project.builtIns
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.ReferenceAccess
import org.jetbrains.kotlin.idea.references.readWriteAccess
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtElement
@@ -52,8 +46,6 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.TypeUtils
class KotlinInlineValHandler : InlineActionHandler() {
@@ -93,16 +85,21 @@ class KotlinInlineValHandler : InlineActionHandler() {
val readReplacement: CodeToInline?
val writeReplacement: CodeToInline?
val assignmentToDelete: KtBinaryExpression?
val descriptor = declaration.resolveToDescriptor() as ValueDescriptor
val isTypeExplicit = declaration.typeReference != null
if (getter == null && setter == null) {
val initialization = extractInitialization(declaration, referenceExpressions, project, editor) ?: return
readReplacement = buildCodeToInline(declaration, initialization.value)
readReplacement = buildCodeToInline(declaration, descriptor.type, isTypeExplicit, initialization.value, false, editor) ?: return
writeReplacement = null
assignmentToDelete = initialization.assignment
}
else {
val descriptor = declaration.resolveToDescriptor() as PropertyDescriptor
readReplacement = getter?.let { buildCodeToInline(getter, descriptor.type, editor) ?: return }
writeReplacement = setter?.let { buildCodeToInline(setter, setter.builtIns.unitType, editor) ?: return }
readReplacement = getter?.let {
buildCodeToInline(getter, descriptor.type, isTypeExplicit, getter.bodyExpression!!, getter.hasBlockBody(), editor) ?: return
}
writeReplacement = setter?.let {
buildCodeToInline(setter, setter.builtIns.unitType, true, setter.bodyExpression!!, setter.hasBlockBody(), editor) ?: return
}
assignmentToDelete = null
}
@@ -175,24 +172,6 @@ class KotlinInlineValHandler : InlineActionHandler() {
}
}
private fun buildCodeToInline(declaration: KtProperty, initializer: KtExpression): CodeToInline {
val descriptor = declaration.resolveToDescriptor() as VariableDescriptor
val expectedType = if (declaration.typeReference != null)
descriptor.returnType ?: TypeUtils.NO_EXPECTED_TYPE
else
TypeUtils.NO_EXPECTED_TYPE
val initializerCopy = initializer.copied()
fun analyzeInitializerCopy(): BindingContext {
return initializerCopy.analyzeInContext(initializer.getResolutionScope(),
contextExpression = initializer,
expectedType = expectedType)
}
val codeToInlineBuilder = CodeToInlineBuilder(descriptor, declaration.getResolutionFacade())
return codeToInlineBuilder.prepareCodeToInline(initializerCopy, emptyList(), ::analyzeInitializerCopy)
}
private fun performRefactoring(
declaration: KtProperty,
readReplacement: CodeToInline?,
@@ -29,7 +29,6 @@ import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.refactoring.util.RefactoringMessageDialog
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
@@ -114,24 +113,30 @@ internal fun <E : KtElement> postProcessInternalReferences(inlinedElement: E): E
return pointer.element
}
internal fun buildCodeToInline(declaration: KtDeclarationWithBody, returnType: KotlinType?, editor: Editor?): CodeToInline? {
val bodyExpression = declaration.bodyExpression!!
val bodyCopy = bodyExpression.copied()
internal fun buildCodeToInline(
declaration: KtDeclaration,
returnType: KotlinType?,
isReturnTypeExplicit: Boolean,
bodyOrInitializer: KtExpression,
isBlockBody: Boolean,
editor: Editor?
): CodeToInline? {
val bodyCopy = bodyOrInitializer.copied()
val expectedType = if (!declaration.hasBlockBody() && declaration.hasDeclaredReturnType())
val expectedType = if (!isBlockBody && isReturnTypeExplicit)
returnType ?: TypeUtils.NO_EXPECTED_TYPE
else
TypeUtils.NO_EXPECTED_TYPE
fun analyzeBodyCopy(): BindingContext {
return bodyCopy.analyzeInContext(bodyExpression.getResolutionScope(),
contextExpression = bodyExpression,
return bodyCopy.analyzeInContext(bodyOrInitializer.getResolutionScope(),
contextExpression = bodyOrInitializer,
expectedType = expectedType)
}
val descriptor = declaration.resolveToDescriptor()
val builder = CodeToInlineBuilder(descriptor as CallableDescriptor, declaration.getResolutionFacade())
if (declaration.hasBlockBody()) {
if (isBlockBody) {
bodyCopy as KtBlockExpression
val statements = bodyCopy.statements