Minor: refactoring codeInliner package
This commit is contained in:
@@ -26,9 +26,9 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
|
||||
|
||||
class ClassUsageReplacementStrategy(
|
||||
typeReplacement: KtUserType?,
|
||||
constructorReplacement: CodeToInline?,
|
||||
project: Project
|
||||
typeReplacement: KtUserType?,
|
||||
constructorReplacement: CodeToInline?,
|
||||
project: Project
|
||||
) : UsageReplacementStrategy {
|
||||
|
||||
private val factory = KtPsiFactory(project)
|
||||
@@ -45,8 +45,7 @@ class ClassUsageReplacementStrategy(
|
||||
|
||||
constructorReplacementStrategy?.createReplacer(usage)?.let { return it }
|
||||
|
||||
val parent = usage.parent
|
||||
when (parent) {
|
||||
when (val parent = usage.parent) {
|
||||
is KtUserType -> {
|
||||
if (typeReplacement == null) return null
|
||||
return {
|
||||
@@ -91,8 +90,7 @@ class ClassUsageReplacementStrategy(
|
||||
|
||||
val result = if (expressionToReplace != newExpression) {
|
||||
expressionToReplace.replaced(newExpression)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
expressionToReplace
|
||||
}
|
||||
|
||||
|
||||
@@ -354,12 +354,11 @@ class CodeInliner<TCallElement : KtElement>(
|
||||
return Argument(valueAssigned, bindingContext.getType(valueAssigned))
|
||||
}
|
||||
|
||||
val resolvedArgument = resolvedCall.valueArguments[parameter]!!
|
||||
when (resolvedArgument) {
|
||||
when (val resolvedArgument = resolvedCall.valueArguments[parameter] ?: return null) {
|
||||
is ExpressionValueArgument -> {
|
||||
val valueArgument = resolvedArgument.valueArgument!!
|
||||
val expression = valueArgument.getArgumentExpression()!!
|
||||
expression.mark(USER_CODE_KEY)
|
||||
val valueArgument = resolvedArgument.valueArgument
|
||||
val expression = valueArgument?.getArgumentExpression()
|
||||
expression?.mark(USER_CODE_KEY) ?: return null
|
||||
if (valueArgument is LambdaArgument) {
|
||||
expression.mark(WAS_FUNCTION_LITERAL_ARGUMENT_KEY)
|
||||
}
|
||||
@@ -447,9 +446,9 @@ class CodeInliner<TCallElement : KtElement>(
|
||||
ShortenReferences { ShortenReferences.Options(removeThis = true) }.process(it, shortenFilter)
|
||||
}
|
||||
|
||||
newElements.forEach {
|
||||
newElements.forEach { element ->
|
||||
// clean up user data
|
||||
it.forEachDescendantOfType<KtExpression> {
|
||||
element.forEachDescendantOfType<KtExpression> {
|
||||
it.clear(USER_CODE_KEY)
|
||||
it.clear(CodeToInline.PARAMETER_USAGE_KEY)
|
||||
it.clear(CodeToInline.TYPE_PARAMETER_USAGE_KEY)
|
||||
@@ -457,7 +456,7 @@ class CodeInliner<TCallElement : KtElement>(
|
||||
it.clear(RECEIVER_VALUE_KEY)
|
||||
it.clear(WAS_FUNCTION_LITERAL_ARGUMENT_KEY)
|
||||
}
|
||||
it.forEachDescendantOfType<KtValueArgument> {
|
||||
element.forEachDescendantOfType<KtValueArgument> {
|
||||
it.clear(MAKE_ARGUMENT_NAMED_KEY)
|
||||
it.clear(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
|
||||
@@ -45,17 +45,17 @@ import org.jetbrains.kotlin.utils.sure
|
||||
import java.util.*
|
||||
|
||||
class CodeToInlineBuilder(
|
||||
private val targetCallable: CallableDescriptor,
|
||||
private val resolutionFacade: ResolutionFacade
|
||||
private val targetCallable: CallableDescriptor,
|
||||
private val resolutionFacade: ResolutionFacade
|
||||
) {
|
||||
private val psiFactory = KtPsiFactory(resolutionFacade.project)
|
||||
|
||||
//TODO: document that code will be modified
|
||||
fun prepareCodeToInline(
|
||||
mainExpression: KtExpression?,
|
||||
statementsBefore: List<KtExpression>,
|
||||
analyze: () -> BindingContext,
|
||||
reformat: Boolean
|
||||
mainExpression: KtExpression?,
|
||||
statementsBefore: List<KtExpression>,
|
||||
analyze: () -> BindingContext,
|
||||
reformat: Boolean
|
||||
): CodeToInline {
|
||||
var bindingContext = analyze()
|
||||
|
||||
@@ -113,8 +113,8 @@ class CodeToInlineBuilder(
|
||||
}
|
||||
|
||||
private fun needToAddParameterTypes(
|
||||
lambdaExpression: KtLambdaExpression,
|
||||
resolutionFacade: ResolutionFacade
|
||||
lambdaExpression: KtLambdaExpression,
|
||||
resolutionFacade: ResolutionFacade
|
||||
): Boolean {
|
||||
val functionLiteral = lambdaExpression.functionLiteral
|
||||
val context = resolutionFacade.analyze(lambdaExpression, BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
|
||||
@@ -122,15 +122,19 @@ class CodeToInlineBuilder(
|
||||
val factory = diagnostic.factory
|
||||
val element = diagnostic.psiElement
|
||||
val hasCantInferParameter = factory == Errors.CANNOT_INFER_PARAMETER_TYPE &&
|
||||
element.parent.parent == functionLiteral
|
||||
element.parent.parent == functionLiteral
|
||||
val hasUnresolvedItOrThis = factory == Errors.UNRESOLVED_REFERENCE &&
|
||||
element.text == "it" &&
|
||||
element.getStrictParentOfType<KtFunctionLiteral>() == functionLiteral
|
||||
element.text == "it" &&
|
||||
element.getStrictParentOfType<KtFunctionLiteral>() == functionLiteral
|
||||
hasCantInferParameter || hasUnresolvedItOrThis
|
||||
}
|
||||
}
|
||||
|
||||
private fun insertExplicitTypeArguments(codeToInline: MutableCodeToInline, bindingContext: BindingContext, analyze: () -> BindingContext): BindingContext {
|
||||
private fun insertExplicitTypeArguments(
|
||||
codeToInline: MutableCodeToInline,
|
||||
bindingContext: BindingContext,
|
||||
analyze: () -> BindingContext
|
||||
): BindingContext {
|
||||
val typeArgsToAdd = ArrayList<Pair<KtCallExpression, KtTypeArgumentList>>()
|
||||
codeToInline.forEachDescendantOfType<KtCallExpression> {
|
||||
if (InsertExplicitTypeArgumentsIntention.isApplicableTo(it, bindingContext)) {
|
||||
@@ -162,8 +166,7 @@ class CodeToInlineBuilder(
|
||||
if (expression.getReceiverExpression() == null) {
|
||||
if (target is ValueParameterDescriptor && target.containingDeclaration == targetCallable) {
|
||||
expression.putCopyableUserData(CodeToInline.PARAMETER_USAGE_KEY, target.name)
|
||||
}
|
||||
else if (target is TypeParameterDescriptor && target.containingDeclaration == targetCallable) {
|
||||
} else if (target is TypeParameterDescriptor && target.containingDeclaration == targetCallable) {
|
||||
expression.putCopyableUserData(CodeToInline.TYPE_PARAMETER_USAGE_KEY, target.name)
|
||||
}
|
||||
|
||||
@@ -187,9 +190,13 @@ class CodeToInlineBuilder(
|
||||
// add receivers in reverse order because arguments of a call were processed after the callee's name
|
||||
for ((expr, receiverExpression) in receiversToAdd.asReversed()) {
|
||||
val expressionToReplace = expr.parent as? KtCallExpression ?: expr
|
||||
codeToInline.replaceExpression(expressionToReplace,
|
||||
psiFactory.createExpressionByPattern("$0.$1", receiverExpression, expressionToReplace,
|
||||
reformat = reformat))
|
||||
codeToInline.replaceExpression(
|
||||
expressionToReplace,
|
||||
psiFactory.createExpressionByPattern(
|
||||
"$0.$1", receiverExpression, expressionToReplace,
|
||||
reformat = reformat
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,10 +95,10 @@ internal fun MutableCodeToInline.toNonMutable(): CodeToInline {
|
||||
}
|
||||
|
||||
internal inline fun <reified T : PsiElement> MutableCodeToInline.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> {
|
||||
return expressions.flatMap { it.collectDescendantsOfType<T>({ true }, predicate) }
|
||||
return expressions.flatMap { it.collectDescendantsOfType({ true }, predicate) }
|
||||
}
|
||||
|
||||
internal inline fun <reified T : PsiElement> MutableCodeToInline.forEachDescendantOfType(noinline action: (T) -> Unit) {
|
||||
expressions.forEach { it.forEachDescendantOfType<T>(action) }
|
||||
expressions.forEach { it.forEachDescendantOfType(action) }
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
|
||||
import java.util.*
|
||||
|
||||
internal abstract class ReplacementPerformer<TElement : KtElement>(
|
||||
protected val codeToInline: MutableCodeToInline,
|
||||
protected var elementToBeReplaced: TElement
|
||||
protected val codeToInline: MutableCodeToInline,
|
||||
protected var elementToBeReplaced: TElement
|
||||
) {
|
||||
protected val psiFactory = KtPsiFactory(elementToBeReplaced)
|
||||
|
||||
@@ -43,8 +43,8 @@ internal abstract class ReplacementPerformer<TElement : KtElement>(
|
||||
}
|
||||
|
||||
internal class AnnotationEntryReplacementPerformer(
|
||||
codeToInline: MutableCodeToInline,
|
||||
elementToBeReplaced: KtAnnotationEntry
|
||||
codeToInline: MutableCodeToInline,
|
||||
elementToBeReplaced: KtAnnotationEntry
|
||||
) : ReplacementPerformer<KtAnnotationEntry>(codeToInline, elementToBeReplaced) {
|
||||
|
||||
override fun doIt(postProcessing: (PsiChildRange) -> PsiChildRange): KtAnnotationEntry {
|
||||
@@ -63,21 +63,22 @@ internal class AnnotationEntryReplacementPerformer(
|
||||
assert(range.first is KtAnnotationEntry)
|
||||
val annotationEntry = range.first as KtAnnotationEntry
|
||||
val text = annotationEntry.valueArguments.single().getArgumentExpression()!!.text
|
||||
return annotationEntry.replaced(psiFactory.createAnnotationEntry("@" + text))
|
||||
return annotationEntry.replaced(psiFactory.createAnnotationEntry("@$text"))
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExpressionReplacementPerformer(
|
||||
codeToInline: MutableCodeToInline,
|
||||
expressionToBeReplaced: KtExpression
|
||||
codeToInline: MutableCodeToInline,
|
||||
expressionToBeReplaced: KtExpression
|
||||
) : ReplacementPerformer<KtExpression>(codeToInline, expressionToBeReplaced) {
|
||||
|
||||
fun KtExpression.replacedWithStringTemplate(templateExpression: KtStringTemplateExpression): KtExpression? {
|
||||
val parent = this.parent
|
||||
|
||||
return if (parent is KtStringTemplateEntryWithExpression
|
||||
// Do not mix raw and non-raw templates
|
||||
&& parent.parent.firstChild.text == templateExpression.firstChild.text) {
|
||||
// Do not mix raw and non-raw templates
|
||||
&& parent.parent.firstChild.text == templateExpression.firstChild.text
|
||||
) {
|
||||
|
||||
val entriesToAdd = templateExpression.entries
|
||||
val grandParentTemplateExpression = parent.parent as KtStringTemplateExpression
|
||||
@@ -87,17 +88,16 @@ internal class ExpressionReplacementPerformer(
|
||||
val nextElement = parent.nextSibling
|
||||
if (lastNewEntry is KtSimpleNameStringTemplateEntry &&
|
||||
lastNewEntry.expression != null &&
|
||||
!canPlaceAfterSimpleNameEntry(nextElement)) {
|
||||
!canPlaceAfterSimpleNameEntry(nextElement)
|
||||
) {
|
||||
lastNewEntry.replace(KtPsiFactory(this).createBlockStringTemplateEntry(lastNewEntry.expression!!))
|
||||
}
|
||||
grandParentTemplateExpression
|
||||
}
|
||||
else null
|
||||
} else null
|
||||
|
||||
parent.delete()
|
||||
result
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
replaced(templateExpression)
|
||||
}
|
||||
}
|
||||
@@ -129,8 +129,7 @@ internal class ExpressionReplacementPerformer(
|
||||
if (canDropElementToBeReplaced) {
|
||||
stub.delete()
|
||||
null
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stub.replaced(psiFactory.createExpression("Unit"))
|
||||
}
|
||||
}
|
||||
@@ -141,17 +140,14 @@ internal class ExpressionReplacementPerformer(
|
||||
var range = if (replaced != null) {
|
||||
if (insertedStatements.isEmpty()) {
|
||||
PsiChildRange.singleElement(replaced)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val statement = insertedStatements.first()
|
||||
PsiChildRange(statement, replaced.parentsWithSelf.first { it.parent == statement.parent })
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (insertedStatements.isEmpty()) {
|
||||
PsiChildRange.EMPTY
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
PsiChildRange(insertedStatements.first(), insertedStatements.last())
|
||||
}
|
||||
}
|
||||
@@ -160,8 +156,7 @@ internal class ExpressionReplacementPerformer(
|
||||
listener?.attach()
|
||||
try {
|
||||
range = postProcessing(range)
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
listener?.detach()
|
||||
}
|
||||
|
||||
@@ -214,8 +209,8 @@ internal class ExpressionReplacementPerformer(
|
||||
val runAfterReplacement = elementToBeReplaced.replaced(runExpression)
|
||||
val ktLambdaArgument = runAfterReplacement.lambdaArguments[0]
|
||||
val block = ktLambdaArgument.getLambdaExpression()?.bodyExpression
|
||||
?: throw KotlinExceptionWithAttachments("cant get body expression for $ktLambdaArgument")
|
||||
.withAttachment("ktLambdaArgument", ktLambdaArgument.text)
|
||||
?: throw KotlinExceptionWithAttachments("cant get body expression for $ktLambdaArgument")
|
||||
.withAttachment("ktLambdaArgument", ktLambdaArgument.text)
|
||||
elementToBeReplaced = block.statements.single()
|
||||
return elementToBeReplaced
|
||||
|
||||
@@ -231,7 +226,7 @@ internal class ExpressionReplacementPerformer(
|
||||
private fun <TElement : KtElement> withElementToBeReplacedPreserved(action: () -> TElement): TElement {
|
||||
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, Unit)
|
||||
val result = action()
|
||||
elementToBeReplaced = result.findDescendantOfType<KtExpression> { it.getCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY) != null }!!
|
||||
elementToBeReplaced = result.findDescendantOfType { it.getCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY) != null }!!
|
||||
elementToBeReplaced.putCopyableUserData(ELEMENT_TO_BE_REPLACED_KEY, null)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -51,72 +51,72 @@ interface UsageReplacementStrategy {
|
||||
private val LOG = Logger.getInstance(UsageReplacementStrategy::class.java)
|
||||
|
||||
fun UsageReplacementStrategy.replaceUsagesInWholeProject(
|
||||
targetPsiElement: PsiElement,
|
||||
progressTitle: String,
|
||||
commandName: String,
|
||||
postAction: () -> Unit = {}
|
||||
targetPsiElement: PsiElement,
|
||||
progressTitle: String,
|
||||
commandName: String,
|
||||
postAction: () -> Unit = {}
|
||||
) {
|
||||
val project = targetPsiElement.project
|
||||
ProgressManager.getInstance().run(
|
||||
object : Task.Modal(project, progressTitle, true) {
|
||||
override fun run(indicator: ProgressIndicator) {
|
||||
val usages = runReadAction {
|
||||
val searchScope = KotlinSourceFilterScope.projectSources(GlobalSearchScope.projectScope(project), project)
|
||||
ReferencesSearch.search(targetPsiElement, searchScope)
|
||||
.filterIsInstance<KtSimpleNameReference>()
|
||||
.map { ref -> ref.expression }
|
||||
}
|
||||
this@replaceUsagesInWholeProject.replaceUsages(usages, targetPsiElement, project, commandName, postAction)
|
||||
object : Task.Modal(project, progressTitle, true) {
|
||||
override fun run(indicator: ProgressIndicator) {
|
||||
val usages = runReadAction {
|
||||
val searchScope = KotlinSourceFilterScope.projectSources(GlobalSearchScope.projectScope(project), project)
|
||||
ReferencesSearch.search(targetPsiElement, searchScope)
|
||||
.filterIsInstance<KtSimpleNameReference>()
|
||||
.map { ref -> ref.expression }
|
||||
}
|
||||
})
|
||||
this@replaceUsagesInWholeProject.replaceUsages(usages, targetPsiElement, project, commandName, postAction)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun UsageReplacementStrategy.replaceUsages(
|
||||
usages: Collection<KtSimpleNameExpression>,
|
||||
targetPsiElement: PsiElement,
|
||||
project: Project,
|
||||
commandName: String,
|
||||
postAction: () -> Unit = {}
|
||||
usages: Collection<KtSimpleNameExpression>,
|
||||
targetPsiElement: PsiElement,
|
||||
project: Project,
|
||||
commandName: String,
|
||||
postAction: () -> Unit = {}
|
||||
) {
|
||||
GuiUtils.invokeLaterIfNeeded({
|
||||
project.executeWriteCommand(commandName) {
|
||||
val targetDeclaration = targetPsiElement as? KtNamedDeclaration
|
||||
project.executeWriteCommand(commandName) {
|
||||
val targetDeclaration = targetPsiElement as? KtNamedDeclaration
|
||||
|
||||
val usagesByFile = usages.groupBy { it.containingFile }
|
||||
val usagesByFile = usages.groupBy { it.containingFile }
|
||||
|
||||
val KEY = Key<Unit>("UsageReplacementStrategy.replaceUsages")
|
||||
val KEY = Key<Unit>("UsageReplacementStrategy.replaceUsages")
|
||||
|
||||
for ((file, usagesInFile) in usagesByFile) {
|
||||
usagesInFile.forEach { it.putCopyableUserData(KEY, Unit) }
|
||||
for ((file, usagesInFile) in usagesByFile) {
|
||||
usagesInFile.forEach { it.putCopyableUserData(KEY, Unit) }
|
||||
|
||||
// we should delete imports later to not affect other usages
|
||||
val importsToDelete = mutableListOf<KtImportDirective>()
|
||||
// we should delete imports later to not affect other usages
|
||||
val importsToDelete = mutableListOf<KtImportDirective>()
|
||||
|
||||
var usagesToProcess = usagesInFile
|
||||
while (usagesToProcess.isNotEmpty()) {
|
||||
if (processUsages(usagesToProcess, targetDeclaration, importsToDelete)) break
|
||||
var usagesToProcess = usagesInFile
|
||||
while (usagesToProcess.isNotEmpty()) {
|
||||
if (processUsages(usagesToProcess, targetDeclaration, importsToDelete)) break
|
||||
|
||||
// some usages may get invalidated we need to find them in the tree
|
||||
usagesToProcess = file.collectDescendantsOfType<KtSimpleNameExpression> { it.getCopyableUserData(KEY) != null }
|
||||
}
|
||||
// some usages may get invalidated we need to find them in the tree
|
||||
usagesToProcess = file.collectDescendantsOfType { it.getCopyableUserData(KEY) != null }
|
||||
}
|
||||
|
||||
file.forEachDescendantOfType<KtSimpleNameExpression> { it.putCopyableUserData(KEY, null) }
|
||||
|
||||
importsToDelete.forEach { it.delete() }
|
||||
}
|
||||
file.forEachDescendantOfType<KtSimpleNameExpression> { it.putCopyableUserData(KEY, null) }
|
||||
|
||||
postAction()
|
||||
}
|
||||
}, ModalityState.NON_MODAL)
|
||||
importsToDelete.forEach { it.delete() }
|
||||
}
|
||||
|
||||
postAction()
|
||||
}
|
||||
}, ModalityState.NON_MODAL)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false if some usages were invalidated
|
||||
*/
|
||||
private fun UsageReplacementStrategy.processUsages(
|
||||
usages: List<KtSimpleNameExpression>,
|
||||
targetDeclaration: KtNamedDeclaration?,
|
||||
importsToDelete: MutableList<KtImportDirective>
|
||||
usages: List<KtSimpleNameExpression>,
|
||||
targetDeclaration: KtNamedDeclaration?,
|
||||
importsToDelete: MutableList<KtImportDirective>
|
||||
): Boolean {
|
||||
var invalidUsagesFound = false
|
||||
for (usage in usages) {
|
||||
@@ -138,17 +138,18 @@ private fun UsageReplacementStrategy.processUsages(
|
||||
}
|
||||
|
||||
createReplacer(usage)?.invoke()
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
LOG.error(e)
|
||||
}
|
||||
}
|
||||
return !invalidUsagesFound
|
||||
}
|
||||
|
||||
private fun UsageReplacementStrategy.specialUsageProcessing(usage: KtSimpleNameExpression, targetDeclaration: KtNamedDeclaration?): Boolean {
|
||||
val usageParent = usage.parent
|
||||
when (usageParent) {
|
||||
private fun UsageReplacementStrategy.specialUsageProcessing(
|
||||
usage: KtSimpleNameExpression,
|
||||
targetDeclaration: KtNamedDeclaration?
|
||||
): Boolean {
|
||||
when (val usageParent = usage.parent) {
|
||||
is KtCallableReferenceExpression -> {
|
||||
val grandParent = usageParent.parent
|
||||
ConvertReferenceToLambdaIntention().applyTo(usageParent, null)
|
||||
@@ -166,7 +167,7 @@ private fun UsageReplacementStrategy.specialUsageProcessing(usage: KtSimpleNameE
|
||||
for (lambdaArgument in lambdaArguments) {
|
||||
val lambdaExpression = lambdaArgument.getLambdaExpression() ?: continue
|
||||
val functionDescriptor =
|
||||
lambdaExpression.functionLiteral.resolveToDescriptorIfAny() as? FunctionDescriptor ?: continue
|
||||
lambdaExpression.functionLiteral.resolveToDescriptorIfAny() as? FunctionDescriptor ?: continue
|
||||
if (functionDescriptor.valueParameters.isNotEmpty()) {
|
||||
specifySignature.applyTo(lambdaExpression, null)
|
||||
}
|
||||
@@ -183,7 +184,7 @@ private fun UsageReplacementStrategy.specialUsageProcessing(usage: KtSimpleNameE
|
||||
}
|
||||
|
||||
private fun UsageReplacementStrategy.doRefactoringInside(
|
||||
element: KtElement, targetName: String?, targetDescriptor: DeclarationDescriptor?
|
||||
element: KtElement, targetName: String?, targetDescriptor: DeclarationDescriptor?
|
||||
) {
|
||||
element.forEachDescendantOfType<KtSimpleNameExpression> { usage ->
|
||||
if (usage.isValid && usage.getReferencedName() == targetName) {
|
||||
|
||||
@@ -50,12 +50,12 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
* @param safeCall If true, then the whole code must not be executed if the [value] evaluates to null.
|
||||
*/
|
||||
internal fun MutableCodeToInline.introduceValue(
|
||||
value: KtExpression,
|
||||
valueType: KotlinType?,
|
||||
usages: Collection<KtExpression>,
|
||||
expressionToBeReplaced: KtExpression,
|
||||
nameSuggestion: String? = null,
|
||||
safeCall: Boolean = false
|
||||
value: KtExpression,
|
||||
valueType: KotlinType?,
|
||||
usages: Collection<KtExpression>,
|
||||
expressionToBeReplaced: KtExpression,
|
||||
nameSuggestion: String? = null,
|
||||
safeCall: Boolean = false
|
||||
) {
|
||||
assert(usages.all { this.containsStrictlyInside(it) })
|
||||
|
||||
@@ -100,12 +100,10 @@ internal fun MutableCodeToInline.introduceValue(
|
||||
}
|
||||
|
||||
replaceUsages(name)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
statementsBefore.add(0, value)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val useIt = !isNameUsed("it")
|
||||
val name = if (useIt) Name.identifier("it") else suggestName { !isNameUsed(it) }
|
||||
replaceUsages(name)
|
||||
@@ -139,17 +137,17 @@ fun String.nameHasConflictsInScope(lexicalScope: LexicalScope) = lexicalScope.ge
|
||||
}
|
||||
|
||||
private fun variableNeedsExplicitType(
|
||||
initializer: KtExpression,
|
||||
initializerType: KotlinType,
|
||||
context: KtExpression,
|
||||
resolutionScope: LexicalScope,
|
||||
bindingContext: BindingContext
|
||||
initializer: KtExpression,
|
||||
initializerType: KotlinType,
|
||||
context: KtExpression,
|
||||
resolutionScope: LexicalScope,
|
||||
bindingContext: BindingContext
|
||||
): Boolean {
|
||||
if (ErrorUtils.containsErrorType(initializerType)) return false
|
||||
val valueTypeWithoutExpectedType = initializer.computeTypeInContext(
|
||||
resolutionScope,
|
||||
context,
|
||||
dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
|
||||
resolutionScope,
|
||||
context,
|
||||
dataFlowInfo = bindingContext.getDataFlowInfoBefore(context)
|
||||
)
|
||||
return valueTypeWithoutExpectedType == null || ErrorUtils.containsErrorType(valueTypeWithoutExpectedType)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user