[Analysis API] allow AbstractSingleSymbolByPsi to accept <expr>-based section in addition to <caret>-based
This commit is contained in:
committed by
Space Team
parent
729bae4a2a
commit
1b0034b6e7
+5
-1
@@ -10,10 +10,14 @@ import org.jetbrains.kotlin.analysis.test.framework.services.expressionMarkerPro
|
|||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
import org.jetbrains.kotlin.test.services.moduleStructure
|
||||||
|
|
||||||
abstract class AbstractSingleSymbolByPsi : AbstractSymbolTest() {
|
abstract class AbstractSingleSymbolByPsi : AbstractSymbolTest() {
|
||||||
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): SymbolsData {
|
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): SymbolsData {
|
||||||
val declaration = testServices.expressionMarkerProvider.getElementOfTypeAtCaret<KtDeclaration>(ktFile)
|
val declaration = testServices.expressionMarkerProvider.getSelectedElementOrElementAtCaretOfTypeByDirective(
|
||||||
|
ktFile, testServices.moduleStructure.modules.first(),
|
||||||
|
KtDeclaration::class
|
||||||
|
) as KtDeclaration
|
||||||
val symbol = declaration.getSymbol()
|
val symbol = declaration.getSymbol()
|
||||||
return SymbolsData(listOf(symbol))
|
return SymbolsData(listOf(symbol))
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-1
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.test.services.TestModuleStructure
|
|||||||
import org.jetbrains.kotlin.test.services.TestService
|
import org.jetbrains.kotlin.test.services.TestService
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
internal class ExpressionMarkersSourceFilePreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
|
internal class ExpressionMarkersSourceFilePreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
|
||||||
override fun process(file: TestFile, content: String): String {
|
override fun process(file: TestFile, content: String): String {
|
||||||
@@ -147,6 +148,40 @@ class ExpressionMarkerProvider : TestService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSelectedElementOrElementAtCaretOfTypeByDirective(
|
||||||
|
ktFile: KtFile,
|
||||||
|
module: TestModule,
|
||||||
|
defaultType: KClass<out PsiElement>? = null,
|
||||||
|
caretTag: String? = null,
|
||||||
|
): PsiElement {
|
||||||
|
val expectedClass = expectedTypeClass(module.directives) ?: defaultType?.java
|
||||||
|
return getSelectedElementOfClassOrNull(ktFile, expectedClass)
|
||||||
|
?: getElementOfClassAtCaretOrNull(ktFile, expectedClass, caretTag)
|
||||||
|
?: error("Neither ${ExpressionMarkersSourceFilePreprocessor.TAGS.OPENING_EXPRESSION_TAG} marker nor <caret> were found in file")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSelectedElementOfClassOrNull(
|
||||||
|
ktFile: KtFile,
|
||||||
|
expectedClass: Class<out PsiElement>?,
|
||||||
|
): PsiElement? {
|
||||||
|
val selectedElement = getSelectedElementOrNull(ktFile) ?: return null
|
||||||
|
if (expectedClass == null) return selectedElement
|
||||||
|
return findDescendantOfTheSameRangeOfType(selectedElement, expectedClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getElementOfClassAtCaretOrNull(
|
||||||
|
ktFile: KtFile,
|
||||||
|
expectedClass: Class<out PsiElement>?,
|
||||||
|
caretTag: String? = null,
|
||||||
|
): PsiElement? {
|
||||||
|
val caretPosition = getCaretPositionOrNull(ktFile, caretTag) ?: return null
|
||||||
|
val elementAtPosition = ktFile.findElementAt(caretPosition) ?: return null
|
||||||
|
if (expectedClass == null) return elementAtPosition
|
||||||
|
return PsiTreeUtil.getParentOfType(elementAtPosition, expectedClass, /*strict*/false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getSelectedElementOrNull(file: KtFile): PsiElement? {
|
fun getSelectedElementOrNull(file: KtFile): PsiElement? {
|
||||||
val range = selected[file.name] ?: return null
|
val range = selected[file.name] ?: return null
|
||||||
val elements = file.elementsInRange(range).trimWhitespaces()
|
val elements = file.elementsInRange(range).trimWhitespaces()
|
||||||
@@ -175,8 +210,12 @@ class ExpressionMarkerProvider : TestService {
|
|||||||
val expectedType = expectedTypeClass(module.directives) ?: return selectedElement
|
val expectedType = expectedTypeClass(module.directives) ?: return selectedElement
|
||||||
if (expectedType.isInstance(selectedElement)) return selectedElement
|
if (expectedType.isInstance(selectedElement)) return selectedElement
|
||||||
|
|
||||||
|
return findDescendantOfTheSameRangeOfType(selectedElement, expectedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findDescendantOfTheSameRangeOfType(selectedElement: PsiElement, expectedClass: Class<out PsiElement>): PsiElement {
|
||||||
return selectedElement.collectDescendantsOfType<PsiElement> {
|
return selectedElement.collectDescendantsOfType<PsiElement> {
|
||||||
expectedType.isInstance(it)
|
expectedClass.isInstance(it)
|
||||||
}.single { it.textRange == selectedElement.textRange }
|
}.single { it.textRange == selectedElement.textRange }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user