[LL FIR] rewrote in-block modifications logic

Now we will invalidate bodies for FIR declarations
immediately after in-block modifications in these declarations
We assume that such in-block modifications can happen
only under write action,
so it should be safe to make changes for FirFile

^KT-59687 Fixed
^KT-59199 Fixed
^KTIJ-26066 Fixed
This commit is contained in:
Dmitrii Gridin
2023-06-30 17:47:58 +02:00
parent a50efd7aa2
commit e354b2a900
108 changed files with 1642 additions and 403 deletions
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.analysis.api.components.KtImportOptimizer
import org.jetbrains.kotlin.analysis.api.components.KtImportOptimizerResult
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
import org.jetbrains.kotlin.analysis.api.fir.isImplicitDispatchReceiver
import org.jetbrains.kotlin.analysis.api.fir.utils.FirBodyReanalyzingVisitorVoid
import org.jetbrains.kotlin.analysis.api.fir.utils.computeImportableName
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
@@ -34,6 +33,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
@@ -109,7 +109,7 @@ internal class KtFirImportOptimizer(
val usedImports = mutableMapOf<FqName, MutableSet<Name>>()
val unresolvedNames = mutableSetOf<Name>()
firFile.accept(object : FirBodyReanalyzingVisitorVoid(firResolveSession) {
firFile.accept(object : FirVisitorVoid() {
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.components.ElementsToShortenCollector.PartialOrderOfScope.Companion.toPartialOrder
import org.jetbrains.kotlin.analysis.api.fir.isImplicitDispatchReceiver
import org.jetbrains.kotlin.analysis.api.fir.references.KDocReferenceResolver
import org.jetbrains.kotlin.analysis.api.fir.utils.FirBodyReanalyzingVisitorVoid
import org.jetbrains.kotlin.analysis.api.fir.utils.computeImportableName
import org.jetbrains.kotlin.analysis.api.fir.utils.firSymbol
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
@@ -59,6 +58,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.*
@@ -359,8 +359,7 @@ private class ElementsToShortenCollector(
private val classShortenOption: (FirClassLikeSymbol<*>) -> ShortenOption,
private val callableShortenOption: (FirCallableSymbol<*>) -> ShortenOption,
private val firResolveSession: LLFirResolveSession,
) :
FirBodyReanalyzingVisitorVoid(firResolveSession) {
) : FirVisitorVoid() {
val typesToShorten: MutableList<ShortenType> = mutableListOf()
val qualifiersToShorten: MutableList<ShortenQualifier> = mutableListOf()
private val visitedProperty = mutableSetOf<FirProperty>()
@@ -370,8 +369,11 @@ private class ElementsToShortenCollector(
valueParameter.correspondingProperty?.let { visitProperty(it) }
}
override fun skipProperty(property: FirProperty): Boolean =
!visitedProperty.add(property)
override fun visitProperty(property: FirProperty) {
if (visitedProperty.add(property)) {
super.visitProperty(property)
}
}
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
@@ -1,150 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.fir.utils
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.psi.*
/**
* A hacky visitor which forces the resolve of declarations' bodies.
*
* Without it, a visitor might see FIR elements which are no longer connected via PSI to the current PSI file. Analysing such
* outdated element does not make any sense, because they do not represent the code in the editor.
*
* [acceptChildrenAndForceBodyReanalysis] functions are just copies of [org.jetbrains.kotlin.fir.FirPureAbstractElement.acceptChildren]
* functions from the respective receivers, except for the bodies/initializers - those are incrementally re-analyzed and visited
* separately.
*
* ATM we don't re-analyze constructors and init blocks because of KTIJ-25785. We also don't re-analyze the parts of the function's
* signature (like types, parameters or default values), because changes to them trigger OOB modification tracker,
* and the whole FIR is rebuilt.
*
* Important points:
* - We cannot just override [visitBlock] and do re-analysis there, because the block's PSI might be already disconnected
* from the PSI file. In such case, it's really hard to find the updated block's PSI.
* - For the same reason, we cannot take the PSI to re-analyze from the [org.jetbrains.kotlin.fir.expressions.FirBlock]s or
* [org.jetbrains.kotlin.fir.expressions.FirExpression]s - they might hold detached PSIs.
* Instead, we get the PSI of an outside declaration, and get the required PSI parts from it.
* - When KT-58257 is implemented, there might be no need for this hack, so we should consider removing it.
*/
internal abstract class FirBodyReanalyzingVisitorVoid(private val firResolveSession: LLFirResolveSession) : FirVisitorVoid() {
/**
* To avoid using labeled this in the [acceptChildrenAndForceBodyReanalysis] functions.
*/
private val thisVisitor: FirBodyReanalyzingVisitorVoid get() = this
final override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
if (simpleFunction.isLocal) {
super.visitSimpleFunction(simpleFunction)
} else {
simpleFunction.acceptChildrenAndForceBodyReanalysis()
}
}
final override fun visitProperty(property: FirProperty) {
if (skipProperty(property)) return
if (property.isLocal) {
super.visitProperty(property)
} else {
property.acceptChildrenAndForceBodyReanalysis()
}
}
final override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
propertyAccessor.acceptChildrenAndForceBodyReanalysis()
}
private fun FirSimpleFunction.acceptChildrenAndForceBodyReanalysis() {
status.accept(thisVisitor)
returnTypeRef.accept(thisVisitor)
receiverParameter?.accept(thisVisitor)
contextReceivers.forEach { it.accept(thisVisitor) }
controlFlowGraphReference?.accept(thisVisitor)
valueParameters.forEach { it.accept(thisVisitor) }
val simpleFunctionPsi = psi as? KtFunction
reanalyzePsiBody(simpleFunctionPsi)?.accept(thisVisitor)
contractDescription.accept(thisVisitor)
annotations.forEach { it.accept(thisVisitor) }
typeParameters.forEach { it.accept(thisVisitor) }
}
/**
* Return `true` from this method if you don't want to visit [property].
*/
protected open fun skipProperty(property: FirProperty): Boolean = false
private fun FirProperty.acceptChildrenAndForceBodyReanalysis() {
status.accept(thisVisitor)
returnTypeRef.accept(thisVisitor)
receiverParameter?.accept(thisVisitor)
val propertyPsi = psi as? KtProperty
reanalyzePsiInitializer(propertyPsi)?.accept(thisVisitor)
reanalyzePsiAccessorOrUseDefault(propertyPsi?.getter, getter)?.accept(thisVisitor)
reanalyzePsiAccessorOrUseDefault(propertyPsi?.setter, setter)?.accept(thisVisitor)
delegate?.accept(thisVisitor) // changes to the delegate cause OOB, no need to re-analyze it
backingField?.accept(thisVisitor) // not reanalyzed because it's not widely used
annotations.forEach { it.accept(thisVisitor) }
controlFlowGraphReference?.accept(thisVisitor)
contextReceivers.forEach { it.accept(thisVisitor) }
typeParameters.forEach { it.accept(thisVisitor) }
}
/**
* If there are default accessor present, we want to correctly visit it, because it can contain important
* information (annotations, for example).
*/
private fun reanalyzePsiAccessorOrUseDefault(
psiAccessor: KtPropertyAccessor?,
firAccessor: FirPropertyAccessor?,
): FirPropertyAccessor? =
if (psiAccessor == null) {
firAccessor as? FirDefaultPropertyAccessor
} else {
// we want only FirPropertyAccessors and nothing else, see KTIJ-25823
psiAccessor.getOrBuildFirSafe<FirPropertyAccessor>(firResolveSession)
}
/**
* N.B. Reanalysing single-expression body returns a [FirExpression], not
* [org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock].
*/
private fun reanalyzePsiBody(declaration: KtDeclarationWithBody?): FirExpression? =
declaration?.bodyExpression?.getOrBuildFirSafe<FirExpression>(firResolveSession)
private fun reanalyzePsiInitializer(declaration: KtDeclarationWithInitializer?): FirExpression? =
declaration?.initializer?.getOrBuildFirSafe<FirExpression>(firResolveSession)
private fun FirPropertyAccessor.acceptChildrenAndForceBodyReanalysis() {
status.accept(thisVisitor)
returnTypeRef.accept(thisVisitor)
contextReceivers.forEach { it.accept(thisVisitor) }
controlFlowGraphReference?.accept(thisVisitor)
valueParameters.forEach { it.accept(thisVisitor) }
val propertyAccessorPsi = psi as? KtPropertyAccessor
reanalyzePsiBody(propertyAccessorPsi)?.accept(thisVisitor)
contractDescription.accept(thisVisitor)
annotations.forEach { it.accept(thisVisitor) }
typeParameters.forEach { it.accept(thisVisitor) }
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
@@ -33,7 +34,9 @@ internal object FileElementFactory {
moduleComponents,
)
ktDeclaration is KtProperty && ktDeclaration.isReanalyzableContainer() -> ReanalyzablePropertyStructureElement(
ktDeclaration is KtProperty &&
(ktDeclaration.isReanalyzableContainer() || ktDeclaration.accessors.any { it.isReanalyzableContainer() })
-> ReanalyzablePropertyStructureElement(
firFile,
ktDeclaration,
(firDeclaration as FirProperty).symbol,
@@ -105,6 +108,11 @@ internal object FileElementFactory {
}
/**
* Covered by org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractInBlockModificationTest
* on the compiler side and by
* org.jetbrains.kotlin.idea.fir.analysis.providers.trackers.AbstractProjectWideOutOfBlockKotlinModificationTrackerTest
* on the plugin part
*
* @return The declaration in which a change of the passed receiver parameter can be treated as in-block modification
*/
@LLFirInternals
@@ -141,11 +149,19 @@ private fun isInsideContract(body: KtExpression, child: PsiElement): Boolean {
return firstStatement.isAncestor(child)
}
@TestOnly
internal fun KtDeclaration.isReanalyzableContainer(): Boolean = when (this) {
is KtNamedFunction -> isReanalyzableContainer()
is KtPropertyAccessor -> isReanalyzableContainer()
is KtProperty -> isReanalyzableContainer()
else -> error("Unknown declaration type: ${this::class.simpleName}")
}
private fun KtNamedFunction.isReanalyzableContainer(): Boolean = name != null && (hasBlockBody() || typeReference != null)
private fun KtPropertyAccessor.isReanalyzableContainer(): Boolean {
val property = property
return property.name != null && (hasBlockBody() || property.typeReference != null)
return property.name != null && (isSetter || hasBlockBody() || property.typeReference != null)
}
private fun KtProperty.isReanalyzableContainer(): Boolean =
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLoc
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceByTraversingWholeTree
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.declarations.FirFile
@@ -88,18 +87,21 @@ internal class FileStructure private constructor(
}
private fun getStructureElementForDeclaration(declaration: KtElement): FileStructureElement {
@Suppress("CANNOT_CHECK_FOR_ERASED")
val structureElement = structureElements.compute(declaration) { _, structureElement ->
when {
structureElement == null -> createStructureElement(declaration)
structureElement is ReanalyzableStructureElement<KtDeclaration, *> && !structureElement.isUpToDate() -> {
structureElement.reanalyze(newKtDeclaration = declaration as KtDeclaration)
structureElement is ReanalyzableStructureElement<*, *> && !structureElement.isUpToDate() -> {
structureElement.reanalyze()
}
else -> structureElement
}
}
return structureElement
?: error("FileStructureElement for was not defined for \n${declaration.getElementTextInContext()}")
return structureElement ?: errorWithFirSpecificEntries(
"FileStructureElement for was not defined for ${declaration::class.simpleName}",
psi = declaration,
)
}
fun getAllDiagnosticsForFile(diagnosticCheckerFilter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> {
@@ -112,7 +114,7 @@ internal class FileStructure private constructor(
private fun MutableCollection<KtPsiDiagnostic>.collectDiagnosticsFromStructureElements(
structureElements: Collection<FileStructureElement>,
diagnosticCheckerFilter: DiagnosticCheckerFilter
diagnosticCheckerFilter: DiagnosticCheckerFilter,
) {
structureElements.forEach { structureElement ->
structureElement.diagnostics.forEach(diagnosticCheckerFilter) { diagnostics ->
@@ -149,9 +151,8 @@ internal class FileStructure private constructor(
private fun createDeclarationStructure(declaration: KtDeclaration): FileStructureElement {
val firDeclaration = declaration.findSourceNonLocalFirDeclaration(
moduleComponents.firFileBuilder,
firFile,
firProvider,
firFile
)
firDeclaration.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
@@ -8,28 +8,19 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.ClassDiagnosticRetriever
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileDiagnosticRetriever
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileStructureElementDiagnostics
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLocalDeclarationBuilder
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.correspondingProperty
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.FirBackingFieldBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirFunctionBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirPropertyBuilder
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.psi.*
import java.util.concurrent.ConcurrentHashMap
internal sealed class FileStructureElement(val firFile: FirFile, protected val moduleComponents: LLFirModuleResolveComponents) {
abstract val psi: KtAnnotated
@@ -65,12 +56,9 @@ internal sealed class ReanalyzableStructureElement<KT : KtDeclaration, S : FirBa
abstract val timestamp: Long
/**
* Creates new declaration by [newKtDeclaration] which will serve as replacement of [firSymbol]
* Also, modify [firFile] & replace old version of declaration with a new one
* Recreate [mappings] and [diagnostics]
*/
abstract fun reanalyze(
newKtDeclaration: KT,
): ReanalyzableStructureElement<KT, S>
abstract fun reanalyze(): ReanalyzableStructureElement<KT, S>
fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp
@@ -94,33 +82,14 @@ internal class ReanalyzableFunctionStructureElement(
) : ReanalyzableStructureElement<KtNamedFunction, FirFunctionSymbol<*>>(firFile, firSymbol, moduleComponents) {
override val mappings = KtToFirMapping(firSymbol.fir, recorder)
override fun reanalyze(newKtDeclaration: KtNamedFunction): ReanalyzableFunctionStructureElement {
val originalFunction = firSymbol.fir as FirSimpleFunction
val originalDesignation = originalFunction.collectDesignation()
override fun reanalyze(): ReanalyzableFunctionStructureElement {
firSymbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
val newFunction = RawFirNonLocalDeclarationBuilder.buildNewSimpleFunction(
session = originalFunction.moduleData.session,
scopeProvider = originalFunction.moduleData.session.kotlinScopeProvider,
designation = originalDesignation,
newFunction = newKtDeclaration,
additionalFunctionInit = {
copyUnmodifiableFieldsForFunction(originalFunction)
},
)
newFunction.apply {
copyAllExceptBodyForFunction(originalFunction)
@OptIn(ResolveStateAccess::class)
resolveState = FirResolvePhase.STATUS.asResolveState()
}
newFunction.bodyResolveOnAir(originalDesignation, firFile, moduleComponents)
return ReanalyzableFunctionStructureElement(
firFile,
newKtDeclaration,
newFunction.symbol,
newKtDeclaration.modificationStamp,
psi,
firSymbol,
psi.modificationStamp,
moduleComponents,
)
}
@@ -135,67 +104,14 @@ internal class ReanalyzablePropertyStructureElement(
) : ReanalyzableStructureElement<KtProperty, FirPropertySymbol>(firFile, firSymbol, moduleComponents) {
override val mappings = KtToFirMapping(firSymbol.fir, recorder)
override fun reanalyze(newKtDeclaration: KtProperty): ReanalyzablePropertyStructureElement {
val originalProperty = firSymbol.fir
val originalDesignation = originalProperty.collectDesignation()
override fun reanalyze(): ReanalyzablePropertyStructureElement {
firSymbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
val newProperty = RawFirNonLocalDeclarationBuilder.buildNewProperty(
session = originalProperty.moduleData.session,
scopeProvider = originalProperty.moduleData.session.kotlinScopeProvider,
designation = originalDesignation,
newProperty = newKtDeclaration,
additionalPropertyInit = {
copyUnmodifiableFieldsForProperty(originalProperty)
},
additionalAccessorInit = {
copyUnmodifiableFieldsForFunction(
if (isGetter) {
originalProperty.getter!!
} else {
originalProperty.setter!!
}
)
},
additionalBackingFieldInit = {
copyUnmodifiableFieldsForBackingField(originalProperty.backingField!!)
},
)
newProperty.apply {
copyAllExceptBodyFromCallable(originalProperty)
replaceBodyResolveState(FirPropertyBodyResolveState.NOTHING_RESOLVED)
@OptIn(ResolveStateAccess::class)
resolveState = FirResolvePhase.STATUS.asResolveState()
getter?.let { getter ->
getter.copyAllExceptBodyForFunction(originalProperty.getter!!)
@OptIn(ResolveStateAccess::class)
getter.resolveState = FirResolvePhase.STATUS.asResolveState()
}
setter?.let { setter ->
setter.copyAllExceptBodyForFunction(originalProperty.setter!!)
@OptIn(ResolveStateAccess::class)
setter.resolveState = FirResolvePhase.STATUS.asResolveState()
}
backingField?.let { backingField ->
backingField.copyAllExceptBodyFromCallable(originalProperty.backingField!!)
@OptIn(ResolveStateAccess::class)
backingField.resolveState = FirResolvePhase.STATUS.asResolveState()
}
}
newProperty.bodyResolveOnAir(originalDesignation, firFile, moduleComponents)
return ReanalyzablePropertyStructureElement(
firFile,
newKtDeclaration,
newProperty.symbol,
newKtDeclaration.modificationStamp,
psi,
firSymbol,
psi.modificationStamp,
moduleComponents,
)
}
@@ -284,7 +200,7 @@ internal class DanglingTopLevelModifierListStructureElement(
firFile: FirFile,
val fir: FirDeclaration,
moduleComponents: LLFirModuleResolveComponents,
override val psi: KtAnnotated
override val psi: KtAnnotated,
) :
FileStructureElement(firFile, moduleComponents) {
override val mappings = KtToFirMapping(fir, FirElementsRecorder())
@@ -312,55 +228,3 @@ internal class RootStructureElement(
}
}
}
private fun <C : FirCallableDeclaration> C.bodyResolveOnAir(
originalDesignation: FirDesignation,
firFile: FirFile,
moduleComponents: LLFirModuleResolveComponents
) {
val designationToResolveOnAir = FirDesignationWithFile(originalDesignation.path, this, firFile)
moduleComponents.firModuleLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
designationToResolveOnAir,
onAirCreatedDeclaration = false,
towerDataContextCollector = null
)
}
private fun FirPropertyBuilder.copyUnmodifiableFieldsForProperty(prototype: FirProperty) {
attributes = prototype.attributes
dispatchReceiverType = prototype.dispatchReceiverType
}
private fun FirFunctionBuilder.copyUnmodifiableFieldsForFunction(prototype: FirFunction) {
attributes = prototype.attributes
dispatchReceiverType = prototype.dispatchReceiverType
}
private fun FirBackingFieldBuilder.copyUnmodifiableFieldsForBackingField(prototype: FirBackingField) {
attributes = prototype.attributes
dispatchReceiverType = prototype.dispatchReceiverType
}
private fun <F : FirFunction> F.copyAllExceptBodyForFunction(prototype: F) {
this.copyAllExceptBodyFromCallable(prototype)
this.replaceValueParameters(prototype.valueParameters)
if (this is FirContractDescriptionOwner) {
this.replaceContractDescription((prototype as FirContractDescriptionOwner).contractDescription)
}
}
private fun <C : FirCallableDeclaration> C.copyAllExceptBodyFromCallable(prototype: C) {
this.replaceAnnotations(prototype.annotations)
this.replaceReturnTypeRef(prototype.returnTypeRef)
this.replaceReceiverParameter(prototype.receiverParameter)
this.replaceStatus(prototype.status)
this.replaceDeprecationsProvider(prototype.deprecationsProvider)
this.replaceContextReceivers(prototype.contextReceivers)
// TODO add replaceTypeParameter to FirCallableDeclaration instead of this unsafe case
(this.typeParameters as MutableList<FirTypeParameterRef>).apply {
clear()
addAll(prototype.typeParameters)
}
}
@@ -0,0 +1,166 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.openapi.application.ApplicationManager
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirInternals
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirLazyBlock
import org.jetbrains.kotlin.fir.expressions.FirLazyExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildLazyBlock
import org.jetbrains.kotlin.fir.expressions.builder.buildLazyExpression
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
import org.jetbrains.kotlin.psi.KtDeclaration
/**
* Must be called in a write action.
*/
@LLFirInternals
fun invalidateAfterInBlockModification(declaration: KtDeclaration) {
ApplicationManager.getApplication().assertIsWriteThread()
val project = declaration.project
val ktModule = ProjectStructureProvider.getModule(project, declaration, contextualModule = null)
val resolveSession = ktModule.getFirResolveSession(project)
when (val firDeclaration = declaration.resolveToFirSymbol(resolveSession).fir) {
is FirSimpleFunction -> firDeclaration.inBodyInvalidation()
is FirPropertyAccessor -> firDeclaration.inBodyInvalidation()
is FirProperty -> firDeclaration.inBodyInvalidation()
else -> errorWithFirSpecificEntries("Unknown declaration with body", fir = firDeclaration, psi = declaration)
}
}
/**
* Drop body and all related stuff.
* We should drop:
* * body
* * control flow graph reference, because it depends on the body
* * reduce phase if needed
*
* Depends on the body, but we shouldn't drop:
* * implicit type, because the change mustn't change the resulting type
* * contract, because a change inside a contract description is OOBM, so this function won't be called in this case
*
* Also, we shouldn't update somehow value parameters because they have their own "bodies" (a default value) and
* changes in them are OOBM, so it is not our case.
*/
private fun FirSimpleFunction.inBodyInvalidation() {
invalidateBody()
}
private fun FirFunction.invalidateBody(): FirResolvePhase? {
val body = body ?: return null
// the body is not yet resolved, so there is nothing to invalidate
if (body is FirLazyBlock) return null
val newPhase = phaseWithoutBody
decreasePhase(newPhase)
replaceBody(buildLazyBlock())
replaceControlFlowGraphReference(null)
if (this is FirContractDescriptionOwner) {
replaceContractDescription(FirEmptyContractDescription)
}
return newPhase
}
/**
* Drop body and all related stuff.
* We should drop:
* * initializer or delegate expression
* * control flow graph reference, because it depends on the initializer or delegate
* * body resolution state
* * reduce phase if needed
*
* Depends on the body, but we shouldn't drop:
* * implicit type, because the change mustn't change the resulting type
*
* Also, we shouldn't update the property accessors because they don't depend on the initializer or delegate.
* So it is fine to leave the phase of setter/getter/backing field as it is.
*/
private fun FirProperty.inBodyInvalidation() {
val blockIsInvalidated = invalidateInitializer() || invalidateDelegate()
// the block is not invalidated, so there is nothing to reanalyze
if (!blockIsInvalidated) return
decreasePhase(phaseWithoutBody)
replaceControlFlowGraphReference(null)
replaceBodyResolveState(FirPropertyBodyResolveState.NOTHING_RESOLVED)
}
/**
* Drop body and all related stuff.
* We should drop:
* * body
* * control flow graph reference, because it depends on the body
* * property body resolution state
* * reduce phase if needed
*
* Depends on the body, but we shouldn't drop:
* * implicit type, because the change mustn't change the resulting type
* * contract, because a change inside a contract description is OOBM, so this function won't be called in this case
*/
private fun FirPropertyAccessor.inBodyInvalidation() {
val newPhase = invalidateBody() ?: return
val property = propertySymbol.fir
property.decreasePhase(newPhase)
val newPropertyResolveState = if (isGetter) {
FirPropertyBodyResolveState.INITIALIZER_RESOLVED
} else {
FirPropertyBodyResolveState.INITIALIZER_AND_GETTER_RESOLVED
}
property.replaceBodyResolveState(minOf(property.bodyResolveState, newPropertyResolveState))
}
private fun FirProperty.invalidateInitializer(): Boolean = replaceWithLazyExpressionIfNeeded(::initializer, ::replaceInitializer)
private fun FirProperty.invalidateDelegate(): Boolean = replaceWithLazyExpressionIfNeeded(::delegate, ::replaceDelegate)
private inline fun replaceWithLazyExpressionIfNeeded(
expressionGetter: () -> FirExpression?,
replaceExpression: (FirExpression) -> Unit,
): Boolean {
val expression = expressionGetter() ?: return false
// the expression is not yet resolved, so there is nothing to invalidate
if (expression is FirLazyExpression) return false
replaceExpression(buildLazyExpression { source = expression.source })
return true
}
private val FirDeclaration.phaseWithoutBody: FirResolvePhase
get() {
val phaseBeforeBody = if (contractShouldBeResolved) {
FirResolvePhase.CONTRACTS.previous
} else {
FirResolvePhase.BODY_RESOLVE.previous
}
return minOf(phaseBeforeBody, resolvePhase)
}
private val FirDeclaration.contractShouldBeResolved: Boolean
get() = this is FirFunction && body?.statements?.firstOrNull() is FirContractCallBlock
private fun FirDeclaration.decreasePhase(newPhase: FirResolvePhase) {
@OptIn(ResolveStateAccess::class)
resolveState = newPhase.asResolveState()
}
@@ -16,10 +16,6 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.BodyBuildingMode
import org.jetbrains.kotlin.fir.builder.PsiRawFirBuilder
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.FirBackingFieldBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirFunctionBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirPropertyAccessorBuilder
import org.jetbrains.kotlin.fir.declarations.builder.FirPropertyBuilder
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirMultiDelegatedConstructorCall
@@ -41,27 +37,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
private val declarationToBuild: KtDeclaration,
private val functionsToRebind: Set<FirFunction>? = null,
private val replacementApplier: RawFirReplacement.Applier? = null,
private val additionalFunctionInit: FirFunctionBuilder.() -> Unit = {},
private val additionalPropertyInit: FirPropertyBuilder.() -> Unit = {},
private val additionalAccessorInit: FirPropertyAccessorBuilder.() -> Unit = {},
private val additionalBackingFieldInit: FirBackingFieldBuilder.() -> Unit = {},
) : PsiRawFirBuilder(session, baseScopeProvider, bodyBuildingMode = BodyBuildingMode.NORMAL) {
override fun FirFunctionBuilder.additionalFunctionInit() {
additionalFunctionInit.invoke(this)
}
override fun FirPropertyBuilder.additionalPropertyInit() {
additionalPropertyInit.invoke(this)
}
override fun FirPropertyAccessorBuilder.additionalPropertyAccessorInit() {
additionalAccessorInit.invoke(this)
}
override fun FirBackingFieldBuilder.additionalBackingFieldInit() {
additionalBackingFieldInit.invoke(this)
}
companion object {
fun buildNewFile(
session: FirSession,
@@ -72,54 +48,12 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
return builder.buildFirFile(file)
}
fun buildNewSimpleFunction(
session: FirSession,
scopeProvider: FirScopeProvider,
designation: FirDesignation,
newFunction: KtNamedFunction,
additionalFunctionInit: FirFunctionBuilder.() -> Unit,
): FirSimpleFunction {
val builder = RawFirNonLocalDeclarationBuilder(
session = session,
baseScopeProvider = scopeProvider,
originalDeclaration = designation.target as FirDeclaration,
declarationToBuild = newFunction,
additionalFunctionInit = additionalFunctionInit,
)
builder.context.packageFqName = newFunction.containingKtFile.packageFqName
return builder.moveNext(designation.path.iterator(), containingClass = null) as FirSimpleFunction
}
fun buildNewProperty(
session: FirSession,
scopeProvider: FirScopeProvider,
designation: FirDesignation,
newProperty: KtProperty,
additionalPropertyInit: FirPropertyBuilder.() -> Unit,
additionalAccessorInit: FirPropertyAccessorBuilder.() -> Unit,
additionalBackingFieldInit: FirBackingFieldBuilder.() -> Unit,
): FirProperty {
val builder = RawFirNonLocalDeclarationBuilder(
session = session,
baseScopeProvider = scopeProvider,
originalDeclaration = designation.target as FirDeclaration,
declarationToBuild = newProperty,
additionalPropertyInit = additionalPropertyInit,
additionalAccessorInit = additionalAccessorInit,
additionalBackingFieldInit = additionalBackingFieldInit,
)
builder.context.packageFqName = newProperty.containingKtFile.packageFqName
return builder.moveNext(designation.path.iterator(), containingClass = null) as FirProperty
}
fun buildWithReplacement(
session: FirSession,
scopeProvider: FirScopeProvider,
designation: FirDesignation,
rootNonLocalDeclaration: KtDeclaration,
replacement: RawFirReplacement?
replacement: RawFirReplacement?,
): FirDeclaration {
val replacementApplier = replacement?.Applier()
val builder = RawFirNonLocalDeclarationBuilder(
@@ -167,7 +101,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
override fun addCapturedTypeParameters(
status: Boolean,
declarationSource: KtSourceElement?,
currentFirTypeParameters: List<FirTypeParameterRef>
currentFirTypeParameters: List<FirTypeParameterRef>,
) {
if (originalDeclaration is FirTypeParameterRefsOwner && declarationSource?.psi == originalDeclaration.psi) {
super.addCapturedTypeParameters(status, declarationSource, originalDeclaration.typeParameters)
@@ -183,7 +117,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
override fun convertProperty(
property: KtProperty,
ownerRegularOrAnonymousObjectSymbol: FirClassSymbol<*>?,
ownerRegularClassTypeParametersCount: Int?
ownerRegularClassTypeParametersCount: Int?,
): FirProperty {
val replacementProperty = replacementApplier?.tryReplace(property) ?: property
check(replacementProperty is KtProperty)
@@ -199,7 +133,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
functionSymbol: FirFunctionSymbol<*>,
defaultTypeRef: FirTypeRef?,
valueParameterDeclaration: ValueParameterDeclaration,
additionalAnnotations: List<FirAnnotation>
additionalAnnotations: List<FirAnnotation>,
): FirValueParameter {
val replacementParameter = replacementApplier?.tryReplace(valueParameter) ?: valueParameter
check(replacementParameter is KtParameter)
@@ -214,7 +148,7 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
private fun extractContructorConversionParams(
classOrObject: KtClassOrObject,
constructor: KtConstructor<*>?
constructor: KtConstructor<*>?,
): ConstructorConversionParams {
val typeParameters = mutableListOf<FirTypeParameterRef>()
context.appendOuterTypeParameters(ignoreLastLevel = false, typeParameters)
@@ -24,16 +24,18 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
/**
* 'Non-local' stands for not local classes/functions/etc.
*/
internal fun KtDeclaration.findSourceNonLocalFirDeclaration(
firFileBuilder: LLFirFileBuilder,
provider: FirProvider,
containerFirFile: FirFile? = null,
): FirDeclaration {
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
): FirDeclaration = findSourceNonLocalFirDeclaration(
firFileBuilder.buildRawFirFileWithCaching(containingKtFile),
provider,
)
/**
* 'Non-local' stands for not local classes/functions/etc.
*/
internal fun KtDeclaration.findSourceNonLocalFirDeclaration(firFile: FirFile, provider: FirProvider): FirDeclaration {
// TODO test what way faster
if (isPhysical) {
// do not request providers with non-physical psi in order not to leak them there and
@@ -5,7 +5,7 @@ var x: Int = 10/* ReanalyzablePropertyStructureElement */
}
class X {/* NonReanalyzableClassDeclarationStructureElement */
var y: Int = 10/* NonReanalyzableNonClassDeclarationStructureElement */
var y: Int = 10/* ReanalyzablePropertyStructureElement */
get() = field
set(value) {
field = value
@@ -0,0 +1,9 @@
import kotlin.contracts.InvocationKind
inline fun f<caret>oo(block: () -> Unit) {
kotlin.contracts.contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
@@ -0,0 +1,21 @@
BEFORE MODIFICATION:
public final inline [ResolvedTo(BODY_RESOLVE)] fun foo([ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[Contract description] <
Q|kotlin|.<Unresolved name: contracts>#.<Unresolved name: contract>#(<L> = [ResolvedTo(RAW_FIR)] contract@fun <anonymous>(): <ERROR TYPE REF: Unresolved name: callsInPlace> <inline=Unknown> {
^ <Unresolved name: callsInPlace>#(R|<local>/block|, <Unresolved name: InvocationKind>#.<Unresolved name: EXACTLY_ONCE>#)
}
)
>
{
{
kotlin#.contracts#.contract#(<L> = [ResolvedTo(BODY_RESOLVE)] contract@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
callsInPlace#(block#, InvocationKind#.EXACTLY_ONCE#)
}
)
}
R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
AFTER MODIFICATION:
public final inline [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun foo([ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,19 @@
BEFORE MODIFICATION:
public final inline [ResolvedTo(BODY_RESOLVE)] fun foo([ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[R|Contract description]
<
CallsInPlace(block, EXACTLY_ONCE)
>
{
{
Q|kotlin/contracts|.R|kotlin/contracts/contract|(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=@ExtensionFunctionType kotlin/Function1<kotlin/contracts/ContractBuilder, kotlin/Unit>] contract@fun R|kotlin/contracts/ContractBuilder|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|<R|kotlin/Unit|>(R|<local>/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|)
}
)
}
R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
AFTER MODIFICATION:
public final inline [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun foo([ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,7 @@
class MyProducer {
fun produce(): Int = 4
}
fun MyProducer.test<caret>Fun(param1: Int = produce()) {
}
@@ -0,0 +1,6 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun R|MyProducer|.testFun([ResolvedTo(BODY_RESOLVE)] param1: R|kotlin/Int| = this@R|/testFun|.R|/MyProducer.produce|()): R|kotlin/Unit| {
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun R|MyProducer|.testFun([ResolvedTo(BODY_RESOLVE)] param1: R|kotlin/Int| = this@R|/testFun|.R|/MyProducer.produce|()): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
fun test<caret>Fun(param1: Int, param2: String = "str", param3: List<Int> = myList()) {
}
fun myList(): List<Int>
@@ -0,0 +1,6 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun testFun([ResolvedTo(BODY_RESOLVE)] param1: R|kotlin/Int|, [ResolvedTo(BODY_RESOLVE)] param2: R|kotlin/String| = String(str), [ResolvedTo(BODY_RESOLVE)] param3: R|kotlin/collections/List<kotlin/Int>| = R|/myList|()): R|kotlin/Unit| {
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun testFun([ResolvedTo(BODY_RESOLVE)] param1: R|kotlin/Int|, [ResolvedTo(BODY_RESOLVE)] param2: R|kotlin/String| = String(str), [ResolvedTo(BODY_RESOLVE)] param3: R|kotlin/collections/List<kotlin/Int>| = R|/myList|()): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,13 @@
import kotlin.contracts.contract
class A {
fun <caret>x() {
contract {
req
}
val a = doSmth("str")
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,21 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit|
[Contract description] <
<Unresolved name: contract>#(<L> = [ResolvedTo(RAW_FIR)] contract@fun <anonymous>(): <ERROR TYPE REF: Unresolved name: req> <inline=Unknown> {
^ <Unresolved name: req>#
}
)
>
{
{
contract#(<L> = [ResolvedTo(BODY_RESOLVE)] contract@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
req#
}
)
}
[ResolvedTo(BODY_RESOLVE)] lval a: R|kotlin/Int| = R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun x(): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,18 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit|
[R|Contract description]
<
>
{
{
R|kotlin/contracts/contract|(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=@ExtensionFunctionType kotlin/Function1<kotlin/contracts/ContractBuilder, kotlin/Unit>] contract@fun R|kotlin/contracts/ContractBuilder|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
<Unresolved name: req>#
}
)
}
[ResolvedTo(BODY_RESOLVE)] lval a: R|kotlin/Int| = R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun x(): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,9 @@
import kotlin.contracts.*
class A {
fun passLa<caret>mbdaValue(l: ContractBuilder.() -> Unit) {
contract(l)
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,14 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun passLambdaValue([ResolvedTo(BODY_RESOLVE)] l: R|ERROR CLASS: Symbol not found for ContractBuilder.() -> kotlin/Unit|): R|kotlin/Unit|
[Contract description] <
<Unresolved name: contract>#(R|<local>/l|)
>
{
{
contract#(l#)
}
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun passLambdaValue([ResolvedTo(BODY_RESOLVE)] l: R|ERROR CLASS: Symbol not found for ContractBuilder.() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,14 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun passLambdaValue([ResolvedTo(BODY_RESOLVE)] l: R|kotlin/contracts/ContractBuilder.() -> kotlin/Unit|): R|kotlin/Unit|
[Contract description] <
R|kotlin/contracts/contract|(R|<local>/l|)
>
{
{
R|kotlin/contracts/contract|(R|<local>/l|)
}
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun passLambdaValue([ResolvedTo(BODY_RESOLVE)] l: R|kotlin/contracts/ContractBuilder.() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,11 @@
class A {
fun <caret>x() {
contract {
req
}
val a = doSmth("str")
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,21 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit|
[Contract description] <
<Unresolved name: contract>#(<L> = [ResolvedTo(RAW_FIR)] contract@fun <anonymous>(): <ERROR TYPE REF: Unresolved name: req> <inline=Unknown> {
^ <Unresolved name: req>#
}
)
>
{
{
contract#(<L> = [ResolvedTo(BODY_RESOLVE)] contract@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
req#
}
)
}
[ResolvedTo(BODY_RESOLVE)] lval a: R|kotlin/Int| = R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun x(): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,7 @@
class A {
fun <caret>x(): Int {
return doSmth("str")
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Int| {
^x R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun x(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,7 @@
class A {
fun <caret>x() {
val a = doSmth("str")
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit| {
[ResolvedTo(BODY_RESOLVE)] lval a: R|kotlin/Int| = R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun x(): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
class A {
fun <caret>x(): Int = doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Int| {
^x R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun x(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
class A {
fun <caret>x() = doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtNamedFunction DECLARATION
@@ -0,0 +1,14 @@
import kotlin.contracts.contract
class A {
var x: Int
ge<caret>t() {
contract {
req
}
fun doSmth(i: String) = 4
return doSmth("str")
}
set(value) = Unit
}
@@ -0,0 +1,33 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int|
[Contract description] <
<Unresolved name: contract>#(<L> = [ResolvedTo(RAW_FIR)] contract@fun <anonymous>(): <ERROR TYPE REF: Unresolved name: req> <inline=Unknown> {
^ <Unresolved name: req>#
}
)
>
{
{
contract#(<L> = [ResolvedTo(BODY_RESOLVE)] contract@fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
req#
}
)
}
local final [ResolvedTo(BODY_RESOLVE)] fun doSmth([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/String|): R|kotlin/Int| {
^doSmth Int(4)
}
^ R|<local>/doSmth|(String(str))
}
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ Q|kotlin/Unit|
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] var x: R|kotlin/Int|
public [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] [ContainingClassKey=A] get(): R|kotlin/Int| { LAZY_BLOCK }
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ Q|kotlin/Unit|
}
@@ -0,0 +1,30 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int|
[R|Contract description]
<
>
{
{
R|kotlin/contracts/contract|(<L> = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=@ExtensionFunctionType kotlin/Function1<kotlin/contracts/ContractBuilder, kotlin/Unit>] contract@fun R|kotlin/contracts/ContractBuilder|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
<Unresolved name: req>#
}
)
}
local final [ResolvedTo(BODY_RESOLVE)] fun doSmth([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/String|): R|kotlin/Int| {
^doSmth Int(4)
}
^ R|<local>/doSmth|(String(str))
}
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ Q|kotlin/Unit|
}
AFTER MODIFICATION:
public final [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] var x: R|kotlin/Int|
public [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] [ContainingClassKey=A] get(): R|kotlin/Int| { LAZY_BLOCK }
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ Q|kotlin/Unit|
}
@@ -0,0 +1,7 @@
class A {
val x: Int
ge<caret>t() {
fun doSmth(i: String) = 4
return doSmth("str")
}
}
@@ -0,0 +1,13 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
local final [ResolvedTo(BODY_RESOLVE)] fun doSmth([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/String|): R|kotlin/Int| {
^doSmth Int(4)
}
^ R|<local>/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] get(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
class A {
val x: Int ge<caret>t() = doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1,9 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
^ R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] get(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,8 @@
class A {
val x
g<caret>et() {
return doSmth("str")
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,9 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
^ R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] get(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
class A {
val x ge<caret>t() = doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtPropertyAccessor DECLARATION
@@ -0,0 +1,6 @@
class A {
val <caret>x: Int by lazy {
fun doSmth(i: String) = 4
doSmth("str")
}
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,3 @@
class A {
val <caret>x: Int by ErrorDelegate()
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,6 @@
class A {
val x<caret>: Int = run {
fun doSmth(i: String) = 4
doSmth("str")
}
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,6 @@
class A {
val <caret>x by lazy {
fun doSmth(i: String) = 4
doSmth("str")
}
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,3 @@
class A {
val <caret>x by ErrorDelegate()
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,5 @@
class A {
val x<caret> = run {
doSmth("str")
}
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,8 @@
class A {
var x: Int = 1
se<caret>t(value) {
doSmth(value)
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,11 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
R|/doSmth<Inapplicable(INAPPLICABLE): /doSmth>#|(R|<local>/value|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,6 @@
class A {
var x: Int = 1
se<caret>t(value) = doSmth(value)
}
fun doSmth(i: String) = 4
@@ -0,0 +1,11 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ R|/doSmth<Inapplicable(INAPPLICABLE): /doSmth>#|(R|<local>/value|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,9 @@
class A {
var x
get() = 1
s<caret>et(value) {
doSmth(value)
}
}
fun doSmth(i: String) = 4
@@ -0,0 +1,15 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
^ Int(1)
}
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
R|/doSmth<Inapplicable(INAPPLICABLE): /doSmth>#|(R|<local>/value|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] var x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
^ Int(1)
}
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,7 @@
class A {
var x
get() = 1
s<caret>et(value) = doSmth(value)
}
fun doSmth(i: String) = 4
@@ -0,0 +1,15 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
^ Int(1)
}
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ R|/doSmth<Inapplicable(INAPPLICABLE): /doSmth>#|(R|<local>/value|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] var x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=A] get(): R|kotlin/Int| {
^ Int(1)
}
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] [ContainingClassKey=A] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,9 @@
fun fo<caret>o(arg: Any?, num: Int?, block: () -> Unit) contract [
returns() implies (arg is String),
returns() implies (num != null),
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] {
require(arg is String)
require(num != null)
block()
}
@@ -0,0 +1,15 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun foo([ResolvedTo(BODY_RESOLVE)] arg: R|kotlin/Any?|, [ResolvedTo(BODY_RESOLVE)] num: R|kotlin/Int?|, [ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit|
[Contract description] <
<Unresolved name: returns>#().<Unresolved name: implies>#((R|<local>/arg| is R|kotlin/String|)),
<Unresolved name: returns>#().<Unresolved name: implies>#(!=(R|<local>/num|, Null(null))),
<Unresolved name: callsInPlace>#(R|<local>/block|, <Unresolved name: InvocationKind>#.<Unresolved name: EXACTLY_ONCE>#)
>
{
<Unresolved name: require>#((R|<local>/arg| is R|kotlin/String|))
<Unresolved name: require>#(!=(R|<local>/num|, Null(null)))
R|<local>/block|.R|SubstitutionOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun foo([ResolvedTo(BODY_RESOLVE)] arg: R|kotlin/Any?|, [ResolvedTo(BODY_RESOLVE)] num: R|kotlin/Int?|, [ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
fun fo<caret>o(): Int {
return doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun foo(): R|kotlin/Int| {
^foo R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun foo(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,3 @@
fun f<caret>oo(): Int = doSmth("str")
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun foo(): R|kotlin/Int| {
^foo R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun foo(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,5 @@
fun f<caret>oo() {
doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] fun foo(): R|kotlin/Unit| {
R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] fun foo(): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,3 @@
fun fo<caret>o() = doSmth("str")
fun doSmth(i: String) = 4
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtNamedFunction DECLARATION
@@ -0,0 +1,5 @@
val x: Int
ge<caret>t() {
fun doSmth(i: String) = 4
return doSmth("str")
}
@@ -0,0 +1,13 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
local final [ResolvedTo(BODY_RESOLVE)] fun doSmth([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/String|): R|kotlin/Int| {
^doSmth Int(4)
}
^ R|<local>/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] get(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,3 @@
val x: Int g<caret>et() = doSmth("str")
fun doSmth(i: String) = 4
@@ -0,0 +1,9 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] get(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,6 @@
val x
g<caret>et() {
return doSmth("str")
}
fun doSmth(i: String) = 4
@@ -0,0 +1,9 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ R|/doSmth|(String(str))
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] get(): R|kotlin/Int| { LAZY_BLOCK }
@@ -0,0 +1,3 @@
val x get<caret>() = doSmth("str")
fun doSmth(i: String) = 4
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtPropertyAccessor DECLARATION
@@ -0,0 +1,4 @@
val x<caret>: Int by lazy {
fun doSmth(i: String) = 4
doSmth("str")
}
@@ -0,0 +1,18 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|by <Unresolved name: lazy>#(<L> = [ResolvedTo(RAW_FIR)] lazy@fun <anonymous>(): R|kotlin/Int| <inline=Unknown> {
local final [ResolvedTo(RAW_FIR)] fun doSmth([ResolvedTo(RAW_FIR)] i: R|kotlin/String|): R|kotlin/Int| {
^doSmth Int(4)
}
^ R|<local>/doSmth|(String(str))
}
)
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ D|/x|.<Unresolved name: getValue>#(Null(null), ::R|/x|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|by LAZY_EXPRESSION
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ D|/x|.<Unresolved name: getValue>#(Null(null), ::R|/x|)
}
@@ -0,0 +1 @@
val x<caret>: Int by ErrorDelegate()
@@ -0,0 +1,11 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|by <Unresolved name: ErrorDelegate>#()
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ D|/x|.<Unresolved name: getValue>#(Null(null), ::R|/x|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|by LAZY_EXPRESSION
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ D|/x|.<Unresolved name: getValue>#(Null(null), ::R|/x|)
}
@@ -0,0 +1,3 @@
val <caret>x: Int = doSmth("str")
fun doSmth(i: String) = 4
@@ -0,0 +1,7 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int| = R|/doSmth|(String(str))
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int| = LAZY_EXPRESSION
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
@@ -0,0 +1,4 @@
val x<caret> by lazy {
fun doSmth(i: String) = 4
doSmth("str")
}
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1 @@
val x<caret> by ErrorDelegate()
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,3 @@
val x<caret> = doSmth("str")
fun doSmth(i: String) = 4
@@ -0,0 +1 @@
IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION
@@ -0,0 +1,6 @@
var x: Int = 1
se<caret>t(value) {
doSmth(value)
}
fun doSmth(i: String): Unit = 4
@@ -0,0 +1,11 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
R|/doSmth<Inapplicable(INAPPLICABLE): /doSmth>#|(R|<local>/value|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,4 @@
var x: Int = 1
se<caret>t(value) = doSmth(value)
fun doSmth(i: String): Unit = 4
@@ -0,0 +1,11 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| {
^ R|/doSmth<Inapplicable(INAPPLICABLE): /doSmth>#|(R|<local>/value|)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] var x: R|kotlin/Int| = Int(1)
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int|
public [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] set([ResolvedTo(BODY_RESOLVE)] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK }
@@ -0,0 +1,7 @@
val x
get() = 1
se<caret>t(value) {
doSmth(value)
}
fun doSmth(i: String) = 4
@@ -0,0 +1,11 @@
BEFORE MODIFICATION:
public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ Int(1)
}
AFTER MODIFICATION:
public final [ResolvedTo(ANNOTATIONS_ARGUMENTS_MAPPING)] val x: R|kotlin/Int|
public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| {
^ Int(1)
}

Some files were not shown because too many files have changed in this diff Show More