[LL API] Avoid unnecessary BODY context collection

This commit is contained in:
Yan Zhulanow
2023-08-04 20:30:20 +09:00
committed by Space Team
parent 81d829ce3b
commit f31ffe4404
@@ -72,9 +72,10 @@ internal object ContextCollector {
* Returns `null` if the context was not collected. * Returns `null` if the context was not collected.
*/ */
fun process(file: FirFile, holder: SessionHolder, targetElement: PsiElement, bodyElement: PsiElement? = targetElement): Context? { fun process(file: FirFile, holder: SessionHolder, targetElement: PsiElement, bodyElement: PsiElement? = targetElement): Context? {
val isBodyContextCollected = bodyElement != null
val acceptedElements = targetElement.parentsWithSelf.toSet() val acceptedElements = targetElement.parentsWithSelf.toSet()
val contextProvider = process(computeResolveTarget(file, targetElement), holder) { candidate -> val contextProvider = process(computeResolveTarget(file, targetElement), holder, isBodyContextCollected) { candidate ->
when (candidate) { when (candidate) {
targetElement -> FilterResponse.STOP targetElement -> FilterResponse.STOP
in acceptedElements -> FilterResponse.CONTINUE in acceptedElements -> FilterResponse.CONTINUE
@@ -113,11 +114,21 @@ internal object ContextCollector {
/** /**
* Processes the [FirFile] that owns the [target], collecting contexts for elements matching the [filter]. * Processes the [FirFile] that owns the [target], collecting contexts for elements matching the [filter].
*
* @param target The target to process.
* @param holder The [SessionHolder] for the session that owns a [target].
* @param shouldCollectBodyContext If `true`, [ContextKind.BODY] is collected where available.
* @param filter The filter predicate. Context is collected only for [PsiElement]s for which the [filter] returns `true`.
*/ */
fun process(target: LLFirResolveTarget, holder: SessionHolder, filter: (PsiElement) -> FilterResponse): ContextProvider { fun process(
target: LLFirResolveTarget,
holder: SessionHolder,
shouldCollectBodyContext: Boolean,
filter: (PsiElement) -> FilterResponse
): ContextProvider {
val pathIterator = target.path.iterator() val pathIterator = target.path.iterator()
val visitor = ContextCollectorVisitor(holder, filter) { val visitor = ContextCollectorVisitor(holder, shouldCollectBodyContext, filter) {
if (pathIterator.hasNext()) pathIterator.next() else null if (pathIterator.hasNext()) pathIterator.next() else null
} }
@@ -134,6 +145,7 @@ internal object ContextCollector {
private class ContextCollectorVisitor( private class ContextCollectorVisitor(
private val holder: SessionHolder, private val holder: SessionHolder,
private val shouldCollectBodyContext: Boolean,
private val filter: (PsiElement) -> FilterResponse, private val filter: (PsiElement) -> FilterResponse,
private val interceptor: () -> FirElement? private val interceptor: () -> FirElement?
) : FirDefaultVisitorVoid() { ) : FirDefaultVisitorVoid() {
@@ -177,6 +189,10 @@ private class ContextCollectorVisitor(
return return
} }
if (kind == ContextKind.BODY && !shouldCollectBodyContext) {
return
}
val key = ContextKey(psi, kind) val key = ContextKey(psi, kind)
if (key in result) { if (key in result) {
return return
@@ -203,12 +219,14 @@ private class ContextCollectorVisitor(
override fun visitAnnotationCall(annotationCall: FirAnnotationCall) { override fun visitAnnotationCall(annotationCall: FirAnnotationCall) {
dumpContext(annotationCall.psi, ContextKind.SELF) dumpContext(annotationCall.psi, ContextKind.SELF)
context.forAnnotation { onActiveBody {
dumpContext(annotationCall.psi, ContextKind.BODY) context.forAnnotation {
dumpContext(annotationCall.psi, ContextKind.BODY)
// Technically, annotation arguments might contain arbitrary expressions. // Technically, annotation arguments might contain arbitrary expressions.
// However, such cases are very rare, as it's currently forbidden in Kotlin. // However, such cases are very rare, as it's currently forbidden in Kotlin.
// Here we ignore declarations that might be inside such expressions, avoiding unnecessary tree traversal. // Here we ignore declarations that might be inside such expressions, avoiding unnecessary tree traversal.
}
} }
} }
@@ -217,17 +235,19 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(regularClass) processSignatureAnnotations(regularClass)
context.withContainingClass(regularClass) { onActiveBody {
regularClass.lazyResolveToPhase(FirResolvePhase.STATUS) regularClass.lazyResolveToPhase(FirResolvePhase.STATUS)
processList(regularClass.typeParameters) context.withContainingClass(regularClass) {
processList(regularClass.typeParameters)
context.withRegularClass(regularClass, holder) { context.withRegularClass(regularClass, holder) {
dumpContext(regularClass.psi, ContextKind.BODY) dumpContext(regularClass.psi, ContextKind.BODY)
onActive { onActive {
withInterceptor { withInterceptor {
processChildren(regularClass) processChildren(regularClass)
}
} }
} }
} }
@@ -243,46 +263,50 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(constructor) processSignatureAnnotations(constructor)
context.withConstructor(constructor) { onActiveBody {
constructor.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) constructor.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
val owningClass = context.containerIfAny as? FirRegularClass context.withConstructor(constructor) {
context.forConstructorParameters(constructor, owningClass, holder) { val owningClass = context.containerIfAny as? FirRegularClass
processList(constructor.valueParameters) context.forConstructorParameters(constructor, owningClass, holder) {
} processList(constructor.valueParameters)
}
context.forConstructorBody(constructor, session) { context.forConstructorBody(constructor, session) {
processList(constructor.valueParameters) processList(constructor.valueParameters)
dumpContext(constructor.psi, ContextKind.BODY) dumpContext(constructor.psi, ContextKind.BODY)
onActive {
process(constructor.body)
}
}
onActive { onActive {
process(constructor.body) context.forDelegatedConstructorCall(constructor, owningClass = null, holder) {
process(constructor.delegatedConstructor)
}
} }
}
onActive { onActive {
context.forDelegatedConstructorCall(constructor, owningClass = null, holder) { processChildren(constructor)
process(constructor.delegatedConstructor)
} }
} }
onActive {
processChildren(constructor)
}
} }
} }
override fun visitEnumEntry(enumEntry: FirEnumEntry) { override fun visitEnumEntry(enumEntry: FirEnumEntry) {
dumpContext(enumEntry.psi, ContextKind.SELF) dumpContext(enumEntry.psi, ContextKind.SELF)
enumEntry.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) onActiveBody {
enumEntry.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
context.forEnumEntry { context.forEnumEntry {
dumpContext(enumEntry.psi, ContextKind.BODY) dumpContext(enumEntry.psi, ContextKind.BODY)
onActive { onActive {
super.visitEnumEntry(enumEntry) super.visitEnumEntry(enumEntry)
}
} }
} }
} }
@@ -290,24 +314,26 @@ private class ContextCollectorVisitor(
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) = withProcessor { override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) = withProcessor {
dumpContext(simpleFunction.psi, ContextKind.SELF) dumpContext(simpleFunction.psi, ContextKind.SELF)
simpleFunction.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
processSignatureAnnotations(simpleFunction) processSignatureAnnotations(simpleFunction)
context.withSimpleFunction(simpleFunction, session) { onActiveBody {
context.forFunctionBody(simpleFunction, holder) { simpleFunction.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
processList(simpleFunction.valueParameters)
dumpContext(simpleFunction.psi, ContextKind.BODY) context.withSimpleFunction(simpleFunction, session) {
context.forFunctionBody(simpleFunction, holder) {
processList(simpleFunction.valueParameters)
dumpContext(simpleFunction.psi, ContextKind.BODY)
onActive {
process(simpleFunction.body)
}
}
onActive { onActive {
process(simpleFunction.body) processChildren(simpleFunction)
} }
} }
onActive {
processChildren(simpleFunction)
}
} }
} }
@@ -316,21 +342,23 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(property) processSignatureAnnotations(property)
onActive { onActiveBody {
property.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) property.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
context.withProperty(property) { context.withProperty(property) {
context.forPropertyInitializer { dumpContext(property.psi, ContextKind.BODY)
onActive {
onActive {
context.forPropertyInitializer {
process(property.initializer) process(property.initializer)
}
onActive { onActive {
process(property.delegate) process(property.delegate)
} }
onActive { onActive {
process(property.backingField) process(property.backingField)
}
} }
} }
@@ -350,11 +378,13 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(propertyAccessor) processSignatureAnnotations(propertyAccessor)
context.withPropertyAccessor(propertyAccessor.propertySymbol.fir, propertyAccessor, holder) { onActiveBody {
dumpContext(propertyAccessor.psi, ContextKind.BODY) context.withPropertyAccessor(propertyAccessor.propertySymbol.fir, propertyAccessor, holder) {
dumpContext(propertyAccessor.psi, ContextKind.BODY)
onActive { onActive {
processChildren(propertyAccessor) processChildren(propertyAccessor)
}
} }
} }
} }
@@ -364,13 +394,16 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(valueParameter) processSignatureAnnotations(valueParameter)
context.withValueParameter(valueParameter, session) { onActiveBody {
dumpContext(valueParameter.psi, ContextKind.BODY) context.withValueParameter(valueParameter, session) {
dumpContext(valueParameter.psi, ContextKind.BODY)
onActive { onActive {
processChildren(valueParameter) processChildren(valueParameter)
}
} }
} }
} }
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer) = withProcessor { override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer) = withProcessor {
@@ -378,12 +411,14 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(anonymousInitializer) processSignatureAnnotations(anonymousInitializer)
context.withAnonymousInitializer(anonymousInitializer, session) { onActiveBody {
dumpContext(anonymousInitializer.psi, ContextKind.BODY) context.withAnonymousInitializer(anonymousInitializer, session) {
dumpContext(anonymousInitializer.psi, ContextKind.BODY)
onActive { onActive {
anonymousInitializer.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) anonymousInitializer.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
processChildren(anonymousInitializer) processChildren(anonymousInitializer)
}
} }
} }
} }
@@ -393,22 +428,25 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(anonymousFunction) processSignatureAnnotations(anonymousFunction)
context.withAnonymousFunction(anonymousFunction, holder, ResolutionMode.ContextIndependent) { onActiveBody {
for (parameter in anonymousFunction.valueParameters) { context.withAnonymousFunction(anonymousFunction, holder, ResolutionMode.ContextIndependent) {
process(parameter) for (parameter in anonymousFunction.valueParameters) {
context.storeVariable(parameter, holder.session) process(parameter)
} context.storeVariable(parameter, holder.session)
}
dumpContext(anonymousFunction.psi, ContextKind.BODY) dumpContext(anonymousFunction.psi, ContextKind.BODY)
onActive { onActive {
process(anonymousFunction.body) process(anonymousFunction.body)
} }
onActive { onActive {
processChildren(anonymousFunction) processChildren(anonymousFunction)
}
} }
} }
} }
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) = withProcessor { override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) = withProcessor {
@@ -416,22 +454,27 @@ private class ContextCollectorVisitor(
processSignatureAnnotations(anonymousObject) processSignatureAnnotations(anonymousObject)
context.withAnonymousObject(anonymousObject, holder) { onActiveBody {
dumpContext(anonymousObject.psi, ContextKind.BODY) context.withAnonymousObject(anonymousObject, holder) {
dumpContext(anonymousObject.psi, ContextKind.BODY)
onActive { onActive {
processChildren(anonymousObject) processChildren(anonymousObject)
}
} }
} }
} }
override fun visitBlock(block: FirBlock) = withProcessor { override fun visitBlock(block: FirBlock) = withProcessor {
dumpContext(block.psi, ContextKind.SELF) dumpContext(block.psi, ContextKind.SELF)
context.forBlock(session) { onActiveBody {
processChildren(block) context.forBlock(session) {
processChildren(block)
dumpContext(block.psi, ContextKind.BODY) dumpContext(block.psi, ContextKind.BODY)
}
} }
} }
@@ -514,6 +557,12 @@ private class ContextCollectorVisitor(
block() block()
} }
} }
private inline fun onActiveBody(block: () -> Unit) {
if (isActive || shouldCollectBodyContext) {
block()
}
}
} }
@DslMarker @DslMarker