diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java
index f66eca7696a..fe0c03de9df 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetFilesProvider.java
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.Collection;
public abstract class JetFilesProvider {
+ @NotNull
public static JetFilesProvider getInstance(Project project) {
return ServiceManager.getService(project, JetFilesProvider.class);
}
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index cc28417f9f4..230773b9caf 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -117,6 +117,9 @@
+
+
diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt
index 061e5c40568..18af6e85f25 100644
--- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt
+++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinResolveCache.kt
@@ -16,7 +16,6 @@
package org.jetbrains.jet.plugin.caches.resolve
-import org.jetbrains.jet.lang.resolve.lazy.ResolveSession
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.JetFile
import com.intellij.psi.util.PsiTreeUtil
@@ -40,19 +39,144 @@ import com.intellij.psi.util.CachedValueProvider
import org.jetbrains.jet.asJava.LightClassUtil
import com.intellij.openapi.roots.libraries.LibraryUtil
import org.jetbrains.jet.lang.resolve.LibrarySourceHacks
+import org.jetbrains.jet.lang.resolve.BindingContext
+import com.intellij.openapi.components.ServiceManager
+import org.jetbrains.jet.lang.resolve.java.JetFilesProvider
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.jet.plugin.project.AnalyzerFacadeProvider
+import org.jetbrains.jet.plugin.project.TargetPlatform
+import org.jetbrains.jet.plugin.project.TargetPlatform.*
+import org.jetbrains.jet.plugin.project.ResolveSessionForBodies
+import org.jetbrains.jet.plugin.project.TargetPlatformDetector
+import com.google.common.collect.ImmutableMap
+import org.jetbrains.jet.lang.resolve.Diagnostics
+import org.jetbrains.jet.util.slicedmap.ReadOnlySlice
+import org.jetbrains.jet.util.slicedmap.WritableSlice
+import org.jetbrains.jet.lang.diagnostics.Diagnostic
+import java.util.HashSet
private val LOG = Logger.getInstance(javaClass())
-class KotlinResolveCache(
+fun JetElement.getLazyResolveSession(): ResolveSessionForBodies {
+ return KotlinCacheService.getInstance(getProject()).getLazyResolveSession(this)
+}
+
+fun JetElement.getAnalysisResults(): AnalyzeExhaust {
+ return KotlinCacheService.getInstance(getProject()).getAnalysisResults(listOf(this))
+}
+
+fun JetElement.getBindingContext(): BindingContext {
+ return getAnalysisResults().getBindingContext()
+}
+
+fun getAnalysisResultsForElements(elements: Collection): AnalyzeExhaust {
+ if (elements.isEmpty()) return AnalyzeExhaust.EMPTY
+ val element = elements.first()
+ return KotlinCacheService.getInstance(element.getProject()).getAnalysisResults(elements)
+}
+
+class KotlinCacheService(val project: Project) {
+ class object {
+ fun getInstance(project: Project) = ServiceManager.getService(project, javaClass())!!
+ }
+
+ private fun globalResolveSessionProvider(platform: TargetPlatform, syntheticFile: JetFile? = null) = {
+ val allFiles = JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project))
+
+ val files = if (syntheticFile == null) allFiles else collectFilesForSyntheticFile(allFiles, syntheticFile)
+ val resolveSession = AnalyzerFacadeProvider.getAnalyzerFacade(platform).getLazyResolveSession(project, files)
+ CachedValueProvider.Result.create(ResolveSessionForBodies(project, resolveSession), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
+ }
+
+ private fun collectFilesForSyntheticFile(allFiles: Collection, syntheticFile: JetFile): Collection {
+ val files = HashSet(allFiles)
+
+ // Add requested file to the list of files for searching declarations
+ files.add(syntheticFile)
+
+ val originalFile = syntheticFile.getOriginalFile()
+ if (syntheticFile != originalFile) {
+ // Given file can be a non-physical copy of the file in list (completion case). Remove the prototype file.
+ files.remove(originalFile)
+ }
+
+ return files
+ }
+
+ private val globalCachesPerPlatform = mapOf(
+ JVM to KotlinResolveCache(project, globalResolveSessionProvider(JVM)),
+ JS to KotlinResolveCache(project, globalResolveSessionProvider(JS))
+ )
+
+ private val syntheticFileCaches = object : SLRUCache>(2, 3) {
+ override fun createValue(file: JetFile?): SynchronizedCachedValue {
+ return SynchronizedCachedValue(
+ project,
+ {
+ CachedValueProvider.Result(
+ KotlinResolveCache(
+ project,
+ globalResolveSessionProvider(
+ TargetPlatformDetector.getPlatform(file!!),
+ file
+ )
+ ),
+ PsiModificationTracker.MODIFICATION_COUNT
+ )
+ },
+ false)
+ }
+
+ }
+
+ public fun getLazyResolveSession(element: JetElement): ResolveSessionForBodies {
+ val file = element.getContainingJetFile()
+ if (!isFileInScope(file)) {
+ return synchronized(syntheticFileCaches) {
+ syntheticFileCaches[file].getValue().getLazyResolveSession()
+ }
+ }
+
+ return globalCachesPerPlatform[TargetPlatformDetector.getPlatform(file)]!!.getLazyResolveSession()
+ }
+
+ public fun getAnalysisResults(elements: Collection): AnalyzeExhaust {
+ if (elements.isEmpty()) return AnalyzeExhaust.EMPTY
+
+ val firstFile = elements.first().getContainingJetFile()
+ if (elements.size == 1 && !isFileInScope(firstFile)) {
+ return synchronized(syntheticFileCaches) {
+ syntheticFileCaches[firstFile].getValue().getAnalysisResultsForElements(elements)
+ }
+ }
+
+ val resolveCache = globalCachesPerPlatform[TargetPlatformDetector.getPlatform(firstFile)]!!
+ return synchronized(resolveCache) {
+ resolveCache.getAnalysisResultsForElements(elements)
+ }
+ }
+
+ private fun isFileInScope(jetFile: JetFile): Boolean {
+ val project = jetFile.getProject()
+ return JetFilesProvider.getInstance(project).isFileInScope(jetFile, GlobalSearchScope.allScope(project))
+ }
+}
+
+private class KotlinResolveCache(
val project: Project,
- val resolveSession: ResolveSession
+ val resolveSessionProvider: () -> CachedValueProvider.Result
) {
+ private val resolveSessionCache = SynchronizedCachedValue(project, resolveSessionProvider)
+
+ public fun getLazyResolveSession(): ResolveSessionForBodies = resolveSessionCache.getValue()
+
private data class Task(
val elements: Set
)
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue ({
+ val resolveSession = getLazyResolveSession()
val results = object : SLRUCache(2, 3) {
override fun createValue(task: Task?): AnalyzeExhaust {
if (DumbService.isDumb(project)) {
diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/chacheUtils.kt b/idea/src/org/jetbrains/jet/plugin/caches/resolve/chacheUtils.kt
new file mode 100644
index 00000000000..44f9b77cc85
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/chacheUtils.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.plugin.caches.resolve
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.util.PsiModificationTracker
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+import com.intellij.psi.util.CachedValuesManager
+import com.intellij.util.containers.SLRUCache
+import com.intellij.psi.util.CachedValueProvider
+
+class SynchronizedCachedValue(project: Project, provider: () -> CachedValueProvider.Result, trackValue: Boolean = true) {
+ private val cachedValue = CachedValuesManager.getManager(project).createCachedValue(
+ provider,
+ trackValue
+ )
+
+ public fun getValue(): V {
+ return synchronized(cachedValue) {
+ cachedValue.getValue() as V
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java
index 2c8ef111694..9d84874c021 100644
--- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java
+++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.plugin.caches.resolve.DeclarationsCacheProvider;
import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManager;
+import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import java.util.Collection;
import java.util.HashSet;
@@ -48,7 +49,7 @@ public final class AnalyzerFacadeWithCache {
// TODO: Also need to pass several files when user have multi-file environment
@NotNull
public static AnalyzeExhaust analyzeFileWithCache(@NotNull JetFile file) {
- return getLazyResolveSessionForFile(file).getResolveCache().getAnalysisResultsForElement(file);
+ return ResolvePackage.getAnalysisResults(file);
}
@NotNull
diff --git a/idea/src/org/jetbrains/jet/plugin/project/ResolveSessionForBodies.java b/idea/src/org/jetbrains/jet/plugin/project/ResolveSessionForBodies.java
index d957faa4e14..1d64d66f290 100644
--- a/idea/src/org/jetbrains/jet/plugin/project/ResolveSessionForBodies.java
+++ b/idea/src/org/jetbrains/jet/plugin/project/ResolveSessionForBodies.java
@@ -32,7 +32,6 @@ import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
-import org.jetbrains.jet.plugin.caches.resolve.KotlinResolveCache;
import org.jetbrains.jet.storage.ExceptionTracker;
import org.jetbrains.jet.storage.StorageManager;
@@ -42,7 +41,6 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
private final Object createdForObject;
private final ResolveSession resolveSession;
private final ResolveElementCache resolveElementCache;
- private final KotlinResolveCache resolveCache;
public ResolveSessionForBodies(@NotNull JetFile file, @NotNull ResolveSession resolveSession) {
this(file, file.getProject(), resolveSession);
@@ -56,7 +54,6 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
this.createdForObject = createdForObject;
this.resolveSession = resolveSession;
this.resolveElementCache = new ResolveElementCache(resolveSession, project);
- this.resolveCache = new KotlinResolveCache(project, resolveSession);
}
@NotNull
@@ -103,11 +100,6 @@ public class ResolveSessionForBodies implements KotlinCodeAnalyzer, Modification
return "ResolveSessionForBodies: " + getModificationCount() + " " + createdForObject + " " + createdForObject.hashCode();
}
- @NotNull
- public KotlinResolveCache getResolveCache() {
- return resolveCache;
- }
-
@Override
@Nullable
public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) {
diff --git a/idea/src/org/jetbrains/jet/plugin/util/DebuggerUtils.java b/idea/src/org/jetbrains/jet/plugin/util/DebuggerUtils.java
index 2c653207a12..c2bf5f6d798 100644
--- a/idea/src/org/jetbrains/jet/plugin/util/DebuggerUtils.java
+++ b/idea/src/org/jetbrains/jet/plugin/util/DebuggerUtils.java
@@ -27,7 +27,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.java.JetFilesProvider;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.name.FqName;
-import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
+import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import java.util.Collection;
@@ -72,8 +72,7 @@ public class DebuggerUtils {
// In the rare case that there's more than one file with this name in this package,
// we may actually need to analyze the project in order to find a file which produces this class
// TODO: this code is not entirely correct, because it takes a session for only one file
- AnalyzeExhaust analyzeExhaust = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(anyFile).getResolveCache()
- .getAnalysisResultsForElements(files);
+ AnalyzeExhaust analyzeExhaust = ResolvePackage.getAnalysisResultsForElements(files);
return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allPackageFiles, className.getInternalName());
}