From f59701a6c46fffda733d9eda063a255ea0825a45 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 2 Apr 2013 14:29:23 +0400 Subject: [PATCH] Extract caching providers --- .../resolve/DeclarationsCacheProvider.java | 32 ++++ .../resolve/JSDeclarationsCacheProvider.java | 83 ++++++++++ .../resolve/JvmDeclarationsCacheProvider.java | 110 +++++++++++++ .../caches/resolve/KotlinCacheManager.java | 145 +++--------------- 4 files changed, 244 insertions(+), 126 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java create mode 100644 idea/src/org/jetbrains/jet/plugin/caches/resolve/JSDeclarationsCacheProvider.java create mode 100644 idea/src/org/jetbrains/jet/plugin/caches/resolve/JvmDeclarationsCacheProvider.java diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java new file mode 100644 index 00000000000..99d755aafd1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/DeclarationsCacheProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2013 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 org.jetbrains.jet.plugin.project.TargetPlatform; + +public abstract class DeclarationsCacheProvider { + protected final TargetPlatform platform; + protected final Project project; + + DeclarationsCacheProvider(Project project, TargetPlatform platform) { + this.platform = platform; + this.project = project; + } + + public abstract KotlinDeclarationsCache getDeclarations(boolean allowIncomplete); +} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/JSDeclarationsCacheProvider.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/JSDeclarationsCacheProvider.java new file mode 100644 index 00000000000..06442f7c9af --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/JSDeclarationsCacheProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright 2010-2013 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.google.common.base.Predicates; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiModificationTracker; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; +import org.jetbrains.jet.plugin.project.TargetPlatform; +import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS; +import org.jetbrains.k2js.config.EcmaVersion; +import org.jetbrains.k2js.config.LibrarySourcesConfig; + +class JSDeclarationsCacheProvider extends DeclarationsCacheProvider { + private final CachedValueProvider declarationsProvider; + private final Key> cachedKey; + private final Object declarationAnalysisLock = new Object(); + + JSDeclarationsCacheProvider(final Project project) { + super(project, TargetPlatform.JS); + + cachedKey = Key.create("KOTLIN_JS_DECLARATIONS_CACHE"); + + declarationsProvider = new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + synchronized (declarationAnalysisLock) { + LibrarySourcesConfig config = new LibrarySourcesConfig( + project, "default", + KotlinFrameworkDetector.getLibLocationAndTargetForProject(project).first, + EcmaVersion.defaultVersion()); + + AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJS.analyzeFiles( + JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)), + Predicates.alwaysFalse(), + config, + true); + + return Result.create( + new KotlinDeclarationsCacheImpl(analyzeExhaust), + PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT + ); + } + } + }; + } + + @Override + public KotlinDeclarationsCache getDeclarations(boolean allowIncomplete) { + synchronized (declarationAnalysisLock) { + return CachedValuesManager.getManager(project).getCachedValue( + project, + cachedKey, + declarationsProvider, + false + ); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/JvmDeclarationsCacheProvider.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/JvmDeclarationsCacheProvider.java new file mode 100644 index 00000000000..c0085421ef0 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/JvmDeclarationsCacheProvider.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2013 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.google.common.base.Predicates; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiModificationTracker; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; +import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; +import org.jetbrains.jet.plugin.project.TargetPlatform; + +import java.util.Collections; + +class JvmDeclarationsCacheProvider extends DeclarationsCacheProvider { + private final CachedValueProvider declarationsProvider; + private final Key> cachedKey; + private final Object declarationAnalysisLock = new Object(); + + private BindingTrace incompleteTrace; + + JvmDeclarationsCacheProvider(final Project project) { + super(project, TargetPlatform.JVM); + + cachedKey = Key.create("KOTLIN_JVM_DECLARATIONS_CACHE"); + + declarationsProvider = new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + // This lock is already acquired by the calling method, + // but we put it here to guard for the case of further modifications + synchronized (declarationAnalysisLock) { + BindingTraceContext trace = new BindingTraceContext(); + + incompleteTrace = trace; + AnalyzeExhaust analyzeExhaust; + try { + analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( + project, + JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)), + trace, + Collections.emptyList(), + Predicates.alwaysFalse(), + true); + } + finally { + incompleteTrace = null; + } + + return Result.create( + new KotlinDeclarationsCacheImpl(analyzeExhaust), + PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT + ); + } + } + }; + } + + @Override + @NotNull + public KotlinDeclarationsCache getDeclarations(boolean allowIncomplete) { + synchronized (declarationAnalysisLock) { + if (allowIncomplete) { + if (incompleteTrace != null) { + return new KotlinDeclarationsCache() { + @NotNull + @Override + public BindingContext getBindingContext() { + return incompleteTrace.getBindingContext(); + } + }; + } + } + + return CachedValuesManager.getManager(project).getCachedValue( + project, + cachedKey, + declarationsProvider, + false + ); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java index 9256fc99536..71492df9875 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/resolve/KotlinCacheManager.java @@ -16,101 +16,42 @@ package org.jetbrains.jet.plugin.caches.resolve; -import com.google.common.base.Predicates; +import com.google.common.collect.Maps; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; -import com.intellij.psi.PsiFile; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.CachedValue; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiModificationTracker; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.BindingTraceContext; -import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; -import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; -import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import org.jetbrains.jet.plugin.project.TargetPlatform; -import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS; -import org.jetbrains.k2js.config.EcmaVersion; -import org.jetbrains.k2js.config.LibrarySourcesConfig; -import java.util.Collections; +import java.util.Map; public class KotlinCacheManager { public static KotlinCacheManager getInstance(@NotNull Project project) { return ServiceManager.getService(project, KotlinCacheManager.class); } - private static final Key> KOTLIN_DECLARATIONS_CACHE = Key.create("KOTLIN_DECLARATIONS_CACHE"); - private static final Key> KOTLIN_JS_DECLARATIONS_CACHE = Key.create("KOTLIN_JS_DECLARATIONS_CACHE"); - - private final Project project; - private final Object declarationAnalysisLock = new Object(); - - private BindingTrace incompleteJvmTrace; + private final Map cacheProviders = Maps.newHashMap(); public KotlinCacheManager(@NotNull Project project) { - this.project = project; - } - - @NotNull - private KotlinDeclarationsCache getDeclarations(boolean allowIncomplete) { - // To prevent dead locks, the lock below must be obtained only inside a read action - ApplicationManager.getApplication().assertReadAccessAllowed(); - synchronized (declarationAnalysisLock) { - if (allowIncomplete) { - if (incompleteJvmTrace != null) { - return new KotlinDeclarationsCache() { - @NotNull - @Override - public BindingContext getBindingContext() { - return incompleteJvmTrace.getBindingContext(); - } - }; - } - } - - return CachedValuesManager.getManager(project).getCachedValue( - project, - KOTLIN_DECLARATIONS_CACHE, - new KotlinDeclarationsJvmCacheProvider(), - false - ); - } - } - - @NotNull - private KotlinDeclarationsCache getJsDeclarations() { - // To prevent dead locks, the lock below must be obtained only inside a read action - ApplicationManager.getApplication().assertReadAccessAllowed(); - synchronized (declarationAnalysisLock) { - return CachedValuesManager.getManager(project).getCachedValue( - project, - KOTLIN_JS_DECLARATIONS_CACHE, - new KotlinDeclarationsJsCacheProvider(), - false - ); - } + cacheProviders.put(TargetPlatform.JVM, new JvmDeclarationsCacheProvider(project)); + cacheProviders.put(TargetPlatform.JS, new JSDeclarationsCacheProvider(project)); } /** * Should be called under read lock. */ @NotNull - public KotlinDeclarationsCache getDeclarationsFromProject(TargetPlatform platform) { - return platform == TargetPlatform.JVM ? getDeclarations(false) : getJsDeclarations(); + public KotlinDeclarationsCache getDeclarationsFromProject(@NotNull TargetPlatform platform) { + // Computing declarations should be performed under read lock + ApplicationManager.getApplication().assertReadAccessAllowed(); + return getRegisteredProvider(platform).getDeclarations(false); } @NotNull public KotlinDeclarationsCache getPossiblyIncompleteDeclarationsForLightClassGeneration() { + // Computing declarations should be performed under read lock + ApplicationManager.getApplication().assertReadAccessAllowed(); + /* * If we have the following classes * @@ -126,64 +67,16 @@ public class KotlinCacheManager { * * Our workaround is to return partially complete results when we generate light classes */ - return getDeclarations(true); + return getRegisteredProvider(TargetPlatform.JVM).getDeclarations(true); } - private class KotlinDeclarationsJsCacheProvider implements CachedValueProvider { - @Nullable - @Override - public Result compute() { - // This lock is already acquired by the calling method, - // but we put it here to guard for the case of further modifications - synchronized (declarationAnalysisLock) { - LibrarySourcesConfig config = new LibrarySourcesConfig( - project, "default", - KotlinFrameworkDetector.getLibLocationAndTargetForProject(project).first, - EcmaVersion.defaultVersion()); - - AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJS.analyzeFiles( - JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)), - Predicates.alwaysFalse(), - config, - true); - - return Result.create( - new KotlinDeclarationsCacheImpl(analyzeExhaust), - PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT - ); - } + @NotNull + private DeclarationsCacheProvider getRegisteredProvider(TargetPlatform platform) { + DeclarationsCacheProvider provider = cacheProviders.get(platform); + if (provider == null) { + throw new IllegalStateException("Provider isn't registered for platform: " + platform); } - } - private class KotlinDeclarationsJvmCacheProvider implements CachedValueProvider { - @Nullable - @Override - public Result compute() { - // This lock is already acquired by the calling method, - // but we put it here to guard for the case of further modifications - synchronized (declarationAnalysisLock) { - BindingTraceContext trace = new BindingTraceContext(); - - incompleteJvmTrace = trace; - AnalyzeExhaust analyzeExhaust; - try { - analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - project, - JetFilesProvider.getInstance(project).allInScope(GlobalSearchScope.allScope(project)), - trace, - Collections.emptyList(), - Predicates.alwaysFalse(), - true); - } - finally { - incompleteJvmTrace = null; - } - - return Result.create( - new KotlinDeclarationsCacheImpl(analyzeExhaust), - PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT - ); - } - } + return provider; } }