Binding trace filtering: do not calculate diagnostics if no one is going to query them

This commit is contained in:
Dmitry Jemerov
2016-09-26 12:48:46 +02:00
parent b365e547c4
commit d8b0c7aaec
24 changed files with 230 additions and 89 deletions
@@ -83,10 +83,11 @@ class ResolveElementCache(
},
false)
private class CachedPartialResolve(val bindingContext: BindingContext, file: KtFile) {
private class CachedPartialResolve(val bindingContext: BindingContext, file: KtFile, val filter: BindingTraceFilter) {
private val modificationStamp: Long? = modificationStamp(file)
fun isUpToDate(file: KtFile) = modificationStamp == modificationStamp(file)
fun isUpToDate(file: KtFile, newFilter: BindingTraceFilter) =
modificationStamp == modificationStamp(file) && filter.includesEverythingIn(newFilter)
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
@@ -117,7 +118,7 @@ class ResolveElementCache(
= getElementsAdditionalResolve(function, null, BodyResolveMode.FULL)
fun resolvePrimaryConstructorParametersDefaultValues(ktClass: KtClass): BindingContext {
return constructorAdditionalResolve(resolveSession, ktClass, ktClass.getContainingKtFile()).bindingContext
return constructorAdditionalResolve(resolveSession, ktClass, ktClass.getContainingKtFile(), BindingTraceFilter.NO_DIAGNOSTICS).bindingContext
}
@Deprecated("Use getElementsAdditionalResolve")
@@ -149,7 +150,16 @@ class ResolveElementCache(
return bindingContext
}
BodyResolveMode.PARTIAL -> {
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)
}
@@ -158,18 +168,18 @@ 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) }) { // partial resolve is already cached for these statements
if (cachedResults.all { it != null && it.isUpToDate(file, bodyResolveMode.bindingTraceFilter) }) { // partial resolve is already cached for these statements
return CompositeBindingContext.create(cachedResults.map { it!!.bindingContext }.distinct())
}
val (bindingContext, statementFilter) = performElementAdditionalResolve(resolveElement, contextElements, BodyResolveMode.PARTIAL)
val (bindingContext, statementFilter) = performElementAdditionalResolve(resolveElement, contextElements, bodyResolveMode)
if (statementFilter == StatementFilter.NONE) { // partial resolve is not supported for the given declaration - full resolve performed instead
fullResolveMap[resolveElement] = CachedFullResolve(bindingContext, resolveElement)
return bindingContext
}
val resolveToCache = CachedPartialResolve(bindingContext, file)
val resolveToCache = CachedPartialResolve(bindingContext, file, bodyResolveMode.bindingTraceFilter)
for (statement in (statementFilter as PartialBodyResolveFilter).allStatementsToResolve) {
if (!partialResolveMap.containsKey(statement) && bindingContext[BindingContext.PROCESSED, statement] == true) {
@@ -182,15 +192,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
}
}
}
@@ -311,17 +312,17 @@ class ResolveElementCache(
}
val trace: BindingTrace = when (resolveElement) {
is KtNamedFunction -> functionAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtNamedFunction -> functionAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtAnonymousInitializer -> initializerAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtAnonymousInitializer -> initializerAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtSecondaryConstructor -> secondaryConstructorAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtSecondaryConstructor -> secondaryConstructorAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtProperty -> propertyAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter())
is KtProperty -> propertyAdditionalResolve(resolveSession, resolveElement, file, createStatementFilter(), bodyResolveMode.bindingTraceFilter)
is KtSuperTypeList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtClassOrObject, file)
is KtSuperTypeList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtClassOrObject, file, bodyResolveMode.bindingTraceFilter)
is KtInitializerList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtEnumEntry, file)
is KtInitializerList -> delegationSpecifierAdditionalResolve(resolveSession, resolveElement, resolveElement.getParent() as KtEnumEntry, file, bodyResolveMode.bindingTraceFilter)
is KtImportList -> {
val resolver = resolveSession.fileScopeProvider.getImportResolver(resolveElement.getContainingKtFile())
@@ -341,9 +342,9 @@ class ResolveElementCache(
is KtAnnotationEntry -> annotationAdditionalResolve(resolveSession, resolveElement)
is KtClass -> constructorAdditionalResolve(resolveSession, resolveElement, file)
is KtClass -> constructorAdditionalResolve(resolveSession, resolveElement, file, bodyResolveMode.bindingTraceFilter)
is KtTypeAlias -> typealiasAdditionalResolve(resolveSession, resolveElement)
is KtTypeAlias -> typealiasAdditionalResolve(resolveSession, resolveElement, bodyResolveMode.bindingTraceFilter)
is KtTypeParameter -> typeParameterAdditionalResolve(resolveSession, resolveElement)
@@ -353,7 +354,7 @@ class ResolveElementCache(
else -> {
if (resolveElement.getParentOfType<KtPackageDirective>(true) != null) {
packageRefAdditionalResolve(resolveSession, resolveElement)
packageRefAdditionalResolve(resolveSession, resolveElement, bodyResolveMode.bindingTraceFilter)
}
else {
error("Invalid type of the topmost parent: $resolveElement\n${resolveElement.getElementTextWithContext()}")
@@ -368,8 +369,9 @@ class ResolveElementCache(
return Pair(trace.bindingContext, statementFilterUsed)
}
private fun packageRefAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement): BindingTrace {
val trace = createDelegatingTrace(ktElement)
private fun packageRefAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(ktElement, bindingTraceFilter)
if (ktElement is KtSimpleNameExpression) {
val header = ktElement.getParentOfType<KtPackageDirective>(true)!!
@@ -398,7 +400,7 @@ class ResolveElementCache(
}
private fun codeFragmentAdditionalResolve(codeFragment: KtCodeFragment, bodyResolveMode: BodyResolveMode): BindingTrace {
val trace = createDelegatingTrace(codeFragment)
val trace = createDelegatingTrace(codeFragment, bodyResolveMode.bindingTraceFilter)
val contextResolveMode = if (bodyResolveMode == BodyResolveMode.PARTIAL)
BodyResolveMode.PARTIAL_FOR_COMPLETION
@@ -456,8 +458,9 @@ class ResolveElementCache(
}
private fun delegationSpecifierAdditionalResolve(resolveSession: ResolveSession, ktElement: KtElement,
classOrObject: KtClassOrObject, file: KtFile): BindingTrace {
val trace = createDelegatingTrace(ktElement)
classOrObject: KtClassOrObject, file: KtFile,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(ktElement, bindingTraceFilter)
val descriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor
// Activate resolving of supertypes
@@ -475,8 +478,10 @@ class ResolveElementCache(
}
private fun propertyAdditionalResolve(resolveSession: ResolveSession, property: KtProperty,
file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(property)
file: KtFile,
statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(property, bindingTraceFilter)
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
val descriptor = resolveSession.resolveToDescriptor(property) as PropertyDescriptor
@@ -501,8 +506,9 @@ class ResolveElementCache(
}
private fun functionAdditionalResolve(resolveSession: ResolveSession, namedFunction: KtNamedFunction, file: KtFile,
statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(namedFunction)
statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(namedFunction, bindingTraceFilter)
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(namedFunction)
val functionDescriptor = resolveSession.resolveToDescriptor(namedFunction) as FunctionDescriptor
@@ -517,8 +523,9 @@ class ResolveElementCache(
}
private fun secondaryConstructorAdditionalResolve(resolveSession: ResolveSession, constructor: KtSecondaryConstructor,
file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(constructor)
file: KtFile, statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(constructor, bindingTraceFilter)
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(constructor)
val constructorDescriptor = resolveSession.resolveToDescriptor(constructor) as ClassConstructorDescriptor
@@ -532,8 +539,8 @@ class ResolveElementCache(
return trace
}
private fun constructorAdditionalResolve(resolveSession: ResolveSession, klass: KtClass, file: KtFile): BindingTrace {
val trace = createDelegatingTrace(klass)
private fun constructorAdditionalResolve(resolveSession: ResolveSession, klass: KtClass, file: KtFile, filter : BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(klass, filter)
val scope = resolveSession.declarationScopeProvider.getResolutionScopeForDeclaration(klass)
val classDescriptor = resolveSession.resolveToDescriptor(klass) as ClassDescriptor
@@ -547,8 +554,9 @@ class ResolveElementCache(
return trace
}
private fun typealiasAdditionalResolve(resolveSession: ResolveSession, typeAlias: KtTypeAlias): BindingTrace {
val trace = createDelegatingTrace(typeAlias)
private fun typealiasAdditionalResolve(resolveSession: ResolveSession, typeAlias: KtTypeAlias,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(typeAlias, bindingTraceFilter)
val typeAliasDescriptor = resolveSession.resolveToDescriptor(typeAlias)
ForceResolveUtil.forceResolveAllContents(typeAliasDescriptor)
forceResolveAnnotationsInside(typeAlias)
@@ -556,8 +564,9 @@ class ResolveElementCache(
}
private fun initializerAdditionalResolve(resolveSession: ResolveSession, anonymousInitializer: KtAnonymousInitializer,
file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(anonymousInitializer)
file: KtFile, statementFilter: StatementFilter,
bindingTraceFilter: BindingTraceFilter): BindingTrace {
val trace = createDelegatingTrace(anonymousInitializer, bindingTraceFilter)
val classOrObjectDescriptor = resolveSession.resolveToDescriptor(anonymousInitializer.containingDeclaration) as LazyClassDescriptor
@@ -595,9 +604,9 @@ class ResolveElementCache(
}
// All additional resolve should be done to separate trace
private fun createDelegatingTrace(resolveElement: KtElement): BindingTrace {
private fun createDelegatingTrace(resolveElement: KtElement, filter: BindingTraceFilter): BindingTrace {
return resolveSession.storageManager.createSafeTrace(
DelegatingBindingTrace(resolveSession.bindingContext, "trace to resolve element", resolveElement))
DelegatingBindingTrace(resolveSession.bindingContext, "trace to resolve element", resolveElement, filter))
}
private class BodyResolveContextForLazy(
@@ -70,7 +70,7 @@ abstract class AbstractKtReference<T : KtElement>(element: T)
override fun isSoft(): Boolean = false
private fun resolveToPsiElements(): Collection<PsiElement> {
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS)
return resolveToPsiElements(bindingContext, getTargetDescriptors(bindingContext))
}