Debugger behavior fixed: backend relies on all relevant files being analyzed, not only one

This commit is contained in:
Andrey Breslav
2014-04-09 15:20:09 +04:00
parent 9da2cbd5e8
commit fdc42c6c1d
2 changed files with 22 additions and 14 deletions
@@ -44,11 +44,14 @@ class KotlinResolveCache(
val project: Project, val project: Project,
val resolveSession: ResolveSession val resolveSession: ResolveSession
) { ) {
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue ({
val results = object : SLRUCache<JetElement, AnalyzeExhaust>(2, 3) {
override fun createValue(element: JetElement?): AnalyzeExhaust {
element!!
private data class Task(
val elements: Set<JetElement>
)
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue ({
val results = object : SLRUCache<Task, AnalyzeExhaust>(2, 3) {
override fun createValue(task: Task?): AnalyzeExhaust {
if (DumbService.isDumb(project)) { if (DumbService.isDumb(project)) {
return AnalyzeExhaust.EMPTY return AnalyzeExhaust.EMPTY
} }
@@ -56,12 +59,8 @@ class KotlinResolveCache(
ApplicationUtils.warnTimeConsuming(LOG) ApplicationUtils.warnTimeConsuming(LOG)
try { try {
if (element !is JetFile) {
error("Only files are supported")
}
// todo: look for pre-existing results for this element or its parents // todo: look for pre-existing results for this element or its parents
val trace = DelegatingBindingTrace(resolveSession.getBindingContext(), "Trace for resolution of " + element) val trace = DelegatingBindingTrace(resolveSession.getBindingContext(), "Trace for resolution of " + task!!.elements.makeString(", "))
val injector = InjectorForTopDownAnalyzerForJvm( val injector = InjectorForTopDownAnalyzerForJvm(
project, project,
SimpleGlobalContext(resolveSession.getStorageManager(), resolveSession.getExceptionTracker()), SimpleGlobalContext(resolveSession.getStorageManager(), resolveSession.getExceptionTracker()),
@@ -78,7 +77,7 @@ class KotlinResolveCache(
analyzingBootstrapLibrary = false, analyzingBootstrapLibrary = false,
declaredLocally = false declaredLocally = false
), ),
listOf(getContainingNonlocalDeclaration(element)) task.elements.map { getContainingNonlocalDeclaration(it) }
) )
return AnalyzeExhaust.success( return AnalyzeExhaust.success(
trace.getBindingContext(), trace.getBindingContext(),
@@ -104,12 +103,20 @@ class KotlinResolveCache(
CachedValueProvider.Result(results, PsiModificationTracker.MODIFICATION_COUNT, resolveSession.getExceptionTracker()) CachedValueProvider.Result(results, PsiModificationTracker.MODIFICATION_COUNT, resolveSession.getExceptionTracker())
}, false) }, false)
fun getAnalysisResultsForElement(element: JetElement): AnalyzeExhaust { private fun getAnalysisResults(task: Task): AnalyzeExhaust {
return synchronized(analysisResults) { return synchronized(analysisResults) {
analysisResults.getValue()!![element] analysisResults.getValue()!![task]
} }
} }
fun getAnalysisResultsForElement(element: JetElement): AnalyzeExhaust {
return getAnalysisResults(Task(setOf(element)))
}
fun getAnalysisResultsForElements(elements: Collection<JetElement>): AnalyzeExhaust {
return getAnalysisResults(Task(elements.toSet()))
}
private fun getContainingNonlocalDeclaration(element: JetElement): JetElement? { private fun getContainingNonlocalDeclaration(element: JetElement): JetElement? {
return PsiTreeUtil.getParentOfType(element, javaClass<JetFile>(), false); return PsiTreeUtil.getParentOfType(element, javaClass<JetFile>(), false);
} }
@@ -119,4 +126,3 @@ class KotlinResolveCache(
LOG.error(e) LOG.error(e)
} }
} }
@@ -71,7 +71,9 @@ public class DebuggerUtils {
// In the rare case that there's more than one file with this name in this package, // 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 // we may actually need to analyze the project in order to find a file which produces this class
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeWithCache.analyzeFileWithCache(anyFile); // TODO: this code is not entirely correct, because it takes a session for only one file
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(anyFile).getResolveCache()
.getAnalysisResultsForElements(files);
return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allPackageFiles, className.getInternalName()); return PsiCodegenPredictor.getFileForCodegenNamedClass(analyzeExhaust.getBindingContext(), allPackageFiles, className.getInternalName());
} }