From c4aab8340bcddf6061d7394c9b5e35daf3daba5b Mon Sep 17 00:00:00 2001 From: Natalia Selezneva Date: Fri, 14 Sep 2018 15:54:17 +0300 Subject: [PATCH] Do not store script definition in psiFile This may cause problems when definitions are reordered or switched off KT-27375 Fixed --- .../jetbrains/kotlin/codegen/ScriptCodegen.kt | 2 +- .../kotlin/codegen/context/ScriptContext.kt | 2 +- .../lazy/descriptors/LazyScriptDescriptor.kt | 6 ++--- .../org/jetbrains/kotlin/psi/KtScript.java | 10 +++----- .../script/KotlinScriptDefinitionProvider.kt | 8 +------ .../idea/caches/project/getModuleInfo.kt | 3 +-- .../core/script/ScriptDefinitionsManager.kt | 23 +++++++++++++++++++ .../core/script/ScriptDependenciesUpdater.kt | 4 ++-- 8 files changed, 35 insertions(+), 23 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt index d89f482f83c..5e7d2a70615 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ScriptCodegen.kt @@ -77,7 +77,7 @@ class ScriptCodegen private constructor( classBuilder: ClassBuilder, methodContext: MethodContext ) { - val scriptDefinition = scriptContext.script.kotlinScriptDefinition.value + val scriptDefinition = scriptContext.script.kotlinScriptDefinition val jvmSignature = typeMapper.mapScriptSignature( scriptDescriptor, diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.kt index 2422c6f95ae..bb83f117748 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/ScriptContext.kt @@ -77,7 +77,7 @@ class ScriptContext( scriptDescriptor.unsubstitutedPrimaryConstructor.valueParameters[ctorImplicitReceiversParametersStart + index].name.identifier fun getImplicitReceiverType(index: Int): Type? { - val receivers = script.kotlinScriptDefinition.value.implicitReceivers + val receivers = script.kotlinScriptDefinition.implicitReceivers val kClass = receivers.getOrNull(index)?.classifier as? KClass<*> return kClass?.java?.classId?.let(AsmUtil::asmTypeByClassId) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt index f5502230223..f18ccf054bf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyScriptDescriptor.kt @@ -18,7 +18,8 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.name.ClassId @@ -38,7 +39,6 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.script.KotlinScriptDefinition import org.jetbrains.kotlin.script.ScriptPriorities -import org.jetbrains.kotlin.script.findScriptDefinition import org.jetbrains.kotlin.types.TypeSubstitutor import kotlin.reflect.KClass import kotlin.reflect.KType @@ -69,7 +69,7 @@ class LazyScriptDescriptor( val scriptDefinition: () -> KotlinScriptDefinition = resolveSession.storageManager.createLazyValue { val file = scriptInfo.script.containingKtFile - findScriptDefinition(file) ?: throw RuntimeException("file ${file.name} is not a script") + scriptInfo.script.kotlinScriptDefinition ?: throw RuntimeException("file ${file.name} is not a script") } override fun substitute(substitutor: TypeSubstitutor) = this diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtScript.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtScript.java index bcbda5cfa71..079e93cf8bb 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtScript.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtScript.java @@ -18,8 +18,6 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.util.PsiTreeUtil; -import kotlin.Lazy; -import kotlin.LazyKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.stubs.KotlinScriptStub; @@ -29,14 +27,12 @@ import org.jetbrains.kotlin.script.ScriptDefinitionProvider; import java.util.List; -import static kotlin.LazyThreadSafetyMode.PUBLICATION; - public class KtScript extends KtNamedDeclarationStub implements KtDeclarationContainer { - public final Lazy kotlinScriptDefinition = LazyKt.lazy(PUBLICATION, () -> { + public KotlinScriptDefinition getKotlinScriptDefinition() { ScriptDefinitionProvider definitionsProvider = ScriptDefinitionProvider.Companion.getInstance(getProject()); KotlinScriptDefinition definition = definitionsProvider.findScriptDefinition(getContainingKtFile().getName()); return definition != null ? definition : definitionsProvider.getDefaultScriptDefinition(); - }); + } public KtScript(@NotNull ASTNode node) { super(node); @@ -54,7 +50,7 @@ public class KtScript extends KtNamedDeclarationStub implement return stub.getFqName(); } KtFile containingKtFile = getContainingKtFile(); - return containingKtFile.getPackageFqName().child(kotlinScriptDefinition.getValue().getScriptName(this)); + return containingKtFile.getPackageFqName().child(getKotlinScriptDefinition().getScriptName(this)); } @Override diff --git a/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt b/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt index e230d2d71e8..39bf94d0d11 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionProvider.kt @@ -22,7 +22,6 @@ import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.psi.KtFile @@ -55,18 +54,13 @@ fun findScriptDefinition(file: VirtualFile, project: Project): KotlinScriptDefin if (psiFile != null) { if (psiFile !is KtFile) return null if (!DumbService.isDumb(project)) { - return psiFile.script?.kotlinScriptDefinition?.value + return psiFile.script?.kotlinScriptDefinition } } return ScriptDefinitionProvider.getInstance(project).findScriptDefinition(file.name) } -fun findScriptDefinition(psiFile: PsiFile): KotlinScriptDefinition? { - if (psiFile.isDirectory) return null - return (psiFile as? KtFile)?.script?.kotlinScriptDefinition?.value -} - abstract class LazyScriptDefinitionProvider : ScriptDefinitionProvider { protected val lock = ReentrantReadWriteLock() diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt index 83ec4e2716c..2de5e19f81d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/project/getModuleInfo.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected import org.jetbrains.kotlin.idea.util.isKotlinBinary import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.script.findScriptDefinition import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.yieldIfNotNull @@ -169,7 +168,7 @@ private fun PsiElement.collectInfos(c: ModuleInfoCollector): T { getModuleRelatedModuleInfo(project, virtualFile)?.let { return c.onResult(it) } - findScriptDefinition(virtualFile, project)?.let { + containingKtFile.script?.kotlinScriptDefinition?.let { return c.onResult(ScriptModuleInfo(project, virtualFile, it)) } } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt index 034882171a1..b2efb62feae 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDefinitionsManager.kt @@ -32,6 +32,8 @@ import com.intellij.openapi.projectRoots.ex.PathUtilEx import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile +import com.intellij.ui.EditorNotifications +import com.intellij.util.containers.SLRUMap import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.caches.project.SdkInfo import org.jetbrains.kotlin.idea.caches.project.getScriptRelatedModuleInfo @@ -42,6 +44,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.flattenTo import java.io.File import java.net.URLClassLoader +import java.util.concurrent.locks.ReentrantReadWriteLock import kotlin.concurrent.write import kotlin.script.dependencies.Environment import kotlin.script.dependencies.ScriptContents @@ -61,6 +64,24 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit private var definitionsByContributor = mutableMapOf>() private var definitions: Sequence? = null + private val scriptDefinitionsCacheLock = ReentrantReadWriteLock() + private val scriptDefinitionsCache = SLRUMap(10, 10) + + override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? { + if (nonScriptFileName(fileName)) return null + + val cached = synchronized(scriptDefinitionsCacheLock) { scriptDefinitionsCache.get(fileName) } + if (cached != null) return cached + + val definition = super.findScriptDefinition(fileName) ?: return null + + synchronized(scriptDefinitionsCacheLock) { + scriptDefinitionsCache.put(fileName, definition) + } + + return definition + } + fun reloadDefinitionsBy(contributor: ScriptDefinitionContributor) = lock.write { if (definitions == null) return // not loaded yet @@ -129,6 +150,8 @@ class ScriptDefinitionsManager(private val project: Project) : LazyScriptDefinit } clearCache() + scriptDefinitionsCache.clear() + // TODO: clear by script type/definition ServiceManager.getService(project, ScriptDependenciesCache::class.java).clear() } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt index d886b8fc6d9..c2302cd9041 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/script/ScriptDependenciesUpdater.kt @@ -78,7 +78,7 @@ class ScriptDependenciesUpdater( if (ApplicationManager.getApplication().isUnitTestMode && ApplicationManager.getApplication().isScriptDependenciesUpdaterDisabled == true) return - val scriptDef = findScriptDefinition(ktFile) ?: return + val scriptDef = ktFile.script?.kotlinScriptDefinition ?: return if (!ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)) return ScriptDependenciesLoader.updateDependencies(file, scriptDef, project, shouldNotifyRootsChanged = true) @@ -104,7 +104,7 @@ class ScriptDependenciesUpdater( } val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return - val scriptDef = findScriptDefinition(ktFile) ?: return + val scriptDef = ktFile.script?.kotlinScriptDefinition ?: return if (!ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)) return