From 046c55a7ac6d7411b3ed55de9377037fcf4cb00d Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 26 Oct 2016 17:51:35 +0300 Subject: [PATCH] Caching for PARTIAL_FOR_COMPLETION resolve too (because it's used not only in completion) --- .../kotlin/resolve/lazy/BodyResolveMode.kt | 20 +++----- .../idea/project/ResolveElementCache.kt | 21 +++----- .../kotlin/idea/ResolveElementCacheTest.kt | 49 +++++++++++++++---- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/BodyResolveMode.kt b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/BodyResolveMode.kt index f59b607fe83..a11c7cdb4b3 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/BodyResolveMode.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/resolve/lazy/BodyResolveMode.kt @@ -18,19 +18,15 @@ package org.jetbrains.kotlin.resolve.lazy import org.jetbrains.kotlin.resolve.BindingTraceFilter -open class BodyResolveMode { - open val bindingTraceFilter: BindingTraceFilter = BindingTraceFilter.ACCEPT_ALL +enum class BodyResolveMode(val bindingTraceFilter: BindingTraceFilter) { + FULL(BindingTraceFilter.ACCEPT_ALL), + PARTIAL_FOR_COMPLETION(BindingTraceFilter.NO_DIAGNOSTICS), + PARTIAL_WITH_DIAGNOSTICS(BindingTraceFilter.ACCEPT_ALL), + PARTIAL(BindingTraceFilter.NO_DIAGNOSTICS) - companion object { - @JvmField val FULL = BodyResolveMode() + ; - @JvmField val PARTIAL = object : BodyResolveMode() { - override val bindingTraceFilter: BindingTraceFilter - get() = BindingTraceFilter.NO_DIAGNOSTICS - } - - @JvmField val PARTIAL_WITH_DIAGNOSTICS = BodyResolveMode() - - @JvmField val PARTIAL_FOR_COMPLETION = BodyResolveMode() + fun doesNotLessThan(other: BodyResolveMode): Boolean { + return this <= other && this.bindingTraceFilter.includesEverythingIn(other.bindingTraceFilter) } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index 2bdac2a60ff..6138aa9a336 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt @@ -83,11 +83,11 @@ class ResolveElementCache( }, false) - private class CachedPartialResolve(val bindingContext: BindingContext, file: KtFile, val filter: BindingTraceFilter) { + private class CachedPartialResolve(val bindingContext: BindingContext, file: KtFile, val mode: BodyResolveMode) { private val modificationStamp: Long? = modificationStamp(file) - fun isUpToDate(file: KtFile, newFilter: BindingTraceFilter) = - modificationStamp == modificationStamp(file) && filter.includesEverythingIn(newFilter) + fun isUpToDate(file: KtFile, newMode: BodyResolveMode) = + modificationStamp == modificationStamp(file) && mode.doesNotLessThan(newMode) private fun modificationStamp(file: KtFile): Long? { return if (!file.isPhysical) // for non-physical file we don't get MODIFICATION_COUNT increased and must reset data on any modification of the file @@ -150,15 +150,6 @@ class ResolveElementCache( return bindingContext } - BodyResolveMode.PARTIAL_FOR_COMPLETION -> { - if (resolveElement !is KtDeclaration) { - return getElementsAdditionalResolve(resolveElement, null, BodyResolveMode.FULL) - } - - // not cached - return performElementAdditionalResolve(resolveElement, contextElements, bodyResolveMode).first - } - else -> { if (resolveElement !is KtDeclaration) { return getElementsAdditionalResolve(resolveElement, null, BodyResolveMode.FULL) @@ -168,7 +159,7 @@ class ResolveElementCache( val statementsToResolve = contextElements!!.map { PartialBodyResolveFilter.findStatementToResolve(it, resolveElement) }.distinct() val partialResolveMap = partialBodyResolveCache.value val cachedResults = statementsToResolve.map { partialResolveMap[it ?: resolveElement] } - if (cachedResults.all { it != null && it.isUpToDate(file, bodyResolveMode.bindingTraceFilter) }) { // partial resolve is already cached for these statements + if (cachedResults.all { it != null && it.isUpToDate(file, bodyResolveMode) }) { // partial resolve is already cached for these statements return CompositeBindingContext.create(cachedResults.map { it!!.bindingContext }.distinct()) } @@ -179,7 +170,7 @@ class ResolveElementCache( return bindingContext } - val resolveToCache = CachedPartialResolve(bindingContext, file, bodyResolveMode.bindingTraceFilter) + val resolveToCache = CachedPartialResolve(bindingContext, file, bodyResolveMode) for (statement in (statementFilter as PartialBodyResolveFilter).allStatementsToResolve) { if (!partialResolveMap.containsKey(statement) && bindingContext[BindingContext.PROCESSED, statement] == true) { @@ -408,7 +399,7 @@ class ResolveElementCache( val modifierList = ktAnnotationEntry.getParentOfType(true) val declaration = modifierList?.getParentOfType(true) if (declaration != null) { - doResolveAnnotations(getAnnotationsByDeclaration(resolveSession, modifierList!!, declaration)) + doResolveAnnotations(getAnnotationsByDeclaration(resolveSession, modifierList, declaration)) } else { val fileAnnotationList = ktAnnotationEntry.getParentOfType(true) diff --git a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt index e0f55fd8002..6bdc1cd6dea 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt @@ -193,33 +193,40 @@ class C(param1: String = "", param2: Int = 0) { val bindingContext3 = statement2.analyze(BodyResolveMode.PARTIAL_FOR_COMPLETION) assert(bindingContext3 === bindingContext1) + + val bindingContext4 = statement2.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) + assert(bindingContext4 === bindingContext1) } } fun testPartialResolveCaching() { - doTest { this.testPartialResolveCaching() } + doTest { this.testPartialResolveCaching(BodyResolveMode.PARTIAL) } } - private fun Data.testPartialResolveCaching() { + fun testPartialForCompletionResolveCaching() { + doTest { this.testPartialResolveCaching(BodyResolveMode.PARTIAL_FOR_COMPLETION) } + } + + private fun Data.testPartialResolveCaching(mode: BodyResolveMode) { val statement1 = statements[0] val statement2 = statements[1] - val bindingContext1 = statement1.analyze(BodyResolveMode.PARTIAL) - val bindingContext2 = statement2.analyze(BodyResolveMode.PARTIAL) + val bindingContext1 = statement1.analyze(mode) + val bindingContext2 = statement2.analyze(mode) assert(bindingContext1 !== bindingContext2) - val bindingContext3 = statement1.analyze(BodyResolveMode.PARTIAL) - val bindingContext4 = statement2.analyze(BodyResolveMode.PARTIAL) + val bindingContext3 = statement1.analyze(mode) + val bindingContext4 = statement2.analyze(mode) assert(bindingContext3 === bindingContext1) assert(bindingContext4 === bindingContext2) file.add(factory.createFunction("fun foo(){}")) - val bindingContext5 = statement1.analyze(BodyResolveMode.PARTIAL) + val bindingContext5 = statement1.analyze(mode) assert(bindingContext5 !== bindingContext1) statement1.parent.addAfter(factory.createExpression("x()"), statement1) - val bindingContext6 = statement1.analyze(BodyResolveMode.PARTIAL) + val bindingContext6 = statement1.analyze(mode) assert(bindingContext6 !== bindingContext5) } @@ -227,7 +234,7 @@ class C(param1: String = "", param2: Int = 0) { doTest { val nonPhysicalFile = KtPsiFactory(project).createAnalyzableFile("NonPhysical.kt", FILE_TEXT, file) val nonPhysicalData = extractData(nonPhysicalFile) - nonPhysicalData.testPartialResolveCaching() + nonPhysicalData.testPartialResolveCaching(BodyResolveMode.PARTIAL) } } @@ -265,6 +272,30 @@ class C(param1: String = "", param2: Int = 0) { } } + fun testPartialForCompletionAndPartialAfter() { + doTest { + val statement = statements[0] + val bindingContext1 = statement.analyze(BodyResolveMode.PARTIAL_FOR_COMPLETION) + val bindingContext2 = statement.analyze(BodyResolveMode.PARTIAL) + assert(bindingContext2 === bindingContext1) + + val bindingContext3 = statement.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) + assert(bindingContext3 !== bindingContext1) + } + } + + fun testPartialWithDiagnosticsAndPartialAfter() { + doTest { + val statement = statements[0] + val bindingContext1 = statement.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) + val bindingContext2 = statement.analyze(BodyResolveMode.PARTIAL) + assert(bindingContext2 === bindingContext1) + + val bindingContext3 = statement.analyze(BodyResolveMode.PARTIAL_FOR_COMPLETION) + assert(bindingContext3 !== bindingContext1) + } + } + fun testFullResolvedCachedWhenPartialForConstructorInvoked() { doTest { val defaultValue1 = klass.getPrimaryConstructorParameters()[0].defaultValue!!