AA: introduce static project structure provider by compiler configuration
Also add standalone mode utils to configure Application/Project environments
This commit is contained in:
committed by
Ilya Kirillov
parent
d219de0f88
commit
26e923e3ae
+5
-5
@@ -3,18 +3,18 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.impl.base.test.utils.libraries
|
||||
package org.jetbrains.kotlin.analysis.api.impl.base.util
|
||||
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
||||
import com.intellij.util.io.URLUtil.JAR_SEPARATOR
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.absolutePathString
|
||||
|
||||
object TestLibraryUtils {
|
||||
object LibraryUtils {
|
||||
fun getAllVirtualFilesFromJar(jar: Path): Collection<VirtualFile> {
|
||||
val jarFileSystem = CoreJarFileSystem()
|
||||
val root = jarFileSystem.refreshAndFindFileByPath(jar.absolutePathString() + "!/")!!
|
||||
val root = jarFileSystem.refreshAndFindFileByPath(jar.toAbsolutePath().toString() + JAR_SEPARATOR)!!
|
||||
|
||||
val files = mutableSetOf<VirtualFile>()
|
||||
VfsUtilCore.iterateChildrenRecursively(
|
||||
@@ -29,4 +29,4 @@ object TestLibraryUtils {
|
||||
)
|
||||
return files
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-55
@@ -5,19 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.impl.base.test
|
||||
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.TestReferenceResolveResultRenderer.renderResolvedTo
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
@@ -52,7 +48,7 @@ abstract class AbstractReferenceResolveTest : AbstractHLApiSingleModuleTest() {
|
||||
) {
|
||||
val symbols = ktReferences.flatMap { it.resolveToSymbols() }
|
||||
checkReferenceResultForValidity(ktReferences, module, testServices, symbols)
|
||||
renderResolvedTo(symbols)
|
||||
renderResolvedTo(symbols, renderingOptions)
|
||||
}
|
||||
|
||||
if (Directives.UNRESOLVED_REFERENCE in module.directives) {
|
||||
@@ -83,49 +79,6 @@ abstract class AbstractReferenceResolveTest : AbstractHLApiSingleModuleTest() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtAnalysisSession.renderResolvedTo(symbols: List<KtSymbol>) =
|
||||
symbols.map { renderResolveResult(it) }
|
||||
.sorted()
|
||||
.withIndex()
|
||||
.joinToString(separator = "\n") { "${it.index}: ${it.value}" }
|
||||
|
||||
|
||||
private fun KtAnalysisSession.renderResolveResult(symbol: KtSymbol): String {
|
||||
return buildString {
|
||||
symbolContainerFqName(symbol)?.let { fqName ->
|
||||
append("(in $fqName) ")
|
||||
}
|
||||
when (symbol) {
|
||||
is KtDeclarationSymbol -> append(symbol.render(renderingOptions))
|
||||
is KtPackageSymbol -> append("package ${symbol.fqName}")
|
||||
is KtReceiverParameterSymbol -> {
|
||||
append("extension receiver with type ")
|
||||
append(symbol.type.render(renderingOptions.typeRendererOptions))
|
||||
}
|
||||
else -> error("Unexpected symbol ${symbol::class}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")// KtAnalysisSession receiver
|
||||
private fun KtAnalysisSession.symbolContainerFqName(symbol: KtSymbol): String? {
|
||||
if (symbol is KtPackageSymbol || symbol is KtValueParameterSymbol) return null
|
||||
val nonLocalFqName = when (symbol) {
|
||||
is KtConstructorSymbol -> symbol.containingClassIdIfNonLocal?.asSingleFqName()
|
||||
is KtCallableSymbol -> symbol.callableIdIfNonLocal?.asSingleFqName()?.parent()
|
||||
is KtClassLikeSymbol -> symbol.classIdIfNonLocal?.asSingleFqName()?.parent()
|
||||
else -> null
|
||||
}
|
||||
when (nonLocalFqName) {
|
||||
null -> Unit
|
||||
FqName.ROOT -> return "ROOT"
|
||||
else -> return nonLocalFqName.asString()
|
||||
}
|
||||
val container = (symbol as? KtSymbolWithKind)?.getContainingSymbol() ?: return null
|
||||
val parents = generateSequence(container) { it.getContainingSymbol() }.toList().asReversed()
|
||||
return "<local>: " + parents.joinToString(separator = ".") { (it as? KtNamedSymbol)?.name?.asString() ?: "<no name>" }
|
||||
}
|
||||
|
||||
private object Directives : SimpleDirectivesContainer() {
|
||||
val UNRESOLVED_REFERENCE by directive(
|
||||
"Reference should be unresolved",
|
||||
@@ -137,9 +90,4 @@ abstract class AbstractReferenceResolveTest : AbstractHLApiSingleModuleTest() {
|
||||
sortNestedDeclarations = true
|
||||
)
|
||||
|
||||
private fun PsiReference.unwrapMultiReferences(): List<PsiReference> = when (this) {
|
||||
is KtReference -> listOf(this)
|
||||
is PsiMultiReference -> references.flatMap { it.unwrapMultiReferences() }
|
||||
else -> error("Unexpected reference $this")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.impl.base.test
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
object TestReferenceResolveResultRenderer {
|
||||
fun KtAnalysisSession.renderResolvedTo(
|
||||
symbols: List<KtSymbol>,
|
||||
renderingOptions: KtDeclarationRendererOptions = KtDeclarationRendererOptions.DEFAULT
|
||||
) =
|
||||
symbols.map { renderResolveResult(it, renderingOptions) }
|
||||
.sorted()
|
||||
.withIndex()
|
||||
.joinToString(separator = "\n") { "${it.index}: ${it.value}" }
|
||||
|
||||
private fun KtAnalysisSession.renderResolveResult(
|
||||
symbol: KtSymbol,
|
||||
renderingOptions: KtDeclarationRendererOptions
|
||||
): String {
|
||||
return buildString {
|
||||
symbolContainerFqName(symbol)?.let { fqName ->
|
||||
append("(in $fqName) ")
|
||||
}
|
||||
when (symbol) {
|
||||
is KtDeclarationSymbol -> append(symbol.render(renderingOptions))
|
||||
is KtPackageSymbol -> append("package ${symbol.fqName}")
|
||||
is KtReceiverParameterSymbol -> {
|
||||
append("extension receiver with type ")
|
||||
append(symbol.type.render(renderingOptions.typeRendererOptions))
|
||||
}
|
||||
else -> error("Unexpected symbol ${symbol::class}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")// KtAnalysisSession receiver
|
||||
private fun KtAnalysisSession.symbolContainerFqName(symbol: KtSymbol): String? {
|
||||
if (symbol is KtPackageSymbol || symbol is KtValueParameterSymbol) return null
|
||||
val nonLocalFqName = when (symbol) {
|
||||
is KtConstructorSymbol -> symbol.containingClassIdIfNonLocal?.asSingleFqName()
|
||||
is KtCallableSymbol -> symbol.callableIdIfNonLocal?.asSingleFqName()?.parent()
|
||||
is KtClassLikeSymbol -> symbol.classIdIfNonLocal?.asSingleFqName()?.parent()
|
||||
else -> null
|
||||
}
|
||||
when (nonLocalFqName) {
|
||||
null -> Unit
|
||||
FqName.ROOT -> return "ROOT"
|
||||
else -> return nonLocalFqName.asString()
|
||||
}
|
||||
val container = (symbol as? KtSymbolWithKind)?.getContainingSymbol() ?: return null
|
||||
val parents = generateSequence(container) { it.getContainingSymbol() }.toList().asReversed()
|
||||
return "<local>: " + parents.joinToString(separator = ".") { (it as? KtNamedSymbol)?.name?.asString() ?: "<no name>" }
|
||||
}
|
||||
}
|
||||
+14
-5
@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.analyse
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils.offsetToLineAndColumn
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
inline fun <T> runReadAction(crossinline runnable: () -> T): T {
|
||||
return ApplicationManager.getApplication().runReadAction(Computable { runnable() })
|
||||
@@ -51,3 +51,12 @@ fun String.indented(indent: Int): String {
|
||||
fun KtDeclaration.getNameWithPositionString(): String {
|
||||
return (presentation?.presentableText ?: name ?: this::class.simpleName) + "@" + position()
|
||||
}
|
||||
|
||||
fun findReferencesAtCaret(mainKtFile: KtFile, caretPosition: Int): List<KtReference> =
|
||||
mainKtFile.findReferenceAt(caretPosition)?.unwrapMultiReferences().orEmpty().filterIsInstance<KtReference>()
|
||||
|
||||
fun PsiReference.unwrapMultiReferences(): List<PsiReference> = when (this) {
|
||||
is KtReference -> listOf(this)
|
||||
is PsiMultiReference -> references.flatMap { it.unwrapMultiReferences() }
|
||||
else -> error("Unexpected reference $this")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user