diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CompilerFacility.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CompilerFacility.kt index 9505e87326b..b391c598b9b 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CompilerFacility.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CompilerFacility.kt @@ -138,7 +138,7 @@ internal class KtFe10CompilerFacility( } val outputFiles = state.factory.asList().map(::KtCompiledFileForOutputFile) - return KtCompilationResult.Success(outputFiles) + return KtCompilationResult.Success(outputFiles, capturedValues = emptyList()) } finally { state.destroy() } diff --git a/analysis/analysis-api-fir/build.gradle.kts b/analysis/analysis-api-fir/build.gradle.kts index 16e718df8b0..2f1eab28818 100644 --- a/analysis/analysis-api-fir/build.gradle.kts +++ b/analysis/analysis-api-fir/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(project(":compiler:cli-base")) implementation(project(":compiler:backend")) implementation(project(":compiler:backend.jvm.entrypoint")) + implementation(project(":compiler:backend.jvm.lower")) implementation(project(":compiler:ir.backend.common")) implementation(project(":compiler:ir.serialization.jvm")) api(intellijCore()) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompilerFacility.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompilerFacility.kt index 63f59d57d1e..c92530549f2 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompilerFacility.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCompilerFacility.kt @@ -6,18 +6,22 @@ package org.jetbrains.kotlin.analysis.api.fir.components import com.intellij.openapi.progress.ProgressManager -import org.jetbrains.kotlin.analysis.api.components.KtCompilationResult +import org.jetbrains.kotlin.analysis.api.compile.CodeFragmentCapturedValue import org.jetbrains.kotlin.analysis.api.components.KtCompilerFacility +import org.jetbrains.kotlin.analysis.api.components.KtCompilationResult import org.jetbrains.kotlin.analysis.api.components.KtCompilerTarget import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.analysis.api.impl.base.util.KtCompiledFileForOutputFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirWholeFileResolveTarget import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.resolve +import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentCapturedValueAnalyzer import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CompilationPeerCollector +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.builtins.DefaultBuiltIns @@ -33,19 +37,35 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticMarker import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic import org.jetbrains.kotlin.diagnostics.Severity -import org.jetbrains.kotlin.fir.backend.Fir2IrCommonMemberStorage -import org.jetbrains.kotlin.fir.backend.Fir2IrConfiguration -import org.jetbrains.kotlin.fir.backend.Fir2IrConverter +import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.jvm.* +import org.jetbrains.kotlin.fir.declarations.FirCodeFragment import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.pipeline.applyIrGenerationExtensions import org.jetbrains.kotlin.fir.pipeline.signatureComposerForJvmFir2Ir +import org.jetbrains.kotlin.fir.references.FirReference +import org.jetbrains.kotlin.fir.references.FirThisReference +import org.jetbrains.kotlin.fir.references.toResolvedSymbol +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.PsiIrFileEntry import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.ir.util.StubGeneratorExtensions import org.jetbrains.kotlin.load.kotlin.toSourceElement +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi2ir.generators.fragments.EvaluatorFragmentInfo import org.jetbrains.kotlin.resolve.source.PsiSourceFile import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource +import org.jetbrains.kotlin.utils.addToStdlib.runIf internal class KtFirCompilerFacility( override val analysisSession: KtFirAnalysisSession @@ -75,14 +95,31 @@ internal class KtFirCompilerFacility( return KtCompilationResult.Failure(frontendErrors) } + val codeFragmentMappings = runIf(file is KtCodeFragment) { + computeCodeFragmentMappings(file, mainFirFile, firResolveSession, configuration) + } + val compilationPeerData = CompilationPeerCollector.process(mainFirFile) - val filesToCompile = compilationPeerData.files + val filesToCompile = buildList { + val dependencyFiles = buildSet { + addAll(compilationPeerData.files) + addAll(codeFragmentMappings?.capturedFiles.orEmpty()) + + // The main file needs to be the last so caches for the context declarations are populated in FIR-to-IR. + remove(file) + } + + addAll(dependencyFiles) + add(file) + } val firFilesToCompile = filesToCompile.map(::getFullyResolvedFirFile) val generateClassFilter = SingleFileGenerateClassFilter(file, compilationPeerData.inlinedClasses) - val fir2IrExtensions = JvmFir2IrExtensions(effectiveConfiguration, JvmIrDeserializerImpl(), JvmIrMangler) + + val jvmGeneratorExtensions = JvmFir2IrExtensions(effectiveConfiguration, JvmIrDeserializerImpl(), JvmIrMangler) + val fir2IrExtensions = CompilerFacilityFir2IrExtensions(jvmGeneratorExtensions, codeFragmentMappings?.injectedValueProvider) val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val fir2IrConfiguration = Fir2IrConfiguration( @@ -111,8 +148,11 @@ internal class KtFirCompilerFacility( ProgressManager.checkCanceled() + val irGeneratorExtensions = IrGenerationExtension.getInstances(project) + fir2IrResult.components.applyIrGenerationExtensions(fir2IrResult.irModuleFragment, irGeneratorExtensions) + val bindingContext = NoScopeRecordCliBindingTrace().bindingContext - val codegenFactory = createJvmIrCodegenFactory(effectiveConfiguration) + val codegenFactory = createJvmIrCodegenFactory(effectiveConfiguration, file is KtCodeFragment, fir2IrResult.irModuleFragment) val generationState = GenerationState.Builder( project, @@ -136,7 +176,7 @@ internal class KtFirCompilerFacility( fir2IrResult.irModuleFragment, fir2IrResult.components.symbolTable, fir2IrResult.components.irProviders, - JvmFir2IrExtensions(effectiveConfiguration, JvmIrDeserializerImpl(), JvmIrMangler), + CompilerFacilityJvmGeneratorExtensions(jvmGeneratorExtensions), FirJvmBackendExtension(fir2IrResult.components, null), fir2IrResult.pluginContext ) @@ -152,7 +192,8 @@ internal class KtFirCompilerFacility( } val outputFiles = generationState.factory.asList().map(::KtCompiledFileForOutputFile) - return KtCompilationResult.Success(outputFiles) + val capturedValues = codeFragmentMappings?.capturedValues ?: emptyList() + return KtCompilationResult.Success(outputFiles, capturedValues) } finally { generationState.destroy() } @@ -182,6 +223,74 @@ internal class KtFirCompilerFacility( } } + private class CodeFragmentMappings( + val capturedValues: List, + val capturedFiles: List, + val injectedValueProvider: InjectedSymbolProvider + ) + + private fun computeCodeFragmentMappings( + mainKtFile: KtFile, + mainFirFile: FirFile, + resolveSession: LLFirResolveSession, + configuration: CompilerConfiguration, + ): CodeFragmentMappings { + val codeFragment = mainFirFile.declarations.single() as FirCodeFragment + + val capturedData = CodeFragmentCapturedValueAnalyzer.analyze(resolveSession, codeFragment) + + val capturedSymbols = capturedData.symbols + val capturedValues = capturedSymbols.map { it.value } + val injectedSymbols = capturedSymbols.map { InjectedValue(it.symbol, it.typeRef, it.value.isMutated) } + + codeFragment.conversionData = CodeFragmentConversionData( + classId = ClassId(FqName.ROOT, Name.identifier(configuration[CODE_FRAGMENT_CLASS_NAME] ?: "CodeFragment")), + methodName = Name.identifier(configuration[CODE_FRAGMENT_METHOD_NAME] ?: "run"), + injectedSymbols + ) + + val injectedSymbolMapping = injectedSymbols.associateBy { it.symbol } + val injectedValueProvider = InjectedSymbolProvider(mainKtFile, injectedSymbolMapping) + + return CodeFragmentMappings(capturedValues, capturedData.files, injectedValueProvider) + } + + private class InjectedSymbolProvider( + private val mainKtFile: KtFile, + private val injectedSymbolMapping: Map, InjectedValue> + ) : (FirReference, Fir2IrConversionScope) -> InjectedValue? { + override fun invoke(calleeReference: FirReference, conversionScope: Fir2IrConversionScope): InjectedValue? { + val irFile = conversionScope.containingFileIfAny() + val psiFile = (irFile?.fileEntry as? PsiIrFileEntry)?.psiFile + + if (psiFile != mainKtFile) { + return null + } + + val symbol = when (calleeReference) { + is FirThisReference -> calleeReference.boundSymbol + else -> calleeReference.toResolvedSymbol>() + } + return injectedSymbolMapping[symbol] + } + } + + private class CompilerFacilityJvmGeneratorExtensions( + private val delegate: JvmGeneratorExtensions + ) : StubGeneratorExtensions(), JvmGeneratorExtensions by delegate { + override val rawTypeAnnotationConstructor: IrConstructor? + get() = delegate.rawTypeAnnotationConstructor + } + + private class CompilerFacilityFir2IrExtensions( + delegate: Fir2IrExtensions, + private val injectedValueProvider: InjectedSymbolProvider? + ) : Fir2IrExtensions by delegate { + override fun findInjectedValue(calleeReference: FirReference, conversionScope: Fir2IrConversionScope): InjectedValue? { + return injectedValueProvider?.invoke(calleeReference, conversionScope) + } + } + private class SingleFileGenerateClassFilter( private val file: KtFile, private val inlinedClasses: Set @@ -208,7 +317,11 @@ internal class KtFirCompilerFacility( override fun shouldGenerateCodeFragment(script: KtCodeFragment) = false } - private fun createJvmIrCodegenFactory(configuration: CompilerConfiguration): JvmIrCodegenFactory { + private fun createJvmIrCodegenFactory( + configuration: CompilerConfiguration, + isCodeFragment: Boolean, + irModuleFragment: IrModuleFragment, + ): JvmIrCodegenFactory { val jvmGeneratorExtensions = object : JvmGeneratorExtensionsImpl(configuration) { override fun getContainerSource(descriptor: DeclarationDescriptor): DeserializedContainerSource? { // Stubbed top-level function IR symbols (from other source files in the module) require a parent facade class to be @@ -235,10 +348,21 @@ internal class KtFirCompilerFacility( shouldReferenceUndiscoveredExpectSymbols = false, // TODO it was true ) + val phaseConfig = PhaseConfig(if (isCodeFragment) jvmFragmentLoweringPhases else jvmLoweringPhases) + + @OptIn(ObsoleteDescriptorBasedAPI::class) + val evaluatorFragmentInfoForPsi2Ir = runIf(isCodeFragment) { + val irFile = irModuleFragment.files.single { (it.fileEntry as? PsiIrFileEntry)?.psiFile is KtCodeFragment } + val irClass = irFile.declarations.single { it is IrClass && it.metadata is FirMetadataSource.CodeFragment } as IrClass + val irFunction = irClass.declarations.single { it is IrFunction && it !is IrConstructor } as IrFunction + EvaluatorFragmentInfo(irClass.descriptor, irFunction.descriptor, emptyList()) + } + return JvmIrCodegenFactory( configuration, - PhaseConfig(jvmPhases), + phaseConfig, jvmGeneratorExtensions = jvmGeneratorExtensions, + evaluatorFragmentInfoForPsi2Ir = evaluatorFragmentInfoForPsi2Ir, ideCodegenSettings = ideCodegenSettings, ) } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/psiUtils.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/psiUtils.kt index 23951ef9b1c..62e0c19e546 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/psiUtils.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/psiUtils.kt @@ -43,4 +43,4 @@ fun FirBasedSymbol<*>.findPsi(): PsiElement? = */ fun FirDeclaration.findReferencePsi(): PsiElement? { return psi ?: FirSyntheticFunctionInterfaceSourceProvider.findPsi(this) -} +} \ No newline at end of file diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java new file mode 100644 index 00000000000..28d9a1e57ee --- /dev/null +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated.java @@ -0,0 +1,218 @@ +/* + * 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.test.cases.generated.cases.components.compilerFacility; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.analysis.api.fir.test.configurators.AnalysisApiFirTestConfiguratorFactory; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfiguratorFactoryData; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestConfigurator; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.TestModuleKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.FrontendKind; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisSessionMode; +import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiMode; +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compilerFacility.AbstractCompilerFacilityTest; +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/analysis-api/testData/components/compilerFacility/compilation") +@TestDataPath("$PROJECT_ROOT") +public class FirIdeNormalAnalysisSourceModuleCompilerFacilityTestGenerated extends AbstractCompilerFacilityTest { + @NotNull + @Override + public AnalysisApiTestConfigurator getConfigurator() { + return AnalysisApiFirTestConfiguratorFactory.INSTANCE.createConfigurator( + new AnalysisApiTestConfiguratorFactoryData( + FrontendKind.Fir, + TestModuleKind.Source, + AnalysisSessionMode.Normal, + AnalysisApiMode.Ide + ) + ); + } + + @Test + public void testAllFilesPresentInCompilation() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compilerFacility/compilation"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("classKinds.kt") + public void testClassKinds() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.kt"); + } + + @Test + @TestMetadata("imports.kt") + public void testImports() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/imports.kt"); + } + + @Test + @TestMetadata("multipleFiles.kt") + public void testMultipleFiles() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/simple.kt"); + } + + @Nested + @TestMetadata("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments") + @TestDataPath("$PROJECT_ROOT") + public class CodeFragments { + @Test + public void testAllFilesPresentInCodeFragments() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("customName.kt") + public void testCustomName() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.kt"); + } + + @Test + @TestMetadata("imports.kt") + public void testImports() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.kt"); + } + + @Test + @TestMetadata("inlineFunctionUsage.kt") + public void testInlineFunctionUsage() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.kt"); + } + + @Test + @TestMetadata("inlineFunctionUsageSource.kt") + public void testInlineFunctionUsageSource() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.kt"); + } + + @Test + @TestMetadata("local.kt") + public void testLocal() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.kt"); + } + + @Nested + @TestMetadata("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing") + @TestDataPath("$PROJECT_ROOT") + public class Capturing { + @Test + public void testAllFilesPresentInCapturing() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("contextReceiver.kt") + public void testContextReceiver() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.kt"); + } + + @Test + @TestMetadata("contextReceiverExplicit.kt") + public void testContextReceiverExplicit() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.kt"); + } + + @Test + @TestMetadata("extensionReceiver.kt") + public void testExtensionReceiver() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.kt"); + } + + @Test + @TestMetadata("extensionReceiverExplicit.kt") + public void testExtensionReceiverExplicit() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.kt"); + } + + @Test + @TestMetadata("extensionReceiverLabeled.kt") + public void testExtensionReceiverLabeled() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.kt"); + } + + @Test + @TestMetadata("initializer.kt") + public void testInitializer() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.kt"); + } + + @Test + @TestMetadata("local.kt") + public void testLocal() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt"); + } + + @Test + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt"); + } + + @Test + @TestMetadata("localMutated.kt") + public void testLocalMutated() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt"); + } + + @Test + @TestMetadata("nestedOuterClass.kt") + public void testNestedOuterClass() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.kt"); + } + + @Test + @TestMetadata("objectFunction.kt") + public void testObjectFunction() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.kt"); + } + + @Test + @TestMetadata("outerClass.kt") + public void testOuterClass() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.kt"); + } + + @Test + @TestMetadata("outerClassMutated.kt") + public void testOuterClassMutated() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.kt"); + } + + @Test + @TestMetadata("outerClassMutatedPrivate.kt") + public void testOuterClassMutatedPrivate() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.kt"); + } + + @Test + @TestMetadata("valueParameter.kt") + public void testValueParameter() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.kt"); + } + } + } +} diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt new file mode 100644 index 00000000000..ec21b4e12c4 --- /dev/null +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/components/compilerFacility/AbstractCompilerFacilityTest.kt @@ -0,0 +1,208 @@ +/* + * 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.impl.base.test.cases.components.compilerFacility + +import com.intellij.openapi.extensions.LoadingOrder +import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.analysis.api.components.KtCompilationResult +import org.jetbrains.kotlin.analysis.api.components.KtCompiledFile +import org.jetbrains.kotlin.analysis.api.components.KtCompilerFacility +import org.jetbrains.kotlin.analysis.api.components.KtCompilerTarget +import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic +import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi +import org.jetbrains.kotlin.analysis.test.framework.base.AbstractAnalysisApiBasedSingleModuleTest +import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerProvider +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.codegen.BytecodeListingTextCollectingVisitor +import org.jetbrains.kotlin.codegen.ClassBuilderFactories +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.util.DumpIrTreeOptions +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.psi.KtCodeFragment +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.directives.ConfigurationDirectives +import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives +import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions +import org.jetbrains.org.objectweb.asm.ClassReader +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.tree.ClassNode +import java.io.File +import kotlin.test.assertFalse + +abstract class AbstractCompilerFacilityTest : AbstractAnalysisApiBasedSingleModuleTest() { + private companion object { + private val ALLOWED_ERRORS = listOf( + FirErrors.INVISIBLE_REFERENCE, + FirErrors.INVISIBLE_SETTER, + FirErrors.DEPRECATION_ERROR, + FirErrors.DIVISION_BY_ZERO, + FirErrors.OPT_IN_USAGE_ERROR, + FirErrors.OPT_IN_OVERRIDE_ERROR, + FirErrors.UNSAFE_CALL, + FirErrors.UNSAFE_IMPLICIT_INVOKE_CALL, + FirErrors.UNSAFE_INFIX_CALL, + FirErrors.UNSAFE_OPERATOR_CALL, + FirErrors.ITERATOR_ON_NULLABLE, + FirErrors.UNEXPECTED_SAFE_CALL, + FirErrors.DSL_SCOPE_VIOLATION, + ).map { it.name } + } + + override fun doTestByFileStructure(ktFiles: List, module: TestModule, testServices: TestServices) { + val ktFile = ktFiles.singleOrNull() ?: ktFiles.first { it.name == "main.kt" } + + val irCollector = CollectingIrGenerationExtension() + + val project = ktFile.project + project.extensionArea.getExtensionPoint(IrGenerationExtension.extensionPointName) + .registerExtension(irCollector, LoadingOrder.LAST, project) + + val ktCodeFragment = createCodeFragment(ktFile, module, testServices) + if (ktCodeFragment != null) { + for (importNameString in module.directives[Directives.CODE_FRAGMENT_IMPORT]) { + ktCodeFragment.addImport("import $importNameString") + } + } + + val compilerConfiguration = CompilerConfiguration().apply { + put(CommonConfigurationKeys.MODULE_NAME, module.name) + put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, module.languageVersionSettings) + put(JVMConfigurationKeys.IR, true) + + module.directives[Directives.CODE_FRAGMENT_CLASS_NAME].singleOrNull() + ?.let { put(KtCompilerFacility.CODE_FRAGMENT_CLASS_NAME, it) } + + module.directives[Directives.CODE_FRAGMENT_METHOD_NAME].singleOrNull() + ?.let { put(KtCompilerFacility.CODE_FRAGMENT_METHOD_NAME, it) } + } + + val ktTargetFile = ktCodeFragment ?: ktFile + + analyze(ktTargetFile) { + val target = KtCompilerTarget.Jvm(ClassBuilderFactories.TEST) + val allowedErrorFilter: (KtDiagnostic) -> Boolean = { it.factoryName in ALLOWED_ERRORS } + + val actualText = when (val result = compile(ktTargetFile, compilerConfiguration, target, allowedErrorFilter)) { + is KtCompilationResult.Failure -> result.errors.joinToString("\n") { dumpDiagnostic(it) } + is KtCompilationResult.Success -> dumpClassFiles(result.output) + } + + testServices.assertions.assertEqualsToTestDataFileSibling(actualText) + } + + testServices.assertions.assertEqualsToTestDataFileSibling(irCollector.result, extension = ".ir.txt") + } + + override fun configureTest(builder: TestConfigurationBuilder) { + super.configureTest(builder) + with(builder) { + useDirectives(Directives) + useConfigurators() + defaultDirectives { + +ConfigurationDirectives.WITH_STDLIB + +JvmEnvironmentConfigurationDirectives.FULL_JDK + } + } + } + + private fun dumpDiagnostic(diagnostic: KtDiagnostic): String { + val textRanges = when (diagnostic) { + is KtDiagnosticWithPsi<*> -> { + diagnostic.textRanges.singleOrNull()?.toString() + ?: diagnostic.textRanges.joinToString(prefix = "[", postfix = "]") + } + else -> null + } + + return buildString { + if (textRanges != null) { + append(textRanges) + append(" ") + } + append(diagnostic.factoryName) + append(" ") + append(diagnostic.defaultMessage) + } + } + + private fun dumpClassFiles(outputFiles: List): String { + val classes = outputFiles + .filter { it.path.endsWith(".class", ignoreCase = true) } + .also { check(it.isNotEmpty()) } + .sortedBy { it.path } + .map { outputFile -> + val classReader = ClassReader(outputFile.content) + ClassNode(Opcodes.API_VERSION).also { classReader.accept(it, ClassReader.SKIP_CODE) } + } + + val allClasses = classes.associateBy { Type.getObjectType(it.name) } + + return classes.joinToString("\n\n") { node -> + val visitor = BytecodeListingTextCollectingVisitor( + BytecodeListingTextCollectingVisitor.Filter.EMPTY, + allClasses, + withSignatures = false, + withAnnotations = false, + sortDeclarations = true + ) + + node.accept(visitor) + visitor.text + } + } + + object Directives : SimpleDirectivesContainer() { + val CODE_FRAGMENT_IMPORT by stringDirective("Import directive for a code fragment") + val CODE_FRAGMENT_CLASS_NAME by stringDirective("Short name of a code fragment class") + val CODE_FRAGMENT_METHOD_NAME by stringDirective("Name of a code fragment facade method") + } +} + +internal fun createCodeFragment(ktFile: KtFile, module: TestModule, testServices: TestServices): KtCodeFragment? { + val ioFile = module.files.single { it.name == ktFile.name }.originalFile + val ioFragmentFile = File(ioFile.parent, "${ioFile.nameWithoutExtension}.fragment.${ioFile.extension}") + + if (!ioFragmentFile.exists()) { + return null + } + + val contextElement = testServices.expressionMarkerProvider.getElementOfTypeAtCaret(ktFile) + + val fragmentText = ioFragmentFile.readText() + val isBlockFragment = fragmentText.any { it == '\n' } + + val project = ktFile.project + val factory = KtPsiFactory(project, markGenerated = false) + + return when { + isBlockFragment -> factory.createBlockCodeFragment(fragmentText, contextElement) + else -> factory.createExpressionCodeFragment(fragmentText, contextElement) + } +} + +private class CollectingIrGenerationExtension : IrGenerationExtension { + lateinit var result: String + private set + + override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { + assertFalse { ::result.isInitialized } + + val dumpOptions = DumpIrTreeOptions(normalizeNames = true, stableOrder = true) + result = moduleFragment.dump(dumpOptions) + } +} \ No newline at end of file diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/compile/CodeFragmentCapturedValue.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/compile/CodeFragmentCapturedValue.kt new file mode 100644 index 00000000000..c8f7f26144b --- /dev/null +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/compile/CodeFragmentCapturedValue.kt @@ -0,0 +1,104 @@ +/* + * 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.compile + +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +public sealed class CodeFragmentCapturedValue( + public val name: String, + public val isMutated: Boolean, + public val isCrossingInlineBounds: Boolean, +) { + public open val displayText: String + get() = name + + override fun toString(): String { + return javaClass.simpleName + "[name: " + name + "; isMutated: " + isMutated + "; displayText: " + displayText + "]" + } + + /** Represents a local variable or a parameter. */ + public class Local( + name: Name, + isMutated: Boolean, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue(name.asString(), isMutated, isCrossingInlineBounds) + + /** Represents a delegated local variable (`val local by...`). */ + public class LocalDelegate( + name: Name, + isMutated: Boolean, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue(name.asString(), isMutated, isCrossingInlineBounds) { + override val displayText: String + get() = "$name\$delegate" + } + + /** Represents a backing field (a `field` variable inside a property accessor). */ + public class BackingField( + name: Name, + isMutated: Boolean, + isCrossingInlineBounds: Boolean + ) : CodeFragmentCapturedValue(name.asString(), isMutated, isCrossingInlineBounds) { + override val displayText: String + get() = "field" + } + + /** Represents a captured outer class. */ + public class ContainingClass( + private val classId: ClassId, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue("", isMutated = false, isCrossingInlineBounds) { + override val displayText: String + get() { + val simpleName = classId.shortClassName + return if (simpleName.isSpecial) "this" else "this@" + simpleName.asString() + } + } + + /** Represents a captured super class (`super.foo()`). */ + public class SuperClass( + private val classId: ClassId, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue("", isMutated = false, isCrossingInlineBounds) { + override val displayText: String + get() = "super@" + classId.shortClassName.asString() + } + + public class ExtensionReceiver( + labelName: String, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue(labelName, isMutated = false, isCrossingInlineBounds) { + override val displayText: String + get() = "this@$name" + } + + public class ContextReceiver( + public val index: Int, + labelName: Name, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue(labelName.asString(), isMutated = false, isCrossingInlineBounds) { + override val displayText: String + get() = "this@$name" + } + + /** Represents a captured named local function. */ + public class LocalFunction( + name: Name, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue(name.asString(), isMutated = false, isCrossingInlineBounds) + + /** Represents an externally provided value. */ + public class ForeignValue( + name: Name, + isCrossingInlineBounds: Boolean, + ) : CodeFragmentCapturedValue(name.asString(), isMutated = false, isCrossingInlineBounds) + + /** Represents a `coroutineContext` call. */ + public class CoroutineContext( + isCrossingInlineBounds: Boolean + ) : CodeFragmentCapturedValue("coroutineContext", isMutated = false, isCrossingInlineBounds) +} \ No newline at end of file diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCompilerFacility.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCompilerFacility.kt index 515413bb5fa..dd6d500ee97 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCompilerFacility.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtCompilerFacility.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.api.components import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnostic +import org.jetbrains.kotlin.analysis.api.compile.CodeFragmentCapturedValue import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.codegen.ClassBuilderFactory import org.jetbrains.kotlin.config.CompilerConfiguration @@ -26,8 +27,12 @@ public sealed class KtCompilationResult { * Successful compilation result. * * @property output Output files produced by the compiler. For the JVM target, these are class files and '.kotlin_module'. + * @property capturedValues Context values captured by a [KtCodeFragment]. Empty for an ordinary [KtFile]. */ - public class Success(public val output: List) : KtCompilationResult() + public class Success( + public val output: List, + public val capturedValues: List + ) : KtCompilationResult() /** * Failed compilation result. @@ -69,6 +74,16 @@ public sealed class KtCompilerTarget { } public abstract class KtCompilerFacility : KtAnalysisSessionComponent() { + public companion object { + /** Simple class name for the code fragment facade class. */ + public val CODE_FRAGMENT_CLASS_NAME: CompilerConfigurationKey = + CompilerConfigurationKey("code fragment class name") + + /** Entry point method name for the code fragment. */ + public val CODE_FRAGMENT_METHOD_NAME: CompilerConfigurationKey = + CompilerConfigurationKey("code fragment method name") + } + public abstract fun compile( file: KtFile, configuration: CompilerConfiguration, diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt new file mode 100644 index 00000000000..59a2088b0f1 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt @@ -0,0 +1,303 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/classKinds.kt + CLASS ANNOTATION_CLASS name:Anno modality:OPEN visibility:public superTypes:[kotlin.Annotation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Anno + CONSTRUCTOR visibility:public <> () returnType:.Anno [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:Anno modality:OPEN visibility:public superTypes:[kotlin.Annotation]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Generic modality:FINAL visibility:public superTypes:[.Ordinary; .Intf] + annotations: + Anno + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Generic.Generic> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false + CONSTRUCTOR visibility:public <> () returnType:.Generic.Generic> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .Ordinary' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Generic modality:FINAL visibility:public superTypes:[.Ordinary; .Intf]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Ordinary + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Intf + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Ordinary + public open fun hashCode (): kotlin.Int [fake_override] declared in .Intf + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Ordinary + public open fun toString (): kotlin.String [fake_override] declared in .Intf + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:run visibility:public modality:OPEN <> ($this:.Generic.Generic>) returnType:kotlin.Unit + overridden: + public abstract fun run (): kotlin.Unit declared in .Intf + $this: VALUE_PARAMETER name: type:.Generic.Generic> + BLOCK_BODY + CLASS CLASS name:Operation modality:SEALED visibility:public superTypes:[kotlin.Any] + sealedSubclasses: + CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Operation] + CLASS CLASS name:Subtract modality:FINAL visibility:public superTypes:[.Operation] + CLASS CLASS name:Negate modality:FINAL visibility:public superTypes:[.Operation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Operation + CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Operation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Operation.Add + PROPERTY name:firstValue visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:firstValue type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'firstValue: kotlin.Int declared in .Operation.Add.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Operation.Add) returnType:kotlin.Int + correspondingProperty: PROPERTY name:firstValue visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Operation.Add + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Operation.Add' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:firstValue type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Operation.Add declared in .Operation.Add.' type=.Operation.Add origin=null + PROPERTY name:secondValue visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:secondValue type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'secondValue: kotlin.Int declared in .Operation.Add.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Operation.Add) returnType:kotlin.Int + correspondingProperty: PROPERTY name:secondValue visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Operation.Add + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Operation.Add' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:secondValue type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Operation.Add declared in .Operation.Add.' type=.Operation.Add origin=null + CONSTRUCTOR visibility:public <> (firstValue:kotlin.Int, secondValue:kotlin.Int) returnType:.Operation.Add [primary] + VALUE_PARAMETER name:firstValue index:0 type:kotlin.Int + VALUE_PARAMETER name:secondValue index:1 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'protected constructor () [primary] declared in .Operation' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Operation]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Negate modality:FINAL visibility:public superTypes:[.Operation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Operation.Negate + PROPERTY name:value visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'value: kotlin.Int declared in .Operation.Negate.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Operation.Negate) returnType:kotlin.Int + correspondingProperty: PROPERTY name:value visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Operation.Negate + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Operation.Negate' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:value type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Operation.Negate declared in .Operation.Negate.' type=.Operation.Negate origin=null + CONSTRUCTOR visibility:public <> (value:kotlin.Int) returnType:.Operation.Negate [primary] + VALUE_PARAMETER name:value index:0 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'protected constructor () [primary] declared in .Operation' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Negate modality:FINAL visibility:public superTypes:[.Operation]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Subtract modality:FINAL visibility:public superTypes:[.Operation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Operation.Subtract + PROPERTY name:minuend visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:minuend type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'minuend: kotlin.Int declared in .Operation.Subtract.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Operation.Subtract) returnType:kotlin.Int + correspondingProperty: PROPERTY name:minuend visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Operation.Subtract + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Operation.Subtract' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:minuend type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Operation.Subtract declared in .Operation.Subtract.' type=.Operation.Subtract origin=null + PROPERTY name:subtrahend visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:subtrahend type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + GET_VAR 'subtrahend: kotlin.Int declared in .Operation.Subtract.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.Operation.Subtract) returnType:kotlin.Int + correspondingProperty: PROPERTY name:subtrahend visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.Operation.Subtract + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .Operation.Subtract' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:subtrahend type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .Operation.Subtract declared in .Operation.Subtract.' type=.Operation.Subtract origin=null + CONSTRUCTOR visibility:public <> (minuend:kotlin.Int, subtrahend:kotlin.Int) returnType:.Operation.Subtract [primary] + VALUE_PARAMETER name:minuend index:0 type:kotlin.Int + VALUE_PARAMETER name:subtrahend index:1 type:kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'protected constructor () [primary] declared in .Operation' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Subtract modality:FINAL visibility:public superTypes:[.Operation]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int [fake_override] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String [fake_override] declared in .Operation + $this: VALUE_PARAMETER name: type:kotlin.Any + CONSTRUCTOR visibility:protected <> () returnType:.Operation [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Operation modality:SEALED visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:Ordinary modality:ABSTRACT visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Ordinary + CONSTRUCTOR visibility:public <> () returnType:.Ordinary [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Ordinary modality:ABSTRACT visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS ENUM_CLASS name:Direction modality:FINAL visibility:public superTypes:[kotlin.Enum<.Direction>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Direction + CONSTRUCTOR visibility:private <> () returnType:.Direction [primary] + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum' + : .Direction + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:Direction modality:FINAL visibility:public superTypes:[kotlin.Enum<.Direction>]' + ENUM_ENTRY name:EAST + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .Direction' + ENUM_ENTRY name:NORTH + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .Direction' + ENUM_ENTRY name:SOUTH + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .Direction' + ENUM_ENTRY name:WEST + init: EXPRESSION_BODY + ENUM_CONSTRUCTOR_CALL 'private constructor () [primary] declared in .Direction' + FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:.Direction + VALUE_PARAMETER name:value index:0 type:kotlin.String + SYNTHETIC_BODY kind=ENUM_VALUEOF + FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.Direction> + SYNTHETIC_BODY kind=ENUM_VALUES + FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Any [fake_override] + overridden: + protected final fun clone (): kotlin.Any declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum, other:.Direction) returnType:kotlin.Int [fake_override,operator] + overridden: + public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + VALUE_PARAMETER name:other index:0 type:.Direction + FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:finalize visibility:protected/*protected and package*/ modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Unit [fake_override] + overridden: + protected/*protected and package*/ final fun finalize (): kotlin.Unit declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:getDeclaringClass visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:@[FlexibleNullability] java.lang.Class<@[FlexibleNullability] .Direction?>? [fake_override] + overridden: + public final fun getDeclaringClass (): @[FlexibleNullability] java.lang.Class<@[FlexibleNullability] E of kotlin.Enum?>? declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] + overridden: + public final fun hashCode (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [val] + FUN ENUM_CLASS_SPECIAL_MEMBER name: visibility:public modality:FINAL <> () returnType:kotlin.enums.EnumEntries<.Direction> + correspondingProperty: PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [val] + SYNTHETIC_BODY kind=ENUM_ENTRIES + PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + annotations: + IntrinsicConstEvaluation + overridden: + public final name: kotlin.String [val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.String [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.String declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + overridden: + public final ordinal: kotlin.Int [val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:kotlin.Enum) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in kotlin.Enum + $this: VALUE_PARAMETER name: type:kotlin.Enum + CLASS INTERFACE name:Intf modality:ABSTRACT visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Intf + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:run visibility:public modality:ABSTRACT <> ($this:.Intf) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.Intf diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.kt new file mode 100644 index 00000000000..d5dde8fcb4e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.kt @@ -0,0 +1,22 @@ +interface Intf { + fun run() +} + +abstract class Ordinary + +annotation class Anno + +@Anno +class Generic : Ordinary(), Intf { + override fun run() {} +} + +enum class Direction { + NORTH, SOUTH, WEST, EAST +} + +sealed class Operation { + class Add(val firstValue: Int, val secondValue: Int) : Operation() + class Subtract(val minuend: Int, val subtrahend: Int) : Operation() + class Negate(val value: Int) : Operation() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.txt new file mode 100644 index 00000000000..b43ab8f5e84 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.txt @@ -0,0 +1,72 @@ +public annotation class Anno { + // source: 'classKinds.kt' +} + +public final enum class Direction { + // source: 'classKinds.kt' + private synthetic final static field $ENTRIES: kotlin.enums.EnumEntries + private synthetic final static field $VALUES: Direction[] + public final enum static field EAST: Direction + public final enum static field NORTH: Direction + public final enum static field SOUTH: Direction + public final enum static field WEST: Direction + private synthetic final static method $values(): Direction[] + static method (): void + private method (p0: java.lang.String, p1: int): void + public static method getEntries(): kotlin.enums.EnumEntries + public static method valueOf(p0: java.lang.String): Direction + public static method values(): Direction[] +} + +public final class Generic { + // source: 'classKinds.kt' + public method (): void + public method run(): void +} + +public interface Intf { + // source: 'classKinds.kt' + public abstract method run(): void +} + +public final class Operation$Add { + // source: 'classKinds.kt' + private final field firstValue: int + private final field secondValue: int + public method (p0: int, p1: int): void + public final method getFirstValue(): int + public final method getSecondValue(): int + public final inner class Operation$Add +} + +public final class Operation$Negate { + // source: 'classKinds.kt' + private final field value: int + public method (p0: int): void + public final method getValue(): int + public final inner class Operation$Negate +} + +public final class Operation$Subtract { + // source: 'classKinds.kt' + private final field minuend: int + private final field subtrahend: int + public method (p0: int, p1: int): void + public final method getMinuend(): int + public final method getSubtrahend(): int + public final inner class Operation$Subtract +} + +public abstract class Operation { + // source: 'classKinds.kt' + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void + public final inner class Operation$Add + public final inner class Operation$Negate + public final inner class Operation$Subtract +} + +public abstract class Ordinary { + // source: 'classKinds.kt' + public method (): void +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.capturing.txt new file mode 100644 index 00000000000..5cdb5f2a1d9 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.capturing.txt @@ -0,0 +1,4 @@ +ContextReceiver[name: Foo; isMutated: false; displayText: this@Foo] + context(R|Foo|) + fun call(): R|kotlin/Unit| + R|Foo| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.fragment.kt new file mode 100644 index 00000000000..19102815663 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.fragment.kt @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.ir.txt new file mode 100644 index 00000000000..9be3ad1f48c --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.ir.txt @@ -0,0 +1,13 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Foo) returnType:kotlin.String + VALUE_PARAMETER name:p0 index:0 type:.Foo + EXPRESSION_BODY + BLOCK type=kotlin.String origin=null + CALL 'public final fun (): kotlin.String declared in .Foo' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'p0: .Foo declared in .CodeFragment.run' type=.Foo origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.kt new file mode 100644 index 00000000000..c3c7bfbfb28 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.kt @@ -0,0 +1,12 @@ +fun test() { + call(Foo()) +} + +context(Foo) +fun call() { + val x = 0 +} + +class Foo { + val foo: String = "foo" +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.txt new file mode 100644 index 00000000000..1dc6019ad44 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Foo): java.lang.String +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.capturing.txt new file mode 100644 index 00000000000..5cdb5f2a1d9 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.capturing.txt @@ -0,0 +1,4 @@ +ContextReceiver[name: Foo; isMutated: false; displayText: this@Foo] + context(R|Foo|) + fun call(): R|kotlin/Unit| + R|Foo| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.fragment.kt new file mode 100644 index 00000000000..21116d6f06e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.fragment.kt @@ -0,0 +1 @@ +this@Foo.foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.ir.txt new file mode 100644 index 00000000000..9be3ad1f48c --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.ir.txt @@ -0,0 +1,13 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Foo) returnType:kotlin.String + VALUE_PARAMETER name:p0 index:0 type:.Foo + EXPRESSION_BODY + BLOCK type=kotlin.String origin=null + CALL 'public final fun (): kotlin.String declared in .Foo' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'p0: .Foo declared in .CodeFragment.run' type=.Foo origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.kt new file mode 100644 index 00000000000..c3c7bfbfb28 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.kt @@ -0,0 +1,12 @@ +fun test() { + call(Foo()) +} + +context(Foo) +fun call() { + val x = 0 +} + +class Foo { + val foo: String = "foo" +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.txt new file mode 100644 index 00000000000..1dc6019ad44 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Foo): java.lang.String +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.capturing.txt new file mode 100644 index 00000000000..d11d2365d30 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.capturing.txt @@ -0,0 +1,6 @@ +ExtensionReceiver[name: with; isMutated: false; displayText: this@with] + with@fun R|kotlin/String|.(): R|kotlin/Unit| + R|kotlin/String| +ExtensionReceiver[name: with; isMutated: false; displayText: this@with] + with@fun R|Foo|.(): R|kotlin/Unit| + R|Foo| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.fragment.kt new file mode 100644 index 00000000000..01f711e33c5 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.fragment.kt @@ -0,0 +1 @@ +length + foo.length \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.ir.txt new file mode 100644 index 00000000000..1d86e1a2551 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.ir.txt @@ -0,0 +1,18 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.String, p1:.Foo) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:kotlin.String + VALUE_PARAMETER name:p1 index:1 type:.Foo + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'p0: kotlin.String declared in .CodeFragment.run' type=kotlin.String origin=null + other: CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: CALL 'public final fun (): kotlin.String declared in .Foo' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'p1: .Foo declared in .CodeFragment.run' type=.Foo origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.kt new file mode 100644 index 00000000000..987b28703b8 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.kt @@ -0,0 +1,11 @@ +fun test() { + with("Hello, world!") { + with(Foo()) { + val x = 0 + } + } +} + +class Foo { + val foo: String = "foo" +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.txt new file mode 100644 index 00000000000..d5917865a2a --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: java.lang.String, p1: Foo): int +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.capturing.txt new file mode 100644 index 00000000000..57048f1564b --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.capturing.txt @@ -0,0 +1,3 @@ +ExtensionReceiver[name: with; isMutated: false; displayText: this@with] + with@fun R|kotlin/String|.(): R|kotlin/Unit| + R|kotlin/String| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.fragment.kt new file mode 100644 index 00000000000..0b5068123f4 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.fragment.kt @@ -0,0 +1 @@ +this@with.length \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.ir.txt new file mode 100644 index 00000000000..5ef8203f2b4 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.ir.txt @@ -0,0 +1,13 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.String) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:kotlin.String + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'p0: kotlin.String declared in .CodeFragment.run' type=kotlin.String origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.kt new file mode 100644 index 00000000000..aabc54362f0 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.kt @@ -0,0 +1,5 @@ +fun test() { + with("Hello, world!") { + val x = 0 + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.txt new file mode 100644 index 00000000000..47ec434cd58 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: java.lang.String): int +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.capturing.txt new file mode 100644 index 00000000000..8249cd1d037 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.capturing.txt @@ -0,0 +1,3 @@ +ExtensionReceiver[name: str; isMutated: false; displayText: this@str] + str@fun R|kotlin/String|.(): R|kotlin/Unit| + R|kotlin/String| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.fragment.kt new file mode 100644 index 00000000000..01feb60feae --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.fragment.kt @@ -0,0 +1 @@ +this@str.length \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.ir.txt new file mode 100644 index 00000000000..5ef8203f2b4 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.ir.txt @@ -0,0 +1,13 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.String) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:kotlin.String + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'p0: kotlin.String declared in .CodeFragment.run' type=kotlin.String origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.kt new file mode 100644 index 00000000000..2356d33739d --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.kt @@ -0,0 +1,5 @@ +fun test() { + with("Hello, world!") str@{ + val x = 0 + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.txt new file mode 100644 index 00000000000..47ec434cd58 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: java.lang.String): int +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.capturing.txt new file mode 100644 index 00000000000..92c852668ef --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.capturing.txt @@ -0,0 +1,6 @@ +Local[name: a; isMutated: false; displayText: a] + a: R|kotlin/Int| + R|kotlin/Int| +Local[name: b; isMutated: false; displayText: b] + b: R|kotlin/String| + R|kotlin/String| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.fragment.kt new file mode 100644 index 00000000000..c1e0f225857 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.fragment.kt @@ -0,0 +1 @@ +a + b.length \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.ir.txt new file mode 100644 index 00000000000..2223c310fb2 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.ir.txt @@ -0,0 +1,16 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.Int, p1:kotlin.String) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + VALUE_PARAMETER name:p1 index:1 type:kotlin.String + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: GET_VAR 'p0: kotlin.Int declared in .CodeFragment.run' type=kotlin.Int origin=null + other: CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: GET_VAR 'p1: kotlin.String declared in .CodeFragment.run' type=kotlin.String origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.kt new file mode 100644 index 00000000000..3ad11d71465 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.kt @@ -0,0 +1,5 @@ +class Foo(a: Int, b: String) { + init { + val x = 0 + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.txt new file mode 100644 index 00000000000..7825d5eaa4d --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: int, p1: java.lang.String): int +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.capturing.txt new file mode 100644 index 00000000000..30557592863 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.capturing.txt @@ -0,0 +1,3 @@ +Local[name: x; isMutated: false; displayText: x] + lval x: R|kotlin/Int| + R|kotlin/Int| \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.fragment.kt new file mode 100644 index 00000000000..c1b0730e013 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.fragment.kt @@ -0,0 +1 @@ +x \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.ir.txt new file mode 100644 index 00000000000..c80792aa132 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.ir.txt @@ -0,0 +1,12 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:kotlin.Int + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + GET_VAR 'p0: kotlin.Int declared in .CodeFragment.run' type=kotlin.Int origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt new file mode 100644 index 00000000000..81652f5e8b9 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt @@ -0,0 +1,4 @@ +fun test() { + val x = 0 + val y = 0 +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.txt new file mode 100644 index 00000000000..a9d2fdaf041 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: int): int +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.capturing.txt new file mode 100644 index 00000000000..3d1f7671d8d --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.capturing.txt @@ -0,0 +1,9 @@ +LocalFunction[name: call; isMutated: false; displayText: call] + fun call(a: R|kotlin/Int|, b: R|kotlin/String|): R|kotlin/Unit| + R|(kotlin/Int, kotlin/String) -> kotlin/Unit| +Local[name: x; isMutated: false; displayText: x] + lval x: R|kotlin/Int| + R|kotlin/Int| +Local[name: y; isMutated: false; displayText: y] + lval y: R|kotlin/String| + R|kotlin/String| \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.fragment.kt new file mode 100644 index 00000000000..df1955d69c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.fragment.kt @@ -0,0 +1 @@ +call(x, y) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.ir.txt new file mode 100644 index 00000000000..8fbb48011c4 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.ir.txt @@ -0,0 +1,31 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/localFunction.kt + FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + FUN LOCAL_FUNCTION name:call visibility:local modality:FINAL <> (a:kotlin.Int, b:kotlin.String) returnType:kotlin.Unit + VALUE_PARAMETER name:a index:0 type:kotlin.Int + VALUE_PARAMETER name:b index:1 type:kotlin.String + BLOCK_BODY + CALL 'public final fun println (message: kotlin.Any?): kotlin.Unit [inline] declared in kotlin.io' type=kotlin.Unit origin=null + message: CALL 'public final fun repeat (n: kotlin.Int): kotlin.String declared in kotlin.text' type=kotlin.String origin=null + $receiver: GET_VAR 'b: kotlin.String declared in .test.call' type=kotlin.String origin=null + n: GET_VAR 'a: kotlin.Int declared in .test.call' type=kotlin.Int origin=null + VAR name:x type:kotlin.Int [val] + CONST Int type=kotlin.Int value=2 + VAR name:y type:kotlin.String [val] + CONST String type=kotlin.String value="foo" + VAR name:z type:kotlin.Unit [val] + GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:kotlin.Function2, p1:kotlin.Int, p2:kotlin.String) returnType:kotlin.Unit + VALUE_PARAMETER name:p0 index:0 type:kotlin.Function2 + VALUE_PARAMETER name:p1 index:1 type:kotlin.Int + VALUE_PARAMETER name:p2 index:2 type:kotlin.String + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + GET_VAR 'p0: kotlin.Function2 declared in .CodeFragment.run' type=kotlin.Function2 origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt new file mode 100644 index 00000000000..610e72f8bfd --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt @@ -0,0 +1,9 @@ +fun test() { + fun call(a: Int, b: String) { + println(b.repeat(a)) + } + + val x = 2 + val y = "foo" + val z = Unit +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.txt new file mode 100644 index 00000000000..23fe40979b5 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.txt @@ -0,0 +1,7 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: kotlin.jvm.functions.Function2, p1: int, p2: java.lang.String): void +} + +public final class LocalFunctionKt \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.capturing.txt new file mode 100644 index 00000000000..b006f927623 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.capturing.txt @@ -0,0 +1,3 @@ +Local[name: x; isMutated: true; displayText: x] + lvar x: R|kotlin/Int| + R|kotlin/Int| \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.fragment.kt new file mode 100644 index 00000000000..3d2b4b14efe --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.fragment.kt @@ -0,0 +1 @@ +x = 1 \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.ir.txt new file mode 100644 index 00000000000..a98340be514 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.ir.txt @@ -0,0 +1,13 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:generated_for_debugger_fun visibility:public modality:FINAL <> (p0:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER SHARED_VARIABLE_IN_EVALUATOR_FRAGMENT name:p0 index:0 type:kotlin.Int [assignable] + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + SET_VAR 'p0: kotlin.Int [assignable] declared in .CodeFragment.generated_for_debugger_fun' type=kotlin.Unit origin=null + CONST Int type=kotlin.Int value=1 diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt new file mode 100644 index 00000000000..eb43cd6a1da --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt @@ -0,0 +1,7 @@ +fun test() { + var x = 0 + val y = 0 +} + +// FragmentSharedVariablesLowering depends on a specific function name +// CODE_FRAGMENT_METHOD_NAME: generated_for_debugger_fun \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.txt new file mode 100644 index 00000000000..e726e25f658 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.txt @@ -0,0 +1,6 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method generated_for_debugger_fun(p0: kotlin.jvm.internal.Ref$IntRef): void + public final inner class kotlin/jvm/internal/Ref$IntRef +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.capturing.txt new file mode 100644 index 00000000000..cadcb19f591 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.capturing.txt @@ -0,0 +1,6 @@ +ContainingClass[name: ; isMutated: false; displayText: this@Foo] + class Foo : R|kotlin/Any| + R|Foo| +ContainingClass[name: ; isMutated: false; displayText: this@Bar] + class Bar : R|kotlin/Any| + R|Foo.Bar| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.fragment.kt new file mode 100644 index 00000000000..273b7cdbebe --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.fragment.kt @@ -0,0 +1 @@ +callFoo(this@Foo) + callString(a) + callString(b) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.ir.txt new file mode 100644 index 00000000000..93578293e17 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.ir.txt @@ -0,0 +1,22 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Foo, p1:.Foo.Bar) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:.Foo + VALUE_PARAMETER name:p1 index:1 type:.Foo.Bar + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CALL 'public final fun callFoo (foo: .Foo): kotlin.Int declared in .NestedOuterClassKt' type=kotlin.Int origin=null + foo: GET_VAR 'p0: .Foo declared in .CodeFragment.run' type=.Foo origin=null + other: CALL 'public final fun callString (string: kotlin.String): kotlin.Int declared in .NestedOuterClassKt' type=kotlin.Int origin=null + string: CALL 'private final fun (): kotlin.String declared in .Foo' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'p0: .Foo declared in .CodeFragment.run' type=.Foo origin=null + other: CALL 'public final fun callString (string: kotlin.String): kotlin.Int declared in .NestedOuterClassKt' type=kotlin.Int origin=null + string: CALL 'private final fun (): kotlin.String declared in .Foo.Bar' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'p1: .Foo.Bar declared in .CodeFragment.run' type=.Foo.Bar origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.kt new file mode 100644 index 00000000000..b21c4accd37 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.kt @@ -0,0 +1,19 @@ +class Foo { + private val a: String = "foo" + + inner class Bar { + private val b: String = "bar" + + fun test() { + val x = 0 + } + } +} + +fun callFoo(foo: Foo): Int { + return 0 +} + +fun callString(string: String): Int { + return 1 +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.txt new file mode 100644 index 00000000000..71e738e8c51 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.txt @@ -0,0 +1,6 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Foo, p1: Foo$Bar): int + public final inner class Foo$Bar +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.capturing.txt new file mode 100644 index 00000000000..bc27f31626c --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.capturing.txt @@ -0,0 +1 @@ +No captured values \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.fragment.kt new file mode 100644 index 00000000000..bba16b0d864 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.fragment.kt @@ -0,0 +1 @@ +call() \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt new file mode 100644 index 00000000000..b7d37e447f9 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.ir.txt @@ -0,0 +1,12 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + CALL 'public final fun call (): kotlin.Unit declared in .Foo' type=kotlin.Unit origin=null + $this: GET_OBJECT 'CLASS OBJECT name:Foo modality:FINAL visibility:public superTypes:[kotlin.Any]' type=.Foo diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.kt new file mode 100644 index 00000000000..5f760247486 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.kt @@ -0,0 +1,7 @@ +object Foo { + fun test() { + val x = 0 + } + + fun call() {} +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.txt new file mode 100644 index 00000000000..5edbac6f63e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(): void +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.capturing.txt new file mode 100644 index 00000000000..3976076166b --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.capturing.txt @@ -0,0 +1,3 @@ +ContainingClass[name: ; isMutated: false; displayText: this@Test] + class Test : R|kotlin/Any| + R|Test| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.fragment.kt new file mode 100644 index 00000000000..db0ac655185 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.fragment.kt @@ -0,0 +1 @@ +a.length \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.ir.txt new file mode 100644 index 00000000000..a8268fc0a41 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.ir.txt @@ -0,0 +1,14 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Test) returnType:kotlin.Int + VALUE_PARAMETER name:p0 index:0 type:.Test + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public open fun (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=GET_PROPERTY + $this: CALL 'public final fun (): kotlin.String declared in .Test' type=kotlin.String origin=GET_PROPERTY + $this: GET_VAR 'p0: .Test declared in .CodeFragment.run' type=.Test origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.kt new file mode 100644 index 00000000000..0abe1fdf206 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.kt @@ -0,0 +1,7 @@ +class Test { + val a: String = "foo" + + fun test() { + val x = 0 + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.txt new file mode 100644 index 00000000000..7e6d7645658 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Test): int +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.capturing.txt new file mode 100644 index 00000000000..3976076166b --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.capturing.txt @@ -0,0 +1,3 @@ +ContainingClass[name: ; isMutated: false; displayText: this@Test] + class Test : R|kotlin/Any| + R|Test| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.fragment.kt new file mode 100644 index 00000000000..805d25da792 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.fragment.kt @@ -0,0 +1 @@ +a = "bar" \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.ir.txt new file mode 100644 index 00000000000..a3682324011 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.ir.txt @@ -0,0 +1,14 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Test) returnType:kotlin.Unit + VALUE_PARAMETER name:p0 index:0 type:.Test + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + CALL 'public final fun (value: kotlin.String): kotlin.Unit declared in .Test' type=kotlin.Unit origin=EQ + $this: GET_VAR 'p0: .Test declared in .CodeFragment.run' type=.Test origin=null + value: CONST String type=kotlin.String value="bar" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.kt new file mode 100644 index 00000000000..de507b025ca --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.kt @@ -0,0 +1,7 @@ +class Test { + var a: String = "foo" + + fun test() { + val x = 0 + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.txt new file mode 100644 index 00000000000..db0b314e3a8 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Test): void +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.capturing.txt new file mode 100644 index 00000000000..3976076166b --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.capturing.txt @@ -0,0 +1,3 @@ +ContainingClass[name: ; isMutated: false; displayText: this@Test] + class Test : R|kotlin/Any| + R|Test| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt new file mode 100644 index 00000000000..805d25da792 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.fragment.kt @@ -0,0 +1 @@ +a = "bar" \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.ir.txt new file mode 100644 index 00000000000..1e4f88f2e35 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.ir.txt @@ -0,0 +1,14 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Test) returnType:kotlin.Unit + VALUE_PARAMETER name:p0 index:0 type:.Test + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + CALL 'private final fun (value: kotlin.String): kotlin.Unit declared in .Test' type=kotlin.Unit origin=EQ + $this: GET_VAR 'p0: .Test declared in .CodeFragment.run' type=.Test origin=null + value: CONST String type=kotlin.String value="bar" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.kt new file mode 100644 index 00000000000..bd463efec91 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.kt @@ -0,0 +1,7 @@ +class Test { + private var a: String = "foo" + + fun test() { + val x = 0 + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.txt new file mode 100644 index 00000000000..76d4103ab4e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Test): void +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.capturing.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.capturing.txt new file mode 100644 index 00000000000..0857cd9641f --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.capturing.txt @@ -0,0 +1,3 @@ +Local[name: foo; isMutated: false; displayText: foo] + foo: R|Foo?| + R|Foo?| diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.fragment.kt new file mode 100644 index 00000000000..98c062d7434 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.fragment.kt @@ -0,0 +1 @@ +foo?.call() \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.ir.txt new file mode 100644 index 00000000000..f5fbe3bd698 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.ir.txt @@ -0,0 +1,24 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> (p0:.Foo?) returnType:kotlin.Unit? + VALUE_PARAMETER name:p0 index:0 type:.Foo? + EXPRESSION_BODY + BLOCK type=kotlin.Unit? origin=null + BLOCK type=kotlin.Unit? origin=SAFE_CALL + VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:.Foo? [val] + GET_VAR 'p0: .Foo? declared in .CodeFragment.run' type=.Foo? origin=null + WHEN type=kotlin.Unit? origin=null + BRANCH + if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: GET_VAR 'val tmp_0: .Foo? [val] declared in .CodeFragment.run' type=.Foo? origin=null + arg1: CONST Null type=kotlin.Nothing? value=null + then: CONST Null type=kotlin.Nothing? value=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CALL 'public final fun call (): kotlin.Unit declared in .Foo' type=kotlin.Unit origin=null + $this: GET_VAR 'val tmp_0: .Foo? [val] declared in .CodeFragment.run' type=.Foo? origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.kt new file mode 100644 index 00000000000..88548fbce5a --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.kt @@ -0,0 +1,7 @@ +fun test(foo: Foo?) { + val x = 0 +} + +class Foo { + fun call() {} +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.txt new file mode 100644 index 00000000000..7633c83bb5e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(p0: Foo): kotlin.Unit +} diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.fragment.kt new file mode 100644 index 00000000000..7e9668e7834 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.fragment.kt @@ -0,0 +1 @@ +"foo" \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.ir.txt new file mode 100644 index 00000000000..671c052e810 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.ir.txt @@ -0,0 +1,11 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:MyCodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyCodeFragment + CONSTRUCTOR visibility:public <> () returnType:.MyCodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:invoke visibility:public modality:FINAL <> () returnType:kotlin.String + EXPRESSION_BODY + BLOCK type=kotlin.String origin=null + CONST String type=kotlin.String value="foo" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.kt new file mode 100644 index 00000000000..a261cff5864 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.kt @@ -0,0 +1,6 @@ +fun test() { + val x = 0 +} + +// CODE_FRAGMENT_CLASS_NAME: MyCodeFragment +// CODE_FRAGMENT_METHOD_NAME: invoke \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.txt new file mode 100644 index 00000000000..5afbd1b1588 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/customName.txt @@ -0,0 +1,5 @@ +public final class MyCodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method invoke(): java.lang.String +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.fragment.kt new file mode 100644 index 00000000000..65ee1a33c00 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.fragment.kt @@ -0,0 +1 @@ +TreeSet(File("foo").readLines()) \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.ir.txt new file mode 100644 index 00000000000..e174086351e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.ir.txt @@ -0,0 +1,15 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> () returnType:java.util.TreeSet<@[FlexibleNullability] kotlin.String?> + EXPRESSION_BODY + BLOCK type=java.util.TreeSet<@[FlexibleNullability] kotlin.String?> origin=null + CONSTRUCTOR_CALL 'public constructor (p0: @[FlexibleNullability] @[FlexibleMutability] kotlin.collections.MutableCollection?) declared in java.util.TreeSet' type=java.util.TreeSet<@[FlexibleNullability] kotlin.String?> origin=null + : @[FlexibleNullability] kotlin.String? + p0: CALL 'public final fun readLines (charset: java.nio.charset.Charset): kotlin.collections.List declared in kotlin.io' type=kotlin.collections.List origin=null + $receiver: CONSTRUCTOR_CALL 'public constructor (p0: @[FlexibleNullability] kotlin.String?) declared in java.io.File' type=java.io.File origin=null + p0: CONST String type=kotlin.String value="foo" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.kt new file mode 100644 index 00000000000..0c05866ee5a --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.kt @@ -0,0 +1,7 @@ +import java.util.TreeSet + +fun test() { + val x = 0 +} + +// CODE_FRAGMENT_IMPORT: java.io.File \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.txt new file mode 100644 index 00000000000..ca32dc3b4d4 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/imports.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(): java.util.TreeSet +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.fragment.kt new file mode 100644 index 00000000000..ac4e58e6be4 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.fragment.kt @@ -0,0 +1,4 @@ +listOf(1, 2, 3, 4, 5) + .filter { (it % 2) == 0 } + .map { it * 2 } + .forEach { System.out.println(it) } \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.ir.txt new file mode 100644 index 00000000000..ca6e4f62829 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.ir.txt @@ -0,0 +1,50 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + CALL 'public final fun forEach (action: kotlin.Function1): kotlin.Unit [inline] declared in kotlin.collections' type=kotlin.Unit origin=null + : kotlin.Int + $receiver: CALL 'public final fun map (transform: kotlin.Function1): kotlin.collections.List [inline] declared in kotlin.collections' type=kotlin.collections.List origin=null + : kotlin.Int + : kotlin.Int + $receiver: CALL 'public final fun filter (predicate: kotlin.Function1): kotlin.collections.List [inline] declared in kotlin.collections' type=kotlin.collections.List origin=null + : kotlin.Int + $receiver: CALL 'public final fun listOf (vararg elements: T of kotlin.collections.listOf): kotlin.collections.List declared in kotlin.collections' type=kotlin.collections.List origin=null + : kotlin.Int + elements: VARARG type=kotlin.Array varargElementType=kotlin.Int + CONST Int type=kotlin.Int value=1 + CONST Int type=kotlin.Int value=2 + CONST Int type=kotlin.Int value=3 + CONST Int type=kotlin.Int value=4 + CONST Int type=kotlin.Int value=5 + predicate: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Boolean + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Boolean declared in .CodeFragment.run' + CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ + arg0: CALL 'public final fun rem (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PERC + $this: GET_VAR 'it: kotlin.Int declared in .CodeFragment.run.' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=2 + arg1: CONST Int type=kotlin.Int value=0 + transform: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in .CodeFragment.run' + CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MUL + $this: GET_VAR 'it: kotlin.Int declared in .CodeFragment.run.' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=2 + action: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Unit + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + CALL 'public open fun println (p0: kotlin.Int): kotlin.Unit declared in java.io.PrintStream' type=kotlin.Unit origin=null + $this: GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:out type:@[FlexibleNullability] java.io.PrintStream? visibility:public [final,static]' type=@[FlexibleNullability] java.io.PrintStream? origin=GET_PROPERTY + p0: GET_VAR 'it: kotlin.Int declared in .CodeFragment.run.' type=kotlin.Int origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.kt new file mode 100644 index 00000000000..118d01da074 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.kt @@ -0,0 +1,3 @@ +fun test() { + val x = 0 +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.txt new file mode 100644 index 00000000000..5edbac6f63e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsage.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(): void +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.fragment.kt new file mode 100644 index 00000000000..2ee51b3ab89 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.fragment.kt @@ -0,0 +1 @@ +call { it * 2 } \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.ir.txt new file mode 100644 index 00000000000..75e03641a0b --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.ir.txt @@ -0,0 +1,32 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/inlineFunctionUsageSource.kt + FUN name:call visibility:public modality:FINAL <> (block:kotlin.Function1) returnType:kotlin.Unit [inline] + VALUE_PARAMETER name:block index:0 type:kotlin.Function1 + BLOCK_BODY + CALL 'public open fun println (p0: kotlin.Int): kotlin.Unit declared in java.io.PrintStream' type=kotlin.Unit origin=null + $this: GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:out type:@[FlexibleNullability] java.io.PrintStream? visibility:public [final,static]' type=@[FlexibleNullability] java.io.PrintStream? origin=GET_PROPERTY + p0: CALL 'public abstract fun invoke (p1: P1 of kotlin.Function1): R of kotlin.Function1 [operator] declared in kotlin.Function1' type=kotlin.Int origin=INVOKE + $this: GET_VAR 'block: kotlin.Function1 declared in .call' type=kotlin.Function1 origin=VARIABLE_AS_FUNCTION + p1: CONST Int type=kotlin.Int value=5 + FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + VAR name:x type:kotlin.Int [val] + CONST Int type=kotlin.Int value=0 + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Unit + EXPRESSION_BODY + BLOCK type=kotlin.Unit origin=null + CALL 'public final fun call (block: kotlin.Function1): kotlin.Unit [inline] declared in ' type=kotlin.Unit origin=null + block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int + VALUE_PARAMETER name:it index:0 type:kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in .CodeFragment.run' + CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MUL + $this: GET_VAR 'it: kotlin.Int declared in .CodeFragment.run.' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=2 diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.kt new file mode 100644 index 00000000000..60c1d28e0e7 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.kt @@ -0,0 +1,7 @@ +fun test() { + val x = 0 +} + +inline fun call(block: (Int) -> Int) { + System.out.println(block(5)) +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.txt new file mode 100644 index 00000000000..95179b726b6 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/inlineFunctionUsageSource.txt @@ -0,0 +1,7 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(): void +} + +public final class InlineFunctionUsageSourceKt diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.fragment.kt new file mode 100644 index 00000000000..d46fca6504e --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.fragment.kt @@ -0,0 +1,2 @@ +val a = 5 +a * 2 \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.ir.txt new file mode 100644 index 00000000000..a0bc98f23a0 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.ir.txt @@ -0,0 +1,15 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Int + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + VAR name:a type:kotlin.Int [val] + CONST Int type=kotlin.Int value=5 + CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MUL + $this: GET_VAR 'val a: kotlin.Int [val] declared in .CodeFragment.run' type=kotlin.Int origin=null + other: CONST Int type=kotlin.Int value=2 diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.kt new file mode 100644 index 00000000000..543baaa2f66 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.kt @@ -0,0 +1,3 @@ +fun foo() { + val x = 0 +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.txt new file mode 100644 index 00000000000..4d67aba51a6 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/local.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(): int +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.fragment.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.fragment.kt new file mode 100644 index 00000000000..ebf53c12af5 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.fragment.kt @@ -0,0 +1 @@ +2 + 2 * 2 \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.ir.txt new file mode 100644 index 00000000000..011b1e7f675 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.ir.txt @@ -0,0 +1,15 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/fragment.kt + CLASS CLASS name:CodeFragment modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.CodeFragment + CONSTRUCTOR visibility:public <> () returnType:.CodeFragment [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + FUN name:run visibility:public modality:FINAL <> () returnType:kotlin.Int + EXPRESSION_BODY + BLOCK type=kotlin.Int origin=null + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CONST Int type=kotlin.Int value=2 + other: CALL 'public final fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=MUL + $this: CONST Int type=kotlin.Int value=2 + other: CONST Int type=kotlin.Int value=2 diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.kt new file mode 100644 index 00000000000..118d01da074 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.kt @@ -0,0 +1,3 @@ +fun test() { + val x = 0 +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.txt new file mode 100644 index 00000000000..4d67aba51a6 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/simple.txt @@ -0,0 +1,5 @@ +public final class CodeFragment { + // source: 'fragment.kt' + public method (): void + public final static method run(): int +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.ir.txt new file mode 100644 index 00000000000..141de1b4bd6 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.ir.txt @@ -0,0 +1,8 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/imports.kt + FUN name:main visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun writeText (text: kotlin.String, charset: java.nio.charset.Charset): kotlin.Unit declared in kotlin.io' type=kotlin.Unit origin=null + $receiver: CONSTRUCTOR_CALL 'public constructor (p0: @[FlexibleNullability] kotlin.String?) declared in java.io.File' type=java.io.File origin=null + p0: CONST String type=kotlin.String value="foo" + text: CONST String type=kotlin.String value="Hello, world!" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.kt new file mode 100644 index 00000000000..0573b6a2e74 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.kt @@ -0,0 +1,5 @@ +import java.io.File + +fun main() { + File("foo").writeText("Hello, world!") +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.txt new file mode 100644 index 00000000000..2a7abb64856 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/imports.txt @@ -0,0 +1,5 @@ +public final class ImportsKt { + // source: 'imports.kt' + public final static method main(): void + public synthetic static method main(p0: java.lang.String[]): void +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.ir.txt new file mode 100644 index 00000000000..5a1bc0fcf26 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.ir.txt @@ -0,0 +1,29 @@ +MODULE_FRAGMENT name: + FILE fqName:main fileName:/main.kt + CLASS OBJECT name:Main modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:main.Main + CONSTRUCTOR visibility:private <> () returnType:main.Main [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS OBJECT name:Main modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:main visibility:public modality:FINAL <> ($this:main.Main, args:kotlin.Array) returnType:kotlin.Unit + annotations: + JvmStatic + $this: VALUE_PARAMETER name: type:main.Main + VALUE_PARAMETER name:args index:0 type:kotlin.Array + BLOCK_BODY + CALL 'public final fun foo (): kotlin.Unit declared in lib.Foo' type=kotlin.Unit origin=null + $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in lib.Foo' type=lib.Foo origin=null diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.kt new file mode 100644 index 00000000000..d3fd13039a0 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.kt @@ -0,0 +1,18 @@ +// FILE: lib.kt +package lib + +class Foo { + fun foo() {} +} + +// FILE: main.kt +package main + +import lib.Foo + +object Main { + @JvmStatic + fun main(args: Array) { + Foo().foo() + } +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.txt new file mode 100644 index 00000000000..365441a1e9f --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/multipleFiles.txt @@ -0,0 +1,7 @@ +public final class main/Main { + // source: 'main.kt' + public final static field INSTANCE: main.Main + static method (): void + private method (): void + public final static method main(p0: java.lang.String[]): void +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.ir.txt new file mode 100644 index 00000000000..f2db80f4750 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.ir.txt @@ -0,0 +1,6 @@ +MODULE_FRAGMENT name: + FILE fqName: fileName:/simple.kt + FUN name:main visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun println (message: kotlin.Any?): kotlin.Unit [inline] declared in kotlin.io' type=kotlin.Unit origin=null + message: CONST String type=kotlin.String value="Hello, world!" diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.kt b/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.kt new file mode 100644 index 00000000000..e95707aa981 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.kt @@ -0,0 +1,3 @@ +fun main() { + println("Hello, world!") +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.txt new file mode 100644 index 00000000000..927ed1101a9 --- /dev/null +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/simple.txt @@ -0,0 +1,5 @@ +public final class SimpleKt { + // source: 'simple.kt' + public final static method main(): void + public synthetic static method main(p0: java.lang.String[]): void +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CodeFragmentCapturedValueAnalyzer.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CodeFragmentCapturedValueAnalyzer.kt new file mode 100644 index 00000000000..c55dfca4979 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/compile/CodeFragmentCapturedValueAnalyzer.kt @@ -0,0 +1,286 @@ +/* + * 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.compile + +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.analysis.api.compile.CodeFragmentCapturedValue +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbol +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingKtFileIfAny +import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentsCodeFragmentAware +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol +import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.utils.isInline +import org.jetbrains.kotlin.fir.declarations.utils.isLocal +import org.jetbrains.kotlin.fir.expressions.FirResolvable +import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment +import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol +import org.jetbrains.kotlin.fir.labelName +import org.jetbrains.kotlin.fir.references.FirSuperReference +import org.jetbrains.kotlin.fir.references.FirThisReference +import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol +import org.jetbrains.kotlin.fir.resolve.constructFunctionType +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.specialFunctionTypeKind +import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.psi +import org.jetbrains.kotlin.psi.* +import java.util.* +import kotlin.collections.LinkedHashMap + +class CodeFragmentCapturedSymbol( + val value: CodeFragmentCapturedValue, + val symbol: FirBasedSymbol<*>, + val typeRef: FirTypeRef +) + +object CodeFragmentCapturedValueAnalyzer { + fun analyze(resolveSession: LLFirResolveSession, codeFragment: FirCodeFragment): CodeFragmentCapturedValueData { + val selfSymbols = CodeFragmentDeclarationCollector().apply { codeFragment.accept(this) }.symbols.toSet() + val capturedVisitor = CodeFragmentCapturedValueVisitor(resolveSession, selfSymbols) + codeFragment.accept(capturedVisitor) + return CodeFragmentCapturedValueData(capturedVisitor.values, capturedVisitor.files) + } +} + +class CodeFragmentCapturedValueData(val symbols: List, val files: List) + +private class CodeFragmentDeclarationCollector : FirDefaultVisitorVoid() { + private val collectedSymbols = mutableListOf>() + + val symbols: List> + get() = Collections.unmodifiableList(collectedSymbols) + + override fun visitElement(element: FirElement) { + if (element is FirDeclaration) { + collectedSymbols += element.symbol + } + + element.acceptChildren(this) + } +} + +private class CodeFragmentCapturedValueVisitor( + private val resolveSession: LLFirResolveSession, + private val selfSymbols: Set>, +) : FirDefaultVisitorVoid() { + private val collectedMappings = LinkedHashMap, CodeFragmentCapturedSymbol>() + private val collectedFiles = LinkedHashSet() + + private val assignmentLhs = mutableListOf>() + + val values: List + get() = collectedMappings.values.toList() + + val files: List + get() = collectedFiles.toList() + + private val session: FirSession + get() = resolveSession.useSiteFirSession + + override fun visitElement(element: FirElement) { + processElement(element) + + val lhs = (element as? FirVariableAssignment)?.lValue?.toResolvedCallableSymbol() + if (lhs != null) { + assignmentLhs.add(lhs) + } + + element.acceptChildren(this) + + if (lhs != null) { + require(assignmentLhs.removeLast() == lhs) + } + } + + private fun processElement(element: FirElement) { + when (element) { + is FirSuperReference -> { + val symbol = (element.superTypeRef as? FirResolvedTypeRef)?.toRegularClassSymbol(session) + if (symbol != null && symbol !in selfSymbols) { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.SuperClass(symbol.classId, isCrossingInlineBounds) + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, element.superTypeRef)) + } + } + is FirThisReference -> { + val symbol = element.boundSymbol + if (symbol != null && symbol !in selfSymbols) { + when (symbol) { + is FirClassSymbol<*> -> { + if (symbol.classKind != ClassKind.OBJECT) { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.ContainingClass(symbol.classId, isCrossingInlineBounds) + val typeRef = buildResolvedTypeRef { type = symbol.defaultType() } + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, typeRef)) + } + } + is FirFunctionSymbol<*> -> { + val contextReceiverNumber = element.contextReceiverNumber + if (contextReceiverNumber >= 0) { + val contextReceiver = symbol.resolvedContextReceivers[contextReceiverNumber] + val labelName = contextReceiver.labelName + if (labelName != null) { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue + .ContextReceiver(contextReceiverNumber, labelName, isCrossingInlineBounds) + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, contextReceiver.typeRef)) + } + } else { + val labelName = element.labelName + ?: (symbol as? FirAnonymousFunctionSymbol)?.label?.name + ?: symbol.name.asString() + + val typeRef = symbol.receiverParameter?.typeRef ?: error("Receiver parameter not found") + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.ExtensionReceiver(labelName, isCrossingInlineBounds) + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, typeRef)) + } + } + } + } + } + is FirResolvable -> { + val symbol = element.calleeReference.toResolvedCallableSymbol() + if (symbol != null && symbol !in selfSymbols) { + processCall(element, symbol) + } + } + is FirTypeRef -> { + val symbol = element.toClassLikeSymbol(session) + if (symbol != null && symbol !in selfSymbols) { + registerFile(symbol) + } + } + } + } + + private fun processCall(element: FirElement, symbol: FirCallableSymbol<*>) { + when (symbol) { + is FirValueParameterSymbol -> { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.Local(symbol.name, symbol.isMutated, isCrossingInlineBounds) + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, symbol.resolvedReturnTypeRef)) + } + is FirPropertySymbol -> { + if (symbol.isLocal) { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = when { + symbol.hasDelegate -> CodeFragmentCapturedValue.LocalDelegate(symbol.name, symbol.isMutated, isCrossingInlineBounds) + else -> CodeFragmentCapturedValue.Local(symbol.name, symbol.isMutated, isCrossingInlineBounds) + } + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, symbol.resolvedReturnTypeRef)) + } + } + is FirBackingFieldSymbol -> { + val propertyName = symbol.propertySymbol.name + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.BackingField(propertyName, symbol.isMutated, isCrossingInlineBounds) + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, symbol.resolvedReturnTypeRef)) + } + is FirNamedFunctionSymbol -> { + if (symbol.isLocal) { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.LocalFunction(symbol.name, isCrossingInlineBounds) + val firFunction = symbol.fir + val functionType = firFunction.constructFunctionType(firFunction.specialFunctionTypeKind(session)) + val typeRef = buildResolvedTypeRef { type = functionType } + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, typeRef)) + registerFile(symbol) + } + } + } + + if (symbol.callableId == StandardClassIds.Callables.coroutineContext) { + val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol) + val capturedValue = CodeFragmentCapturedValue.CoroutineContext(isCrossingInlineBounds) + register(symbol, CodeFragmentCapturedSymbol(capturedValue, symbol, symbol.resolvedReturnTypeRef)) + } + } + + private fun register(symbol: FirBasedSymbol<*>, mapping: CodeFragmentCapturedSymbol) { + val previousMapping = collectedMappings[symbol] + + if (previousMapping != null) { + val previousValue = previousMapping.value + val newValue = mapping.value + + require(previousValue.javaClass == newValue.javaClass) + + // Only replace non-mutated value with a mutated one. + if (previousValue.isMutated || !newValue.isMutated) { + return + } + } + + collectedMappings[symbol] = mapping + registerFile(symbol) + } + + private fun registerFile(symbol: FirBasedSymbol<*>) { + val needsRegistration = when (symbol) { + is FirRegularClassSymbol -> symbol.isLocal + is FirAnonymousObjectSymbol -> true + is FirNamedFunctionSymbol -> symbol.callableId.isLocal + else -> false + } + + if (!needsRegistration) { + return + } + + val file = symbol.fir.containingKtFileIfAny ?: return + if (!file.isCompiled) { + collectedFiles.add(file) + } + } + + private fun isCrossingInlineBounds(element: FirElement, symbol: FirBasedSymbol<*>): Boolean { + val callSite = element.source?.psi ?: return false + val declarationSite = symbol.fir.source?.psi ?: return false + val commonParent = findCommonParentContextAware(callSite, declarationSite) ?: return false + + for (elementInBetween in callSite.parentsCodeFragmentAware) { + if (elementInBetween === commonParent) { + break + } + + if (elementInBetween is KtFunction) { + val symbolInBetween = elementInBetween.resolveToFirSymbol(resolveSession) + if (symbolInBetween is FirCallableSymbol<*> && !symbolInBetween.isInline) { + return true + } + } + } + + return false + } + + private fun findCommonParentContextAware(callSite: PsiElement, declarationSite: PsiElement): PsiElement? { + val directParent = PsiTreeUtil.findCommonParent(callSite, declarationSite) + if (directParent != null) { + return directParent + } + + val codeFragment = callSite.containingFile as? KtCodeFragment ?: return null + val codeFragmentContext = codeFragment.context ?: return null + return PsiTreeUtil.findCommonParent(codeFragmentContext, declarationSite) + } + + private val FirBasedSymbol<*>.isMutated: Boolean + get() = assignmentLhs.lastOrNull() == this +} \ No newline at end of file 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 a22ebabdbd9..8186b27aab7 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 @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.canBePartOfParentDeclaration @@ -237,3 +238,15 @@ internal inline fun FirScript.forEachDependentDeclaration(action: (FirDeclaratio action(statement) } } + +val PsiElement.parentsWithSelfCodeFragmentAware: Sequence + get() = generateSequence(this) { element -> + when (element) { + is KtCodeFragment -> element.context + is PsiFile -> null + else -> element.parent + } + } + +val PsiElement.parentsCodeFragmentAware: Sequence + get() = parentsWithSelfCodeFragmentAware.drop(1) \ No newline at end of file diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCodeFragmentCapturingTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCodeFragmentCapturingTest.kt new file mode 100644 index 00000000000..ce996320b74 --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractCodeFragmentCapturingTest.kt @@ -0,0 +1,67 @@ +/* + * 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 + +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile +import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentCapturedValueAnalyzer +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider +import org.jetbrains.kotlin.analysis.test.framework.utils.indented +import org.jetbrains.kotlin.fir.declarations.FirCodeFragment +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.renderer.FirRenderer +import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase +import org.jetbrains.kotlin.psi.KtCodeFragment +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.directives.ConfigurationDirectives +import org.jetbrains.kotlin.test.services.TestModuleStructure +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.assertions + +abstract class AbstractCodeFragmentCapturingTest : AbstractLowLevelApiCodeFragmentTest() { + override fun doTest(ktCodeFragment: KtCodeFragment, moduleStructure: TestModuleStructure, testServices: TestServices) { + val project = ktCodeFragment.project + val module = ProjectStructureProvider.getModule(project, ktCodeFragment, contextualModule = null) + + val resolveSession = module.getFirResolveSession(project) + val firFile = ktCodeFragment.getOrBuildFirFile(resolveSession) + + val firCodeFragment = firFile.declarations.single() as FirCodeFragment + firCodeFragment.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) + + val capturedSymbols = CodeFragmentCapturedValueAnalyzer.analyze(resolveSession, firCodeFragment).symbols + + val actualText = capturedSymbols.joinToString("\n") { capturedSymbol -> + val firRenderer = FirRenderer( + bodyRenderer = null, + classMemberRenderer = null, + contractRenderer = null, + modifierRenderer = null + ) + + buildString { + append(capturedSymbol.value) + appendLine().append(firRenderer.renderElementAsString(capturedSymbol.symbol.fir).indented(4)) + appendLine().append(capturedSymbol.typeRef.render().indented(4)) + } + } + + testServices.assertions.assertEqualsToTestDataFileSibling( + actual = actualText.ifEmpty { "No captured values" }, + extension = ".capturing.txt" + ) + } + + override fun configureTest(builder: TestConfigurationBuilder) { + super.configureTest(builder) + with(builder) { + defaultDirectives { + +ConfigurationDirectives.WITH_STDLIB + } + } + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLowLevelApiCodeFragmentTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLowLevelApiCodeFragmentTest.kt new file mode 100644 index 00000000000..18516f99085 --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/AbstractLowLevelApiCodeFragmentTest.kt @@ -0,0 +1,43 @@ +/* + * 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 + +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest +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.psi.KtCodeFragment +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.test.services.TestModuleStructure +import org.jetbrains.kotlin.test.services.TestServices +import java.io.File + +abstract class AbstractLowLevelApiCodeFragmentTest : AbstractLowLevelApiSingleFileTest() { + override val configurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false) + + abstract fun doTest(ktCodeFragment: KtCodeFragment, moduleStructure: TestModuleStructure, testServices: TestServices) + + final override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) { + val contextElement = testServices.expressionMarkerProvider.getElementOfTypeAtCaret(ktFile) + + val fragmentText = moduleStructure.originalTestDataFiles.single() + .run { File(parent, "$nameWithoutExtension.fragment.$extension") } + .readText() + + val isBlockFragment = fragmentText.any { it == '\n' } + + val project = ktFile.project + val factory = KtPsiFactory(project, markGenerated = false) + + val ktCodeFragment = when { + isBlockFragment -> factory.createBlockCodeFragment(fragmentText, contextElement) + else -> factory.createExpressionCodeFragment(fragmentText, contextElement) + } + + doTest(ktCodeFragment, moduleStructure, testServices) + } +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java new file mode 100644 index 00000000000..9bed8e823ed --- /dev/null +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/CodeFragmentCapturingTestGenerated.java @@ -0,0 +1,116 @@ +/* + * 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; + +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/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing") +@TestDataPath("$PROJECT_ROOT") +public class CodeFragmentCapturingTestGenerated extends AbstractCodeFragmentCapturingTest { + @Test + public void testAllFilesPresentInCapturing() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("contextReceiver.kt") + public void testContextReceiver() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiver.kt"); + } + + @Test + @TestMetadata("contextReceiverExplicit.kt") + public void testContextReceiverExplicit() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/contextReceiverExplicit.kt"); + } + + @Test + @TestMetadata("extensionReceiver.kt") + public void testExtensionReceiver() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiver.kt"); + } + + @Test + @TestMetadata("extensionReceiverExplicit.kt") + public void testExtensionReceiverExplicit() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverExplicit.kt"); + } + + @Test + @TestMetadata("extensionReceiverLabeled.kt") + public void testExtensionReceiverLabeled() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/extensionReceiverLabeled.kt"); + } + + @Test + @TestMetadata("initializer.kt") + public void testInitializer() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/initializer.kt"); + } + + @Test + @TestMetadata("local.kt") + public void testLocal() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/local.kt"); + } + + @Test + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localFunction.kt"); + } + + @Test + @TestMetadata("localMutated.kt") + public void testLocalMutated() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/localMutated.kt"); + } + + @Test + @TestMetadata("nestedOuterClass.kt") + public void testNestedOuterClass() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/nestedOuterClass.kt"); + } + + @Test + @TestMetadata("objectFunction.kt") + public void testObjectFunction() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/objectFunction.kt"); + } + + @Test + @TestMetadata("outerClass.kt") + public void testOuterClass() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClass.kt"); + } + + @Test + @TestMetadata("outerClassMutated.kt") + public void testOuterClassMutated() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutated.kt"); + } + + @Test + @TestMetadata("outerClassMutatedPrivate.kt") + public void testOuterClassMutatedPrivate() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/outerClassMutatedPrivate.kt"); + } + + @Test + @TestMetadata("valueParameter.kt") + public void testValueParameter() throws Exception { + runTest("analysis/analysis-api/testData/components/compilerFacility/compilation/codeFragments/capturing/valueParameter.kt"); + } +} diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt index cd3aa991441..6a96d3ef7af 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/analysisApi.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.callRes import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.callResolver.AbstractResolveCallTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.callResolver.AbstractResolveCandidatesTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compileTimeConstantProvider.AbstractCompileTimeConstantEvaluatorTest +import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.compilerFacility.AbstractCompilerFacilityTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider.AbstractContainingDeclarationProviderByDelegatedMemberScopeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider.AbstractContainingDeclarationProviderByMemberScopeTest import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.components.containingDeclarationProvider.AbstractContainingDeclarationProviderByPsiTest @@ -215,6 +216,17 @@ private fun AnalysisApiTestGroup.generateAnalysisApiComponentsTests() { } } + component( + "compilerFacility", + filter = frontendIs(FrontendKind.Fir) + and analysisSessionModeIs(AnalysisSessionMode.Normal) + and analysisApiModeIs(AnalysisApiMode.Ide) + ) { + test(AbstractCompilerFacilityTest::class) { + model("compilation", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME) + } + } + component("compileTimeConstantProvider") { test(AbstractCompileTimeConstantEvaluatorTest::class) { model("evaluate") 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 651c73cf435..cc8f2fc4fc5 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 @@ -181,6 +181,12 @@ internal fun TestGroupSuite.generateFirLowLevelApiTests() { } } + testGroup("analysis/low-level-api-fir/tests", "analysis/analysis-api/testData") { + testClass { + model("components/compilerFacility/compilation/codeFragments/capturing", pattern = TestGeneratorUtil.KT_WITHOUT_DOTS_IN_NAME) + } + } + testGroup( "analysis/low-level-api-fir/tests", "compiler/fir/analysis-tests/testData",