Debugger: merge KotlinPositionManagerCache into KotlinDebuggerCaches

This commit is contained in:
Natalia Ukhorskaya
2016-01-25 15:25:45 +03:00
parent b5b2bbc9ab
commit 9b978377d0
6 changed files with 112 additions and 144 deletions
-3
View File
@@ -258,9 +258,6 @@
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches"
serviceImplementation="org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.KotlinPositionManagerCache"
serviceImplementation="org.jetbrains.kotlin.idea.debugger.KotlinPositionManagerCache"/>
<projectService serviceInterface="org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService"
serviceImplementation="org.jetbrains.kotlin.idea.stubindex.resolve.PluginDeclarationProviderFactoryService"/>
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.fileClasses.internalNameWithoutInnerClasses
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile
import org.jetbrains.kotlin.idea.refactoring.getLineStartOffset
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
@@ -67,7 +68,6 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.toReadOnlyList
import java.util.*
import com.intellij.debugger.engine.DebuggerUtils as JDebuggerUtils
@@ -160,7 +160,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
if (literalsOrFunctions.isEmpty()) return null;
val elementAt = file.findElementAt(start) ?: return null
val typeMapper = KotlinPositionManagerCache.getOrCreateTypeMapper(elementAt)
val typeMapper = KotlinDebuggerCaches.getOrCreateTypeMapper(elementAt)
val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).internalName
for (literal in literalsOrFunctions) {
@@ -269,11 +269,11 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
emptyList()
}
else {
KotlinPositionManagerCache.getOrComputeClassNames(element) {
KotlinDebuggerCaches.getOrComputeClassNames(element) {
element ->
val file = element.containingFile as KtFile
val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null
val typeMapper = KotlinPositionManagerCache.getOrCreateTypeMapper(element)
val typeMapper = KotlinDebuggerCaches.getOrCreateTypeMapper(element)
getInternalClassNameForElement(element, typeMapper, file, isInLibrary)
}
@@ -1,133 +0,0 @@
/*
* Copyright 2010-2016 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.kotlin.idea.debugger
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import java.util.*
class KotlinPositionManagerCache(private val project: Project) {
private val cachedClassNames = CachedValuesManager.getManager(project).createCachedValue(
{
CachedValueProvider.Result<HashMap<PsiElement, List<String>>>(
hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT)
}, false)
private val cachedTypeMappers = CachedValuesManager.getManager(project).createCachedValue(
{
CachedValueProvider.Result<HashMap<PsiElement, JetTypeMapper>>(
hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT)
}, false)
companion object {
fun getOrComputeClassNames(psiElement: PsiElement, create: (PsiElement) -> List<String>): List<String> {
val cache = getInstance(psiElement.project)
synchronized(cache.cachedClassNames) {
val classNamesCache = cache.cachedClassNames.value
val cachedValue = classNamesCache[psiElement]
if (cachedValue != null) return cachedValue
val newValue = create(psiElement)
classNamesCache[psiElement] = newValue
return newValue
}
}
fun getOrCreateTypeMapper(psiElement: PsiElement): JetTypeMapper {
val cache = getInstance(psiElement.project)
synchronized(cache.cachedTypeMappers) {
val typeMappersCache = cache.cachedTypeMappers.value
val file = psiElement.containingFile as KtFile
val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null
if (!isInLibrary) {
// Key = file
val cachedValue = typeMappersCache[file]
if (cachedValue != null) return cachedValue
val newValue = createTypeMapperForSourceFile(file)
typeMappersCache[file] = newValue
return newValue
}
else {
// key = KtElement
val element = getElementToCreateTypeMapperForLibraryFile(psiElement)
val cachedValue = typeMappersCache[psiElement]
if (cachedValue != null) return cachedValue
val newValue = createTypeMapperForLibraryFile(element, file)
typeMappersCache[psiElement] = newValue
return newValue
}
}
}
private fun getInstance(project: Project) = ServiceManager.getService(project, KotlinPositionManagerCache::class.java)!!
private fun createTypeMapperForLibraryFile(element: KtElement, file: KtFile): JetTypeMapper {
val analysisResult = element.analyzeAndGetResult()
val state = GenerationState(
file.project,
ClassBuilderFactories.THROW_EXCEPTION,
analysisResult.moduleDescriptor,
analysisResult.bindingContext,
listOf(file))
state.beforeCompile()
return state.typeMapper
}
private fun getElementToCreateTypeMapperForLibraryFile(element: PsiElement?) =
if (element is KtElement) element else PsiTreeUtil.getParentOfType(element, KtElement::class.java)!!
private fun createTypeMapperForSourceFile(file: KtFile): JetTypeMapper {
val analysisResult = file.analyzeFullyAndGetResult()
analysisResult.throwIfError()
val state = GenerationState(
file.project,
ClassBuilderFactories.THROW_EXCEPTION,
analysisResult.moduleDescriptor,
analysisResult.bindingContext,
listOf(file))
state.beforeCompile()
return state.typeMapper
}
@TestOnly fun addTypeMapper(file: KtFile, typeMapper: JetTypeMapper) {
getInstance(file.project).cachedTypeMappers.value[file] = typeMapper
}
}
}
@@ -20,6 +20,7 @@ import com.intellij.debugger.engine.DebugProcessImpl
import com.sun.jdi.*
import com.sun.tools.jdi.LocalVariableImpl
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtFunction
@@ -41,7 +42,7 @@ fun isInsideInlineArgument(inlineArgument: KtFunction, location: Location, debug
}
private fun lambdaOrdinalIndex(elementAt: KtFunction): Int {
val typeMapper = KotlinPositionManagerCache.getOrCreateTypeMapper(elementAt)
val typeMapper = KotlinDebuggerCaches.getOrCreateTypeMapper(elementAt)
val type = CodegenBinding.asmTypeForAnonymousClass(typeMapper.bindingContext, elementAt)
return type.className.substringAfterLast("$").toInt()
@@ -20,15 +20,26 @@ import com.intellij.debugger.SourcePosition
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.containers.MultiMap
import org.apache.log4j.Logger
import org.jetbrains.annotations.TestOnly
import org.jetbrains.eval4j.Value
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
@@ -41,6 +52,18 @@ class KotlinDebuggerCaches(private val project: Project) {
MultiMap.create(), PsiModificationTracker.MODIFICATION_COUNT)
}, false)
private val cachedClassNames = CachedValuesManager.getManager(project).createCachedValue(
{
CachedValueProvider.Result<HashMap<PsiElement, List<String>>>(
hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT)
}, false)
private val cachedTypeMappers = CachedValuesManager.getManager(project).createCachedValue(
{
CachedValueProvider.Result<HashMap<PsiElement, JetTypeMapper>>(
hashMapOf(), PsiModificationTracker.MODIFICATION_COUNT)
}, false)
companion object {
private val LOG = Logger.getLogger(KotlinDebuggerCaches::class.java)!!
@@ -70,6 +93,85 @@ class KotlinDebuggerCaches(private val project: Project) {
return@synchronized newCompiledData
}
}
fun getOrComputeClassNames(psiElement: PsiElement, create: (PsiElement) -> List<String>): List<String> {
val cache = getInstance(psiElement.project)
synchronized(cache.cachedClassNames) {
val classNamesCache = cache.cachedClassNames.value
val cachedValue = classNamesCache[psiElement]
if (cachedValue != null) return cachedValue
val newValue = create(psiElement)
classNamesCache[psiElement] = newValue
return newValue
}
}
fun getOrCreateTypeMapper(psiElement: PsiElement): JetTypeMapper {
val cache = getInstance(psiElement.project)
synchronized(cache.cachedTypeMappers) {
val typeMappersCache = cache.cachedTypeMappers.value
val file = psiElement.containingFile as KtFile
val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null
if (!isInLibrary) {
// Key = file
val cachedValue = typeMappersCache[file]
if (cachedValue != null) return cachedValue
val newValue = createTypeMapperForSourceFile(file)
typeMappersCache[file] = newValue
return newValue
}
else {
// key = KtElement
val element = getElementToCreateTypeMapperForLibraryFile(psiElement)
val cachedValue = typeMappersCache[psiElement]
if (cachedValue != null) return cachedValue
val newValue = createTypeMapperForLibraryFile(element, file)
typeMappersCache[psiElement] = newValue
return newValue
}
}
}
private fun createTypeMapperForLibraryFile(element: KtElement, file: KtFile): JetTypeMapper {
val analysisResult = element.analyzeAndGetResult()
val state = GenerationState(
file.project,
ClassBuilderFactories.THROW_EXCEPTION,
analysisResult.moduleDescriptor,
analysisResult.bindingContext,
listOf(file))
state.beforeCompile()
return state.typeMapper
}
private fun getElementToCreateTypeMapperForLibraryFile(element: PsiElement?) =
if (element is KtElement) element else PsiTreeUtil.getParentOfType(element, KtElement::class.java)!!
private fun createTypeMapperForSourceFile(file: KtFile): JetTypeMapper {
val analysisResult = file.analyzeFullyAndGetResult()
analysisResult.throwIfError()
val state = GenerationState(
file.project,
ClassBuilderFactories.THROW_EXCEPTION,
analysisResult.moduleDescriptor,
analysisResult.bindingContext,
listOf(file))
state.beforeCompile()
return state.typeMapper
}
@TestOnly fun addTypeMapper(file: KtFile, typeMapper: JetTypeMapper) {
getInstance(file.project).cachedTypeMappers.value[file] = typeMapper
}
}
private fun canBeEvaluatedInThisContext(compiledData: CompiledDataDescriptor, context: EvaluationContextImpl): Boolean {
@@ -32,16 +32,17 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.LightProjectDescriptor;
import com.sun.jdi.Location;
import com.sun.jdi.ReferenceType;
import kotlin.sequences.SequencesKt;
import kotlin.text.StringsKt;
import kotlin.Unit;
import kotlin.io.FilesKt;
import kotlin.jvm.functions.Function1;
import kotlin.sequences.SequencesKt;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.backend.common.output.OutputFile;
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection;
import org.jetbrains.kotlin.codegen.GenerationUtils;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches;
import org.jetbrains.kotlin.idea.project.PluginJetFilesProvider;
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
@@ -93,7 +94,7 @@ public abstract class AbstractPositionManagerTest extends KotlinLightCodeInsight
assertNotNull(positionManager);
for (KtFile file : files) {
KotlinPositionManagerCache.Companion.addTypeMapper(file, state.getTypeMapper());
KotlinDebuggerCaches.Companion.addTypeMapper(file, state.getTypeMapper());
}
return positionManager;