From 14d386223bd17a572bfde3e6390e03fa9bd8a648 Mon Sep 17 00:00:00 2001 From: Ilya Muradyan Date: Mon, 22 Mar 2021 14:20:36 +0300 Subject: [PATCH] [REPL] Fix unresolved imports caching Before this fix, if some imports were not resolved during compilation, this result had been saved in caches, and this import couldn't been resolved during following compilations even if it was added to the module dependencies. This commit adds special handling of resolution caches for the REPL compiler. --- .../compiler/TopDownAnalyzerFacadeForJVM.kt | 16 ++++++-- .../org/jetbrains/kotlin/context/context.kt | 6 ++- .../resolve/jvm/KotlinJavaPsiFacade.java | 37 +++++++++++-------- .../jvm/NotFoundPackagesCachingStrategy.kt | 30 +++++++++++++++ .../impl/LazyPackageViewDescriptorImpl.kt | 2 +- .../descriptors/impl/ModuleDescriptorImpl.kt | 6 ++- .../impl/PackageViewDescriptorFactory.kt | 29 +++++++++++++++ .../plugin/impl/KJvmReplCompilerBase.kt | 7 +++- .../ReplNotFoundPackagesCachingStrategy.kt | 14 +++++++ .../impl/ReplPackageViewDescriptorFactory.kt | 37 +++++++++++++++++++ .../compiler/plugin/repl/ReplCodeAnalyzer.kt | 5 ++- .../scripting/ide_services/JvmReplTest.kt | 17 +++++++++ 12 files changed, 179 insertions(+), 27 deletions(-) create mode 100644 compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/NotFoundPackagesCachingStrategy.kt create mode 100644 core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PackageViewDescriptorFactory.kt create mode 100644 plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplNotFoundPackagesCachingStrategy.kt create mode 100644 plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplPackageViewDescriptorFactory.kt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt index 5522d5d8f79..e8373e30e03 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/TopDownAnalyzerFacadeForJVM.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.context.ModuleContext import org.jetbrains.kotlin.context.MutableModuleContext import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleCapability import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider @@ -143,13 +144,14 @@ object TopDownAnalyzerFacadeForJVM { klibList: List = emptyList(), implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter? = null, explicitModuleDependencyList: List = emptyList(), - explicitModuleFriendsList: List = emptyList() + explicitModuleFriendsList: List = emptyList(), + moduleCapabilities: Map, Any?> = emptyMap() ): ComponentProvider { val jvmTarget = configuration.get(JVMConfigurationKeys.JVM_TARGET, JvmTarget.DEFAULT) val languageVersionSettings = configuration.languageVersionSettings val jvmPlatform = JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget) - val moduleContext = createModuleContext(project, configuration, jvmPlatform) + val moduleContext = createModuleContext(project, configuration, jvmPlatform, moduleCapabilities) val storageManager = moduleContext.storageManager val module = moduleContext.module @@ -318,11 +320,17 @@ object TopDownAnalyzerFacadeForJVM { } } - private fun createModuleContext(project: Project, configuration: CompilerConfiguration, platform: TargetPlatform?): MutableModuleContext { + private fun createModuleContext( + project: Project, + configuration: CompilerConfiguration, + platform: TargetPlatform?, + capabilities: Map, Any?> = emptyMap() + ): MutableModuleContext { val projectContext = ProjectContext(project, "TopDownAnalyzer for JVM") val builtIns = JvmBuiltIns(projectContext.storageManager, JvmBuiltIns.Kind.FROM_DEPENDENCIES) return ContextForNewModule( - projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, platform + projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), + builtIns, platform, capabilities ).apply { builtIns.builtInsModule = module } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/context/context.kt b/compiler/frontend/src/org/jetbrains/kotlin/context/context.kt index a1cf143871a..adaa86ff9a0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/context/context.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/context/context.kt @@ -20,6 +20,7 @@ import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.ModuleCapability import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl @@ -103,8 +104,9 @@ fun ContextForNewModule( projectContext: ProjectContext, moduleName: Name, builtIns: KotlinBuiltIns, - platform: TargetPlatform? + platform: TargetPlatform?, + capabilities: Map, Any?> = emptyMap(), ): MutableModuleContext { - val module = ModuleDescriptorImpl(moduleName, projectContext.storageManager, builtIns, platform) + val module = ModuleDescriptorImpl(moduleName, projectContext.storageManager, builtIns, platform, capabilities) return MutableModuleContextImpl(module, projectContext) } diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/KotlinJavaPsiFacade.java b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/KotlinJavaPsiFacade.java index c2ac39cb9cb..46b0254d03f 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/KotlinJavaPsiFacade.java +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/KotlinJavaPsiFacade.java @@ -83,6 +83,7 @@ public class KotlinJavaPsiFacade implements Disposable { } private volatile PackageCache packageCache; + private volatile NotFoundPackagesCachingStrategy notFoundPackagesCachingStrategy = NotFoundPackagesCachingStrategy.Default.INSTANCE; private final Project project; private final LightModifierList emptyModifierList; @@ -157,6 +158,10 @@ public class KotlinJavaPsiFacade implements Disposable { } } + public void setNotFoundPackagesCachingStrategy(NotFoundPackagesCachingStrategy notFoundPackagesCachingStrategy) { + this.notFoundPackagesCachingStrategy = notFoundPackagesCachingStrategy; + } + public LightModifierList getEmptyModifierList() { return emptyModifierList; } @@ -314,6 +319,8 @@ public class KotlinJavaPsiFacade implements Disposable { } boolean isALibrarySearchScope = isALibrarySearchScope(searchScope); + NotFoundPackagesCachingStrategy.CacheType notFoundCacheType = + notFoundPackagesCachingStrategy.chooseStrategy(isALibrarySearchScope, qualifiedName); { // store found package in a long term cache if package is found in library search scope @@ -353,24 +360,24 @@ public class KotlinJavaPsiFacade implements Disposable { } } - cache.hasPackageInAllScopeCache.put(qualifiedName, found); + if (found || notFoundCacheType != NotFoundPackagesCachingStrategy.CacheType.NO_CACHING) + cache.hasPackageInAllScopeCache.put(qualifiedName, found); } } - // qualifiedName could be like a proper package name, e.g `org.jetbrains.kotlin` - // but it could be as well part of typed text like `fooba` - // - // all those temporary names and those don't even look like a package name should be stored in a short term cache - // while names those are potentially proper package name could be stored for a long time - // (till PROJECT_ROOTS or specific VFS changes) - boolean packageLikeQName = qualifiedName.indexOf('.') > 0; - - ConcurrentMap, PsiPackage> notFoundPackageInScopeCache = - // store NULL_PACKAGE (attribute that package not found) in a long term cache if: - // - library search scope - // - qualifiedName looks like package (has `.` in its name) - isALibrarySearchScope && packageLikeQName ? - cache.packageInLibScopeCache : cache.packageInScopeCache; + ConcurrentMap, PsiPackage> notFoundPackageInScopeCache; + switch (notFoundCacheType) { + case LIB_SCOPE: + notFoundPackageInScopeCache = cache.packageInLibScopeCache; + break; + case SCOPE: + notFoundPackageInScopeCache = cache.packageInScopeCache; + break; + case NO_CACHING: + return null; + default: + throw new IllegalStateException("Impossible enum value: " + notFoundCacheType.toString()); + } return unwrap(ConcurrencyUtil.cacheOrGet(notFoundPackageInScopeCache, key, NULL_PACKAGE)); } diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/NotFoundPackagesCachingStrategy.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/NotFoundPackagesCachingStrategy.kt new file mode 100644 index 00000000000..35cb63e499f --- /dev/null +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/resolve/jvm/NotFoundPackagesCachingStrategy.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2021 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.resolve.jvm + +interface NotFoundPackagesCachingStrategy { + + fun chooseStrategy(isLibrarySearchScope: Boolean, qualifiedName: String): CacheType + + enum class CacheType { + LIB_SCOPE, SCOPE, NO_CACHING + } + + object Default : NotFoundPackagesCachingStrategy { + override fun chooseStrategy(isLibrarySearchScope: Boolean, qualifiedName: String): CacheType { + // qualifiedName could be like a proper package name, e.g `org.jetbrains.kotlin` + // but it could be as well part of typed text like `fooba` + // + // all those temporary names and those don't even look like a package name should be stored in a short term cache + // while names those are potentially proper package name could be stored for a long time + // (till PROJECT_ROOTS or specific VFS changes) + val packageLikeQName = qualifiedName.indexOf('.') > 0 + + return if (isLibrarySearchScope && packageLikeQName) CacheType.LIB_SCOPE + else CacheType.SCOPE + } + } +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazyPackageViewDescriptorImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazyPackageViewDescriptorImpl.kt index c3069310378..8732dec07fe 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazyPackageViewDescriptorImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazyPackageViewDescriptorImpl.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.getValue -class LazyPackageViewDescriptorImpl( +open class LazyPackageViewDescriptorImpl( override val module: ModuleDescriptorImpl, override val fqName: FqName, storageManager: StorageManager diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt index 07ce4f8e12a..660fc39bb45 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ModuleDescriptorImpl.kt @@ -38,6 +38,7 @@ class ModuleDescriptorImpl @JvmOverloads constructor( override val stableName: Name? = null, ) : DeclarationDescriptorImpl(Annotations.EMPTY, moduleName), ModuleDescriptor { private val capabilities: Map, Any?> + private val packageViewDescriptorFactory: PackageViewDescriptorFactory init { if (!moduleName.isSpecial) { @@ -46,6 +47,7 @@ class ModuleDescriptorImpl @JvmOverloads constructor( this.capabilities = capabilities.toMutableMap() @OptIn(TypeRefinement::class) this.capabilities[REFINER_CAPABILITY] = Ref(null) + packageViewDescriptorFactory = getCapability(PackageViewDescriptorFactory.CAPABILITY) ?: PackageViewDescriptorFactory.Default } private var dependencies: ModuleDependencies? = null @@ -63,8 +65,8 @@ class ModuleDescriptorImpl @JvmOverloads constructor( } } - private val packages = storageManager.createMemoizedFunction { fqName: FqName -> - LazyPackageViewDescriptorImpl(this, fqName, storageManager) + private val packages = storageManager.createMemoizedFunction { fqName: FqName -> + packageViewDescriptorFactory.compute(this, fqName, storageManager) } @Deprecated("This method is not going to be supported. Please do not use it") diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PackageViewDescriptorFactory.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PackageViewDescriptorFactory.kt new file mode 100644 index 00000000000..cc4262e1520 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PackageViewDescriptorFactory.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2021 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.descriptors.impl + +import org.jetbrains.kotlin.descriptors.ModuleCapability +import org.jetbrains.kotlin.descriptors.PackageViewDescriptor +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.storage.StorageManager + +interface PackageViewDescriptorFactory { + fun compute( + module: ModuleDescriptorImpl, + fqName: FqName, + storageManager: StorageManager + ): PackageViewDescriptor + + object Default: PackageViewDescriptorFactory { + override fun compute(module: ModuleDescriptorImpl, fqName: FqName, storageManager: StorageManager): PackageViewDescriptor { + return LazyPackageViewDescriptorImpl(module, fqName, storageManager) + } + } + + companion object { + val CAPABILITY = ModuleCapability("PackageViewDescriptorFactory") + } +} diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/KJvmReplCompilerBase.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/KJvmReplCompilerBase.kt index 8755b58c65c..c3c48164c73 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/KJvmReplCompilerBase.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/KJvmReplCompilerBase.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFilter +import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade import org.jetbrains.kotlin.scripting.compiler.plugin.repl.* import org.jetbrains.kotlin.scripting.definitions.ScriptDependenciesProvider import org.jetbrains.kotlin.scripting.resolve.skipExtensionsResolutionForImplicits @@ -333,8 +334,10 @@ class ReplCompilationState( override val baseScriptCompilationConfiguration: ScriptCompilationConfiguration get() = context.baseScriptCompilationConfiguration override val environment: KotlinCoreEnvironment get() = context.environment override val analyzerEngine: AnalyzerT by lazy { - // ReplCodeAnalyzer1(context.environment) - analyzerInit(context, implicitsResolutionFilter) + val analyzer = analyzerInit(context, implicitsResolutionFilter) + val psiFacade = KotlinJavaPsiFacade.getInstance(environment.project) + psiFacade.setNotFoundPackagesCachingStrategy(ReplNotFoundPackagesCachingStrategy) + analyzer } private val manglerAndSymbolTable by lazy { diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplNotFoundPackagesCachingStrategy.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplNotFoundPackagesCachingStrategy.kt new file mode 100644 index 00000000000..ca779d17305 --- /dev/null +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplNotFoundPackagesCachingStrategy.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2021 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.scripting.compiler.plugin.impl + +import org.jetbrains.kotlin.resolve.jvm.NotFoundPackagesCachingStrategy + +object ReplNotFoundPackagesCachingStrategy : NotFoundPackagesCachingStrategy { + override fun chooseStrategy(isLibrarySearchScope: Boolean, qualifiedName: String): NotFoundPackagesCachingStrategy.CacheType { + return NotFoundPackagesCachingStrategy.CacheType.NO_CACHING + } +} diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplPackageViewDescriptorFactory.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplPackageViewDescriptorFactory.kt new file mode 100644 index 00000000000..be0906fe953 --- /dev/null +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ReplPackageViewDescriptorFactory.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2021 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.scripting.compiler.plugin.impl + +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.descriptors.PackageViewDescriptor +import org.jetbrains.kotlin.descriptors.impl.LazyPackageViewDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.PackageViewDescriptorFactory +import org.jetbrains.kotlin.descriptors.packageFragments +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.storage.StorageManager + +object ReplPackageViewDescriptorFactory : PackageViewDescriptorFactory { + override fun compute(module: ModuleDescriptorImpl, fqName: FqName, storageManager: StorageManager): PackageViewDescriptor { + return ReplPackageViewDescriptor(module, fqName, storageManager) + } +} + +class ReplPackageViewDescriptor( + module: ModuleDescriptorImpl, + fqName: FqName, + storageManager: StorageManager +) : LazyPackageViewDescriptorImpl(module, fqName, storageManager) { + private var cachedFragments: List? = null + + override val fragments: List + get() { + cachedFragments?.let { return it } + val calculatedFragments = module.packageFragmentProvider.packageFragments(fqName) + if (calculatedFragments.isNotEmpty()) cachedFragments = calculatedFragments + return calculatedFragments + } +} diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplCodeAnalyzer.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplCodeAnalyzer.kt index e43dfec00de..dcbd2e6bb90 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplCodeAnalyzer.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/repl/ReplCodeAnalyzer.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.PackageViewDescriptorFactory import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile @@ -33,6 +34,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.* import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf import org.jetbrains.kotlin.resolve.scopes.utils.replaceImportingScopes +import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ReplPackageViewDescriptorFactory import org.jetbrains.kotlin.scripting.definitions.ScriptPriorities import kotlin.script.experimental.api.SourceCode import kotlin.script.experimental.jvm.util.CompiledHistoryItem @@ -65,7 +67,8 @@ open class ReplCodeAnalyzerBase( environment.configuration, environment::createPackagePartProvider, { _, _ -> ScriptMutableDeclarationProviderFactory() }, - implicitsResolutionFilter = implicitsResolutionFilter + implicitsResolutionFilter = implicitsResolutionFilter, + moduleCapabilities = mapOf(PackageViewDescriptorFactory.CAPABILITY to ReplPackageViewDescriptorFactory) ) this.module = container.get() diff --git a/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/JvmReplTest.kt b/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/JvmReplTest.kt index 8d0fee6bec5..7a85e1bc325 100644 --- a/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/JvmReplTest.kt +++ b/plugins/scripting/scripting-ide-services-test/test/org/jetbrains/kotlin/scripting/ide_services/JvmReplTest.kt @@ -296,6 +296,12 @@ class JvmIdeServicesTest : TestCase() { val (exitCode, outputJarPath) = compileFile("stringTo.kt", outputJarName) assertEquals(ExitCode.OK, exitCode) + assertCompileFails( + repl, """ + import example.dependency.* + """.trimIndent() + ) + assertEvalUnit( repl, """ @file:DependsOn("$outputJarPath") @@ -412,6 +418,17 @@ private fun JvmTestRepl.compileAndEval(codeLine: SourceCode): Pair