[LL API] Add more flexible 'preferBodyPredicate'
The previous API required to pass the exact declaration element to the 'ContextCollector'. Now it's possible to get a 'BODY' context for some ancestor element.
This commit is contained in:
+2
-1
@@ -175,8 +175,9 @@ private class LLFirBodyTargetResolver(
|
|||||||
|
|
||||||
firCodeFragment.codeFragmentContext = if (contextKtFile != null) {
|
firCodeFragment.codeFragmentContext = if (contextKtFile != null) {
|
||||||
val contextFirFile = resolveSession.getOrBuildFirFile(contextKtFile)
|
val contextFirFile = resolveSession.getOrBuildFirFile(contextKtFile)
|
||||||
|
val sessionHolder = transformer.components
|
||||||
|
|
||||||
val elementContext = ContextCollector.process(contextFirFile, transformer.components, contextPsiElement, preferBody = true)
|
val elementContext = ContextCollector.process(contextFirFile, sessionHolder, contextPsiElement)
|
||||||
?: errorWithAttachment("Cannot find enclosing context for ${contextPsiElement::class}") {
|
?: errorWithAttachment("Cannot find enclosing context for ${contextPsiElement::class}") {
|
||||||
withPsiEntry("contextPsiElement", contextPsiElement)
|
withPsiEntry("contextPsiElement", contextPsiElement)
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-7
@@ -61,9 +61,17 @@ internal object ContextCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the [file], collecting contexts for the [targetElement] and all its PSI tree parents.
|
* Get the most precise context available for the [targetElement] in the [file].
|
||||||
|
*
|
||||||
|
* @param file The file to process.
|
||||||
|
* @param holder A [SessionHolder] for the session that owns a [file].
|
||||||
|
* @param targetElement The most precise element for which the context is required.
|
||||||
|
* @param bodyElement An element for which the [ContextKind.BODY] context is preferred.
|
||||||
|
*
|
||||||
|
* Returns the context of the [targetElement] if available, or of one of its tree parents.
|
||||||
|
* Returns `null` if the context was not collected.
|
||||||
*/
|
*/
|
||||||
fun process(file: FirFile, holder: SessionHolder, targetElement: PsiElement, preferBody: Boolean): Context? {
|
fun process(file: FirFile, holder: SessionHolder, targetElement: PsiElement, bodyElement: PsiElement? = targetElement): Context? {
|
||||||
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) { candidate ->
|
||||||
@@ -74,14 +82,21 @@ internal object ContextCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferBody) {
|
for (acceptedElement in acceptedElements) {
|
||||||
val bodyContext = contextProvider[targetElement, ContextKind.BODY]
|
if (acceptedElement === bodyElement) {
|
||||||
if (bodyContext != null) {
|
val bodyContext = contextProvider[acceptedElement, ContextKind.BODY]
|
||||||
return bodyContext
|
if (bodyContext != null) {
|
||||||
|
return bodyContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val elementContext = contextProvider[acceptedElement, ContextKind.SELF]
|
||||||
|
if (elementContext != null) {
|
||||||
|
return elementContext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return acceptedElements.firstNotNullOfOrNull { contextProvider[it, ContextKind.SELF] }
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeResolveTarget(file: FirFile, targetElement: PsiElement): LLFirResolveTarget {
|
private fun computeResolveTarget(file: FirFile, targetElement: PsiElement): LLFirResolveTarget {
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ abstract class AbstractContextCollectorTest : AbstractAnalysisApiBasedSingleModu
|
|||||||
val targetElement = testServices.expressionMarkerProvider
|
val targetElement = testServices.expressionMarkerProvider
|
||||||
.getBottommostSelectedElementOfType(mainKtFile, KtElement::class.java)
|
.getBottommostSelectedElementOfType(mainKtFile, KtElement::class.java)
|
||||||
|
|
||||||
val elementContext = ContextCollector.process(firFile, sessionHolder, targetElement) { it === targetElement }
|
val elementContext = ContextCollector.process(firFile, sessionHolder, targetElement)
|
||||||
?: error("Context not found for element $targetElement")
|
?: error("Context not found for element $targetElement")
|
||||||
|
|
||||||
val actualText = ElementContextRenderer.render(elementContext)
|
val actualText = ElementContextRenderer.render(elementContext)
|
||||||
|
|||||||
Reference in New Issue
Block a user