diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt index 09bc84ccd63..78dedfcbe91 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt @@ -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>() val unresolvedNames = mutableSetOf() - firFile.accept(object : FirBodyReanalyzingVisitorVoid(firResolveSession) { + firFile.accept(object : FirVisitorVoid() { override fun visitElement(element: FirElement) { element.acceptChildren(this) } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt index ecde81cd502..2e1e56502ff 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt @@ -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 = mutableListOf() val qualifiersToShorten: MutableList = mutableListOf() private val visitedProperty = mutableSetOf() @@ -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) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/FirBodyReanalyzingVisitorVoid.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/FirBodyReanalyzingVisitorVoid.kt deleted file mode 100644 index 5a7d1c56eef..00000000000 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/utils/FirBodyReanalyzingVisitorVoid.kt +++ /dev/null @@ -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(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(firResolveSession) - - private fun reanalyzePsiInitializer(declaration: KtDeclarationWithInitializer?): FirExpression? = - declaration?.initializer?.getOrBuildFirSafe(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) } - } -} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileElementFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileElementFactory.kt index 09165e09e3f..0308964e031 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileElementFactory.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileElementFactory.kt @@ -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 = diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt index 7dbbc0145e5..dc2df377ec4 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt @@ -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 && !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 { @@ -112,7 +114,7 @@ internal class FileStructure private constructor( private fun MutableCollection.collectDiagnosticsFromStructureElements( structureElements: Collection, - 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) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt index cb59a8d6487..921527fd758 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt @@ -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 + abstract fun reanalyze(): ReanalyzableStructureElement fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp @@ -94,33 +82,14 @@ internal class ReanalyzableFunctionStructureElement( ) : ReanalyzableStructureElement>(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(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.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.copyAllExceptBodyForFunction(prototype: F) { - this.copyAllExceptBodyFromCallable(prototype) - this.replaceValueParameters(prototype.valueParameters) - - if (this is FirContractDescriptionOwner) { - this.replaceContractDescription((prototype as FirContractDescriptionOwner).contractDescription) - } -} - -private fun 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).apply { - clear() - addAll(prototype.typeParameters) - } -} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/inBlockModification.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/inBlockModification.kt new file mode 100644 index 00000000000..6d16b0395a2 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/inBlockModification.kt @@ -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() +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt index ce0ccce4854..53cd6d1e9b9 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/RawFirNonLocalDeclarationBuilder.kt @@ -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? = 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 + currentFirTypeParameters: List, ) { 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 + additionalAnnotations: List, ): 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() context.appendOuterTypeParameters(ignoreLastLevel = false, typeParameters) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt index 985af944c90..90ff2a21788 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/declarationUtils.kt @@ -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 diff --git a/analysis/low-level-api-fir/testdata/fileStructure/propertyAccessors.kt b/analysis/low-level-api-fir/testdata/fileStructure/propertyAccessors.kt index 411f5aaa16c..baa56881652 100644 --- a/analysis/low-level-api-fir/testdata/fileStructure/propertyAccessors.kt +++ b/analysis/low-level-api-fir/testdata/fileStructure/propertyAccessors.kt @@ -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 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/contract.kt b/analysis/low-level-api-fir/testdata/inBlockModification/contract.kt new file mode 100644 index 00000000000..b280e2da61f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/contract.kt @@ -0,0 +1,9 @@ +import kotlin.contracts.InvocationKind + +inline fun foo(block: () -> Unit) { + kotlin.contracts.contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + + block() +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/contract.out_of_src_roots.txt b/analysis/low-level-api-fir/testdata/inBlockModification/contract.out_of_src_roots.txt new file mode 100644 index 00000000000..d0549a4eff8 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/contract.out_of_src_roots.txt @@ -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|.#.#( = [ResolvedTo(RAW_FIR)] contract@fun (): { + ^ #(R|/block|, #.#) + } + ) + > + { + { + kotlin#.contracts#.contract#( = [ResolvedTo(BODY_RESOLVE)] contract@fun .(): { + callsInPlace#(block#, InvocationKind#.EXACTLY_ONCE#) + } + ) + } + + R|/block|.R|SubstitutionOverride|() +} + +AFTER MODIFICATION: +public final inline [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun foo([ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/contract.txt b/analysis/low-level-api-fir/testdata/inBlockModification/contract.txt new file mode 100644 index 00000000000..e7c106948e1 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/contract.txt @@ -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|( = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=@ExtensionFunctionType kotlin/Function1] contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlin/contracts/ContractBuilder.callsInPlace|(R|/block|, Q|kotlin/contracts/InvocationKind|.R|kotlin/contracts/InvocationKind.EXACTLY_ONCE|) + } + ) + } + + R|/block|.R|SubstitutionOverride|() +} + +AFTER MODIFICATION: +public final inline [ResolvedTo(ARGUMENTS_OF_ANNOTATIONS)] fun foo([ResolvedTo(BODY_RESOLVE)] block: R|() -> kotlin/Unit|): R|kotlin/Unit| { LAZY_BLOCK } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.kt b/analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.kt new file mode 100644 index 00000000000..04244388efa --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.kt @@ -0,0 +1,7 @@ +class MyProducer { + fun produce(): Int = 4 +} + +fun MyProducer.testFun(param1: Int = produce()) { + +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.txt b/analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.txt new file mode 100644 index 00000000000..5fb4a5b05ed --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.kt b/analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.kt new file mode 100644 index 00000000000..045697fe11b --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.kt @@ -0,0 +1,5 @@ +fun testFun(param1: Int, param2: String = "str", param3: List = myList()) { + +} + +fun myList(): List \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.txt b/analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.txt new file mode 100644 index 00000000000..f2305d78d4f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.txt @@ -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| = 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| = R|/myList|()): R|kotlin/Unit| { LAZY_BLOCK } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.kt new file mode 100644 index 00000000000..a9a7d19f783 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.kt @@ -0,0 +1,13 @@ +import kotlin.contracts.contract + +class A { + fun x() { + contract { + req + } + + val a = doSmth("str") + } +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.out_of_src_roots.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.out_of_src_roots.txt new file mode 100644 index 00000000000..0e45a3a00a4 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.out_of_src_roots.txt @@ -0,0 +1,21 @@ +BEFORE MODIFICATION: +public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit| + [Contract description] < + #( = [ResolvedTo(RAW_FIR)] contract@fun (): { + ^ # + } + ) + > + { + { + contract#( = [ResolvedTo(BODY_RESOLVE)] contract@fun .(): { + 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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.txt new file mode 100644 index 00000000000..a2fb4e25c9e --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.txt @@ -0,0 +1,18 @@ +BEFORE MODIFICATION: +public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit| + [R|Contract description] + < + > + { + { + R|kotlin/contracts/contract|( = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=@ExtensionFunctionType kotlin/Function1] contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + # + } + ) + } + + [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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.kt new file mode 100644 index 00000000000..336c3a0acd1 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.kt @@ -0,0 +1,9 @@ +import kotlin.contracts.* + +class A { + fun passLambdaValue(l: ContractBuilder.() -> Unit) { + contract(l) + } +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.out_of_src_roots.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.out_of_src_roots.txt new file mode 100644 index 00000000000..49094530a81 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.out_of_src_roots.txt @@ -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] < + #(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.txt new file mode 100644 index 00000000000..405e349e6a1 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.txt @@ -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|/l|) + > + { + { + R|kotlin/contracts/contract|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.kt new file mode 100644 index 00000000000..5f56ce9b38a --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.kt @@ -0,0 +1,11 @@ +class A { + fun x() { + contract { + req + } + + val a = doSmth("str") + } +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.txt new file mode 100644 index 00000000000..0e45a3a00a4 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.txt @@ -0,0 +1,21 @@ +BEFORE MODIFICATION: +public final [ResolvedTo(BODY_RESOLVE)] fun x(): R|kotlin/Unit| + [Contract description] < + #( = [ResolvedTo(RAW_FIR)] contract@fun (): { + ^ # + } + ) + > + { + { + contract#( = [ResolvedTo(BODY_RESOLVE)] contract@fun .(): { + 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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.kt new file mode 100644 index 00000000000..3a0578c5f4e --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.kt @@ -0,0 +1,7 @@ +class A { + fun x(): Int { + return doSmth("str") + } +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.txt new file mode 100644 index 00000000000..d48eb3b1e2f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.kt new file mode 100644 index 00000000000..7b3c1bff2d4 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.kt @@ -0,0 +1,7 @@ +class A { + fun x() { + val a = doSmth("str") + } +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.txt new file mode 100644 index 00000000000..9bd5bd27722 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.kt new file mode 100644 index 00000000000..a8a51cd620f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.kt @@ -0,0 +1,5 @@ +class A { + fun x(): Int = doSmth("str") +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.txt new file mode 100644 index 00000000000..d48eb3b1e2f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.kt new file mode 100644 index 00000000000..6493c4899c5 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.kt @@ -0,0 +1,5 @@ +class A { + fun x() = doSmth("str") +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.txt new file mode 100644 index 00000000000..ace1111236c --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtNamedFunction DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.kt new file mode 100644 index 00000000000..9a99c405e48 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.kt @@ -0,0 +1,14 @@ +import kotlin.contracts.contract + +class A { + var x: Int + get() { + contract { + req + } + + fun doSmth(i: String) = 4 + return doSmth("str") + } + set(value) = Unit +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.out_of_src_roots.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.out_of_src_roots.txt new file mode 100644 index 00000000000..88473ec439f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.out_of_src_roots.txt @@ -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] < + #( = [ResolvedTo(RAW_FIR)] contract@fun (): { + ^ # + } + ) + > + { + { + contract#( = [ResolvedTo(BODY_RESOLVE)] contract@fun .(): { + req# + } + ) + } + + local final [ResolvedTo(BODY_RESOLVE)] fun doSmth([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/String|): R|kotlin/Int| { + ^doSmth Int(4) + } + + ^ R|/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| + } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.txt new file mode 100644 index 00000000000..27c3eb22663 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.txt @@ -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|( = [ResolvedTo(BODY_RESOLVE)] [MatchingParameterFunctionTypeKey=@ExtensionFunctionType kotlin/Function1] contract@fun R|kotlin/contracts/ContractBuilder|.(): R|kotlin/Unit| { + # + } + ) + } + + local final [ResolvedTo(BODY_RESOLVE)] fun doSmth([ResolvedTo(BODY_RESOLVE)] i: R|kotlin/String|): R|kotlin/Int| { + ^doSmth Int(4) + } + + ^ R|/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| + } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.kt new file mode 100644 index 00000000000..004d617a35d --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.kt @@ -0,0 +1,7 @@ +class A { + val x: Int + get() { + fun doSmth(i: String) = 4 + return doSmth("str") + } +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.txt new file mode 100644 index 00000000000..ca1190e46df --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.txt @@ -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|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.kt new file mode 100644 index 00000000000..dd372c7e937 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.kt @@ -0,0 +1,5 @@ +class A { + val x: Int get() = doSmth("str") +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.txt new file mode 100644 index 00000000000..ead91544187 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.kt new file mode 100644 index 00000000000..734ba5aa1f9 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.kt @@ -0,0 +1,8 @@ +class A { + val x + get() { + return doSmth("str") + } +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.txt new file mode 100644 index 00000000000..ead91544187 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.kt new file mode 100644 index 00000000000..1ebf6ac26a5 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.kt @@ -0,0 +1,5 @@ +class A { + val x get() = doSmth("str") +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.txt new file mode 100644 index 00000000000..1bd196cec5a --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtPropertyAccessor DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.kt new file mode 100644 index 00000000000..773e1046c2e --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.kt @@ -0,0 +1,6 @@ +class A { + val x: Int by lazy { + fun doSmth(i: String) = 4 + doSmth("str") + } +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.kt new file mode 100644 index 00000000000..564cdb3ecb5 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.kt @@ -0,0 +1,3 @@ +class A { + val x: Int by ErrorDelegate() +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.kt new file mode 100644 index 00000000000..de5005ce9f1 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.kt @@ -0,0 +1,6 @@ +class A { + val x: Int = run { + fun doSmth(i: String) = 4 + doSmth("str") + } +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.kt new file mode 100644 index 00000000000..7f6cdb10d62 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.kt @@ -0,0 +1,6 @@ +class A { + val x by lazy { + fun doSmth(i: String) = 4 + doSmth("str") + } +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.kt new file mode 100644 index 00000000000..ebff6f339f6 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.kt @@ -0,0 +1,3 @@ +class A { + val x by ErrorDelegate() +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.kt new file mode 100644 index 00000000000..1f384b5df82 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.kt @@ -0,0 +1,5 @@ +class A { + val x = run { + doSmth("str") + } +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.kt new file mode 100644 index 00000000000..b9edb777e6c --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.kt @@ -0,0 +1,8 @@ +class A { + var x: Int = 1 + set(value) { + doSmth(value) + } +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.txt new file mode 100644 index 00000000000..944ec5016a6 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.txt @@ -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#|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.kt new file mode 100644 index 00000000000..f358b87e2be --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.kt @@ -0,0 +1,6 @@ +class A { + var x: Int = 1 + set(value) = doSmth(value) +} + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.txt new file mode 100644 index 00000000000..9c7db20e16f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.txt @@ -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#|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.kt new file mode 100644 index 00000000000..bc2045afe4b --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.kt @@ -0,0 +1,9 @@ +class A { + var x + get() = 1 + set(value) { + doSmth(value) + } +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.txt new file mode 100644 index 00000000000..1f0b2ac8170 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.txt @@ -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#|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.kt new file mode 100644 index 00000000000..327066cf8e2 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.kt @@ -0,0 +1,7 @@ +class A { + var x + get() = 1 + set(value) = doSmth(value) +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.txt new file mode 100644 index 00000000000..970b51eef53 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.txt @@ -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#|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/rawContract.kt b/analysis/low-level-api-fir/testdata/inBlockModification/rawContract.kt new file mode 100644 index 00000000000..f2701fa7b31 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/rawContract.kt @@ -0,0 +1,9 @@ +fun foo(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() +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/rawContract.txt b/analysis/low-level-api-fir/testdata/inBlockModification/rawContract.txt new file mode 100644 index 00000000000..84fe9f44498 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/rawContract.txt @@ -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] < + #().#((R|/arg| is R|kotlin/String|)), + #().#(!=(R|/num|, Null(null))), + #(R|/block|, #.#) + > + { + #((R|/arg| is R|kotlin/String|)) + #(!=(R|/num|, Null(null))) + R|/block|.R|SubstitutionOverride|() +} + +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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.kt new file mode 100644 index 00000000000..ccb64ff650a --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.kt @@ -0,0 +1,5 @@ +fun foo(): Int { + return doSmth("str") +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.txt new file mode 100644 index 00000000000..029a1a9d4b6 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.kt new file mode 100644 index 00000000000..52ec22f94e0 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.kt @@ -0,0 +1,3 @@ +fun foo(): Int = doSmth("str") + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.txt new file mode 100644 index 00000000000..029a1a9d4b6 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.kt new file mode 100644 index 00000000000..8716c148c21 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.kt @@ -0,0 +1,5 @@ +fun foo() { + doSmth("str") +} + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.txt new file mode 100644 index 00000000000..e69f3450898 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.kt new file mode 100644 index 00000000000..14503b87fb5 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.kt @@ -0,0 +1,3 @@ +fun foo() = doSmth("str") + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.txt new file mode 100644 index 00000000000..ace1111236c --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtNamedFunction DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.kt new file mode 100644 index 00000000000..c8ac8b007e2 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.kt @@ -0,0 +1,5 @@ + val x: Int + get() { + fun doSmth(i: String) = 4 + return doSmth("str") + } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.txt new file mode 100644 index 00000000000..030d1c5ab19 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.txt @@ -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|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.kt new file mode 100644 index 00000000000..3b7230a4857 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.kt @@ -0,0 +1,3 @@ +val x: Int get() = doSmth("str") + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.txt new file mode 100644 index 00000000000..f922d740393 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.kt new file mode 100644 index 00000000000..838407ed522 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.kt @@ -0,0 +1,6 @@ + val x + get() { + return doSmth("str") + } + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.txt new file mode 100644 index 00000000000..f922d740393 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.txt @@ -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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.kt new file mode 100644 index 00000000000..3f0e46de639 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.kt @@ -0,0 +1,3 @@ +val x get() = doSmth("str") + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.txt new file mode 100644 index 00000000000..1bd196cec5a --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtPropertyAccessor DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.kt new file mode 100644 index 00000000000..ba7105bfaa7 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.kt @@ -0,0 +1,4 @@ +val x: Int by lazy { + fun doSmth(i: String) = 4 + doSmth("str") +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.txt new file mode 100644 index 00000000000..8af1425396a --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.txt @@ -0,0 +1,18 @@ +BEFORE MODIFICATION: +public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|by #( = [ResolvedTo(RAW_FIR)] lazy@fun (): R|kotlin/Int| { + local final [ResolvedTo(RAW_FIR)] fun doSmth([ResolvedTo(RAW_FIR)] i: R|kotlin/String|): R|kotlin/Int| { + ^doSmth Int(4) + } + + ^ R|/doSmth|(String(str)) +} +) + public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| { + ^ D|/x|.#(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|.#(Null(null), ::R|/x|) + } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.kt new file mode 100644 index 00000000000..efd82d78f9d --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.kt @@ -0,0 +1 @@ +val x: Int by ErrorDelegate() diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.txt new file mode 100644 index 00000000000..4b6bc10af7d --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.txt @@ -0,0 +1,11 @@ +BEFORE MODIFICATION: +public final [ResolvedTo(BODY_RESOLVE)] val x: R|kotlin/Int|by #() + public [ResolvedTo(BODY_RESOLVE)] get(): R|kotlin/Int| { + ^ D|/x|.#(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|.#(Null(null), ::R|/x|) + } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.kt new file mode 100644 index 00000000000..b9befeaa582 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.kt @@ -0,0 +1,3 @@ +val x: Int = doSmth("str") + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.txt new file mode 100644 index 00000000000..0ad7b259bcd --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.txt @@ -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| diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.kt new file mode 100644 index 00000000000..7d9bd37bc2c --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.kt @@ -0,0 +1,4 @@ +val x by lazy { + fun doSmth(i: String) = 4 + doSmth("str") +} diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.kt new file mode 100644 index 00000000000..ea7b28e82ec --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.kt @@ -0,0 +1 @@ +val x by ErrorDelegate() diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.kt new file mode 100644 index 00000000000..b8bfc3fdff4 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.kt @@ -0,0 +1,3 @@ +val x = doSmth("str") + +fun doSmth(i: String) = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.txt new file mode 100644 index 00000000000..b94e2395f70 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.txt @@ -0,0 +1 @@ +IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS KtProperty DECLARATION diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.kt new file mode 100644 index 00000000000..3159ad562ee --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.kt @@ -0,0 +1,6 @@ +var x: Int = 1 + set(value) { + doSmth(value) + } + +fun doSmth(i: String): Unit = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.txt new file mode 100644 index 00000000000..e0122d6b81e --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.txt @@ -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#|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.kt new file mode 100644 index 00000000000..b174bdfec09 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.kt @@ -0,0 +1,4 @@ +var x: Int = 1 + set(value) = doSmth(value) + +fun doSmth(i: String): Unit = 4 \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.txt new file mode 100644 index 00000000000..ede6f8be951 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.txt @@ -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#|(R|/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 } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.kt new file mode 100644 index 00000000000..108eab08c4e --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.kt @@ -0,0 +1,7 @@ +val x + get() = 1 + set(value) { + doSmth(value) + } + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.txt new file mode 100644 index 00000000000..5bba1f8b9a0 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.txt @@ -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) + } diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.kt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.kt new file mode 100644 index 00000000000..d53f9d5f154 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.kt @@ -0,0 +1,5 @@ +val x + get() = 1 + set(value) = doSmth(value) + +fun doSmth(i: String) = 4 diff --git a/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.txt b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.txt new file mode 100644 index 00000000000..5bba1f8b9a0 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.txt @@ -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) + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTestCase.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTestCase.kt index e06973f743d..8437244c775 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTestCase.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractFirLazyDeclarationResolveTestCase.kt @@ -42,13 +42,7 @@ abstract class AbstractFirLazyDeclarationResolveTestCase : AbstractLowLevelApiSi resolverProvider: (LLFirResolveSession) -> Pair Unit)>, ) { val resultBuilder = StringBuilder() - val renderer = FirRenderer( - builder = resultBuilder, - declarationRenderer = FirDeclarationRendererWithFilteredAttributes(), - resolvePhaseRenderer = FirResolvePhaseRenderer(), - errorExpressionRenderer = FirErrorExpressionExtendedRenderer(), - fileAnnotationsContainerRenderer = FirFileAnnotationsContainerRenderer(), - ) + val renderer = lazyResolveRenderer(resultBuilder) resolveWithClearCaches(ktFile) { firResolveSession -> checkSession(firResolveSession) @@ -174,3 +168,11 @@ abstract class AbstractFirLazyDeclarationResolveTestCase : AbstractLowLevelApiSi } } } + +internal fun lazyResolveRenderer(builder: StringBuilder): FirRenderer = FirRenderer( + builder = builder, + declarationRenderer = FirDeclarationRendererWithFilteredAttributes(), + resolvePhaseRenderer = FirResolvePhaseRenderer(), + errorExpressionRenderer = FirErrorExpressionExtendedRenderer(), + fileAnnotationsContainerRenderer = FirFileAnnotationsContainerRenderer(), +) diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/AbstractInBlockModificationTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/AbstractInBlockModificationTest.kt new file mode 100644 index 00000000000..3f23a182d46 --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/AbstractInBlockModificationTest.kt @@ -0,0 +1,82 @@ +/* + * 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.extapi.psi.ASTDelegatePsiElement +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType +import org.jetbrains.kotlin.analysis.low.level.api.fir.lazyResolveRenderer +import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithCaches +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirOutOfContentRootTestConfigurator +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator +import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf +import org.jetbrains.kotlin.test.services.TestModuleStructure +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions + +abstract class AbstractInBlockModificationTest : AbstractLowLevelApiSingleFileTest() { + override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) { + val declaration = testServices.expressionMarkerProvider.getElementOfTypeAtCaret(ktFile) + val isSupposedToBeModified = declaration.isReanalyzableContainer() + val actual = if (isSupposedToBeModified) { + resolveWithCaches(ktFile) { firSession -> + val firDeclarationBefore = declaration.getOrBuildFirOfType(firSession) + val declarationTextBefore = firDeclarationBefore.render() + + declaration.modifyBody() + invalidateAfterInBlockModification(declaration) + + val declarationTextAfterModification = firDeclarationBefore.render() + testServices.assertions.assertNotEquals(declarationTextBefore, declarationTextAfterModification) { + "The declaration before and after modification must be in different state" + } + + val firDeclarationAfter = declaration.getOrBuildFirOfType(firSession) + testServices.assertions.assertEquals(firDeclarationBefore, firDeclarationAfter) { + "The declaration before and after must be the same" + } + + val declarationTextAfter = firDeclarationAfter.render() + testServices.assertions.assertEquals(declarationTextBefore, declarationTextAfter) { + "The declaration must have the same in the resolved state" + } + + "BEFORE MODIFICATION:\n$declarationTextBefore\nAFTER MODIFICATION:\n$declarationTextAfterModification" + } + } else { + "IN-BLOCK MODIFICATION IS NOT APPLICABLE FOR THIS ${declaration::class.simpleName} DECLARATION" + } + + testServices.assertions.assertEqualsToTestDataFileSibling(actual) + } + + /** + * Emulate modification inside the body + */ + private fun KtDeclaration.modifyBody() { + parentsWithSelf.filterIsInstance().forEach { + it.subtreeChanged() + } + } +} + +private fun FirDeclaration.render(): String { + val declarationToRender = if (this is FirPropertyAccessor) propertySymbol.fir else this + return lazyResolveRenderer(StringBuilder()).renderElementAsString(declarationToRender) +} + +abstract class AbstractSourceInBlockModificationTest : AbstractInBlockModificationTest() { + override val configurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false) +} + +abstract class AbstractOutOfContentRootInBlockModificationTest : AbstractInBlockModificationTest() { + override val configurator = AnalysisApiFirOutOfContentRootTestConfigurator +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/OutOfContentRootInBlockModificationTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/OutOfContentRootInBlockModificationTestGenerated.java new file mode 100644 index 00000000000..39205534168 --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/OutOfContentRootInBlockModificationTestGenerated.java @@ -0,0 +1,290 @@ +/* + * 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.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/low-level-api-fir/testdata/inBlockModification") +@TestDataPath("$PROJECT_ROOT") +public class OutOfContentRootInBlockModificationTestGenerated extends AbstractOutOfContentRootInBlockModificationTest { + @Test + public void testAllFilesPresentInInBlockModification() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/inBlockModification"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("contract.kt") + public void testContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/contract.kt"); + } + + @Test + @TestMetadata("extensionWithDefaultParameters.kt") + public void testExtensionWithDefaultParameters() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("functionWithDefaultParameters.kt") + public void testFunctionWithDefaultParameters() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithContract.kt") + public void testMemberFunWithBodyWithContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithErrorContract.kt") + public void testMemberFunWithBodyWithErrorContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithFakeContract.kt") + public void testMemberFunWithBodyWithFakeContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithType.kt") + public void testMemberFunWithBodyWithType() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithoutType.kt") + public void testMemberFunWithBodyWithoutType() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.kt"); + } + + @Test + @TestMetadata("memberFunWithTypeWithoutBody.kt") + public void testMemberFunWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberFunWithoutTypeWithoutBody.kt") + public void testMemberFunWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithBodyWithContract.kt") + public void testMemberGetterWithBodyWithContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.kt"); + } + + @Test + @TestMetadata("memberGetterWithTypeWithBody.kt") + public void testMemberGetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithTypeWithoutBody.kt") + public void testMemberGetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithoutTypeWithBody.kt") + public void testMemberGetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithoutTypeWithoutBody.kt") + public void testMemberGetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberPropertyWithTypeInDelegate.kt") + public void testMemberPropertyWithTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithTypeInErrorDelegate.kt") + public void testMemberPropertyWithTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithTypeInInitializer.kt") + public void testMemberPropertyWithTypeInInitializer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.kt"); + } + + @Test + @TestMetadata("memberPropertyWithoutTypeInDelegate.kt") + public void testMemberPropertyWithoutTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithoutTypeInErrorDelegate.kt") + public void testMemberPropertyWithoutTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithoutTypeInInitializer.kt") + public void testMemberPropertyWithoutTypeInInitializer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.kt"); + } + + @Test + @TestMetadata("memberSetterWithTypeWithBody.kt") + public void testMemberSetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberSetterWithTypeWithoutBody.kt") + public void testMemberSetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberSetterWithoutTypeWithBody.kt") + public void testMemberSetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberSetterWithoutTypeWithoutBody.kt") + public void testMemberSetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("rawContract.kt") + public void testRawContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/rawContract.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithTypeWithBody.kt") + public void testTopLevelFunctionWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithTypeWithoutBody.kt") + public void testTopLevelFunctionWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithoutTypeWithBody.kt") + public void testTopLevelFunctionWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithoutTypeWithoutBody.kt") + public void testTopLevelFunctionWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithTypeWithBody.kt") + public void testTopLevelGetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithTypeWithoutBody.kt") + public void testTopLevelGetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithoutTypeWithBody.kt") + public void testTopLevelGetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithoutTypeWithoutBody.kt") + public void testTopLevelGetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithTypeInDelegate.kt") + public void testTopLevelPropertyWithTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithTypeInErrorDelegate.kt") + public void testTopLevelPropertyWithTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithTypeInInititalzer.kt") + public void testTopLevelPropertyWithTypeInInititalzer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithoutTypeInDelegate.kt") + public void testTopLevelPropertyWithoutTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithoutTypeInErrorDelegate.kt") + public void testTopLevelPropertyWithoutTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithoutTypeInInititalzer.kt") + public void testTopLevelPropertyWithoutTypeInInititalzer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithTypeWithBody.kt") + public void testTopLevelSetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithTypeWithoutBody.kt") + public void testTopLevelSetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithoutTypeWithBody.kt") + public void testTopLevelSetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithoutTypeWithoutBody.kt") + public void testTopLevelSetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.kt"); + } +} diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/SourceInBlockModificationTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/SourceInBlockModificationTestGenerated.java new file mode 100644 index 00000000000..0e2abd6fdcd --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/SourceInBlockModificationTestGenerated.java @@ -0,0 +1,290 @@ +/* + * 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.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/low-level-api-fir/testdata/inBlockModification") +@TestDataPath("$PROJECT_ROOT") +public class SourceInBlockModificationTestGenerated extends AbstractSourceInBlockModificationTest { + @Test + public void testAllFilesPresentInInBlockModification() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/low-level-api-fir/testdata/inBlockModification"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("contract.kt") + public void testContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/contract.kt"); + } + + @Test + @TestMetadata("extensionWithDefaultParameters.kt") + public void testExtensionWithDefaultParameters() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/extensionWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("functionWithDefaultParameters.kt") + public void testFunctionWithDefaultParameters() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/functionWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithContract.kt") + public void testMemberFunWithBodyWithContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithContract.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithErrorContract.kt") + public void testMemberFunWithBodyWithErrorContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithErrorContract.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithFakeContract.kt") + public void testMemberFunWithBodyWithFakeContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithFakeContract.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithType.kt") + public void testMemberFunWithBodyWithType() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithType.kt"); + } + + @Test + @TestMetadata("memberFunWithBodyWithoutType.kt") + public void testMemberFunWithBodyWithoutType() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithBodyWithoutType.kt"); + } + + @Test + @TestMetadata("memberFunWithTypeWithoutBody.kt") + public void testMemberFunWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberFunWithoutTypeWithoutBody.kt") + public void testMemberFunWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberFunWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithBodyWithContract.kt") + public void testMemberGetterWithBodyWithContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithBodyWithContract.kt"); + } + + @Test + @TestMetadata("memberGetterWithTypeWithBody.kt") + public void testMemberGetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithTypeWithoutBody.kt") + public void testMemberGetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithoutTypeWithBody.kt") + public void testMemberGetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberGetterWithoutTypeWithoutBody.kt") + public void testMemberGetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberGetterWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberPropertyWithTypeInDelegate.kt") + public void testMemberPropertyWithTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithTypeInErrorDelegate.kt") + public void testMemberPropertyWithTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithTypeInInitializer.kt") + public void testMemberPropertyWithTypeInInitializer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithTypeInInitializer.kt"); + } + + @Test + @TestMetadata("memberPropertyWithoutTypeInDelegate.kt") + public void testMemberPropertyWithoutTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithoutTypeInErrorDelegate.kt") + public void testMemberPropertyWithoutTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("memberPropertyWithoutTypeInInitializer.kt") + public void testMemberPropertyWithoutTypeInInitializer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberPropertyWithoutTypeInInitializer.kt"); + } + + @Test + @TestMetadata("memberSetterWithTypeWithBody.kt") + public void testMemberSetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberSetterWithTypeWithoutBody.kt") + public void testMemberSetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("memberSetterWithoutTypeWithBody.kt") + public void testMemberSetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("memberSetterWithoutTypeWithoutBody.kt") + public void testMemberSetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/memberSetterWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("rawContract.kt") + public void testRawContract() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/rawContract.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithTypeWithBody.kt") + public void testTopLevelFunctionWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithTypeWithoutBody.kt") + public void testTopLevelFunctionWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithoutTypeWithBody.kt") + public void testTopLevelFunctionWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelFunctionWithoutTypeWithoutBody.kt") + public void testTopLevelFunctionWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelFunctionWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithTypeWithBody.kt") + public void testTopLevelGetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithTypeWithoutBody.kt") + public void testTopLevelGetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithoutTypeWithBody.kt") + public void testTopLevelGetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelGetterWithoutTypeWithoutBody.kt") + public void testTopLevelGetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelGetterWithoutTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithTypeInDelegate.kt") + public void testTopLevelPropertyWithTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithTypeInErrorDelegate.kt") + public void testTopLevelPropertyWithTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithTypeInInititalzer.kt") + public void testTopLevelPropertyWithTypeInInititalzer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithTypeInInititalzer.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithoutTypeInDelegate.kt") + public void testTopLevelPropertyWithoutTypeInDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithoutTypeInErrorDelegate.kt") + public void testTopLevelPropertyWithoutTypeInErrorDelegate() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInErrorDelegate.kt"); + } + + @Test + @TestMetadata("topLevelPropertyWithoutTypeInInititalzer.kt") + public void testTopLevelPropertyWithoutTypeInInititalzer() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelPropertyWithoutTypeInInititalzer.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithTypeWithBody.kt") + public void testTopLevelSetterWithTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithTypeWithoutBody.kt") + public void testTopLevelSetterWithTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithTypeWithoutBody.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithoutTypeWithBody.kt") + public void testTopLevelSetterWithoutTypeWithBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithBody.kt"); + } + + @Test + @TestMetadata("topLevelSetterWithoutTypeWithoutBody.kt") + public void testTopLevelSetterWithoutTypeWithoutBody() throws Exception { + runTest("analysis/low-level-api-fir/testdata/inBlockModification/topLevelSetterWithoutTypeWithoutBody.kt"); + } +} diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt index 9c0cdc4cf17..abf9827b586 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/firTestUtils.kt @@ -45,6 +45,13 @@ internal inline fun resolveWithClearCaches(context: KtElement, action: (LLFi return action(resolveSession) } +internal inline fun resolveWithCaches(context: KtElement, action: (LLFirResolveSession) -> R): R { + val project = context.project + val module = ProjectStructureProvider.getModule(project, context, contextualModule = null) + val resolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSession(module) + return action(resolveSession) +} + internal val LLFirResolveSession.isSourceSession: Boolean get() { return when (this) { diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/firLowLevel.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/firLowLevel.kt index 229568130f2..319f949ad9e 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/firLowLevel.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/firLowLevel.kt @@ -14,7 +14,9 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataSpecTest import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataTest import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractOutOfContentRootFileStructureTest +import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractOutOfContentRootInBlockModificationTest import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractSourceFileStructureTest +import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.AbstractSourceInBlockModificationTest import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.AbstractErrorResistanceTest import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.AbstractOutOfContentRootInnerDeclarationsResolvePhaseTest import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.AbstractSourceInnerDeclarationsResolvePhaseTest @@ -57,6 +59,14 @@ internal fun TestGroupSuite.generateFirLowLevelApiTests() { model("errorResistance") } + testClass { + model("inBlockModification") + } + + testClass { + model("inBlockModification") + } + testClass { model("fileStructure") }