Debugger: merge KotlinPositionManagerCache into KotlinDebuggerCaches
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user