[FIR IDE] Extract common components of the Analysis API to separate modules
This commit is contained in:
committed by
teamcityserver
parent
44a1fe668e
commit
e2c9be0932
@@ -16,6 +16,7 @@ dependencies {
|
||||
api(project(":compiler:fir:java"))
|
||||
api(project(":analysis:low-level-api-fir"))
|
||||
api(project(":analysis:analysis-api"))
|
||||
api(project(":analysis:analysis-api-impl-base"))
|
||||
api(project(":compiler:light-classes"))
|
||||
api(intellijCoreDep())
|
||||
implementation(project(":analysis:analysis-api-providers"))
|
||||
@@ -26,6 +27,7 @@ dependencies {
|
||||
testApi(projectTests(":compiler:test-infrastructure"))
|
||||
testApi(projectTests(":compiler:tests-common-new"))
|
||||
testApi(projectTests(":compiler:fir:analysis-tests:legacy-fir-tests"))
|
||||
testApi(projectTests(":analysis:analysis-api-impl-base"))
|
||||
testApi(project(":kotlin-test:kotlin-test-junit"))
|
||||
testApi(toolsJar())
|
||||
testApiJUnit5()
|
||||
|
||||
+17
-57
@@ -6,73 +6,33 @@
|
||||
package org.jetbrains.kotlin.analysis.api.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState
|
||||
import org.jetbrains.kotlin.analysis.api.*
|
||||
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.CachingKtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityTokenFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
||||
class KtFirAnalysisSessionProvider(private val project: Project) : KtAnalysisSessionProvider() {
|
||||
private val cache = KtAnalysisSessionCache<Pair<FirModuleResolveState, KClass<out ValidityToken>>>(project)
|
||||
|
||||
@InvalidWayOfUsingAnalysisSession
|
||||
override fun getAnalysisSession(contextElement: KtElement, factory: ValidityTokenFactory): KtAnalysisSession {
|
||||
val resolveState = contextElement.getResolveState()
|
||||
return cache.getAnalysisSession(resolveState to factory.identifier) {
|
||||
val validityToken = factory.create(project)
|
||||
@Suppress("DEPRECATION")
|
||||
KtFirAnalysisSession.createAnalysisSessionByResolveState(resolveState, validityToken, contextElement)
|
||||
}
|
||||
class KtFirAnalysisSessionProvider(project: Project) : CachingKtAnalysisSessionProvider<FirModuleResolveState>(project) {
|
||||
override fun getResolveState(contextElement: KtElement): FirModuleResolveState {
|
||||
return contextElement.getResolveState()
|
||||
}
|
||||
|
||||
override fun getAnalysisSessionBySymbol(contextSymbol: KtSymbol): KtAnalysisSession {
|
||||
override fun getResolveState(contextSymbol: KtSymbol): FirModuleResolveState {
|
||||
require(contextSymbol is KtFirSymbol<*>)
|
||||
val resolveState = contextSymbol.firRef.resolveState
|
||||
val token = contextSymbol.token
|
||||
return getCachedAnalysisSession(resolveState, token)
|
||||
?: error("analysis session was not found for ${contextSymbol::class}, symbol.isValid=${contextSymbol.isValid()}")
|
||||
return contextSymbol.firRef.resolveState
|
||||
}
|
||||
|
||||
private fun getCachedAnalysisSession(resolveState: FirModuleResolveState, token: ValidityToken): KtAnalysisSession? {
|
||||
return cache.getCachedAnalysisSession(resolveState to token::class)
|
||||
override fun createAnalysisSession(
|
||||
resolveState: FirModuleResolveState,
|
||||
validityToken: ValidityToken,
|
||||
contextElement: KtElement
|
||||
): KtAnalysisSession {
|
||||
@Suppress("DEPRECATION")
|
||||
return KtFirAnalysisSession.createAnalysisSessionByResolveState(resolveState, validityToken, contextElement)
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
override fun clearCaches() {
|
||||
cache.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private class KtAnalysisSessionCache<KEY : Any>(project: Project) {
|
||||
private val cache = CachedValuesManager.getManager(project).createCachedValue {
|
||||
CachedValueProvider.Result(
|
||||
ConcurrentHashMap<KEY, KtAnalysisSession>(),
|
||||
PsiModificationTracker.MODIFICATION_COUNT,
|
||||
ProjectRootModificationTracker.getInstance(project),
|
||||
project.createProjectWideOutOfBlockModificationTracker()
|
||||
)
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun clear() {
|
||||
cache.value.clear()
|
||||
}
|
||||
|
||||
inline fun getAnalysisSession(key: KEY, create: () -> KtAnalysisSession): KtAnalysisSession =
|
||||
cache.value.getOrPut(key) { create() }
|
||||
|
||||
fun getCachedAnalysisSession(key: KEY): KtAnalysisSession? =
|
||||
cache.value[key]
|
||||
}
|
||||
+6
-1
@@ -38,6 +38,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirClassInitializerSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -390,7 +392,10 @@ internal class KtSymbolByFirBuilder private constructor(
|
||||
|
||||
fun buildSubstitutor(substitutor: ConeSubstitutor): KtSubstitutor {
|
||||
if (substitutor == ConeSubstitutor.Empty) return KtSubstitutor.Empty(token)
|
||||
return KtFirSubstitutor(substitutor, this@KtSymbolByFirBuilder, token)
|
||||
return when (substitutor) {
|
||||
is ConeSubstitutorByMap -> KtFirMapBackedSubstitutor(substitutor, this@KtSymbolByFirBuilder, token)
|
||||
else -> KtFirGenericSubstitutor(substitutor, this@KtSymbolByFirBuilder, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeF
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentsOfType
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
@@ -55,10 +54,8 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.parentOrNull
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||
|
||||
+1
-1
@@ -10,12 +10,12 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtSymbolContainingDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithKind
|
||||
|
||||
+1
-1
@@ -13,11 +13,11 @@ import org.jetbrains.kotlin.fir.resolve.calls.ExpressionReceiverValue
|
||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirSafe
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentsOfType
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtVisibilityChecker
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirFileSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFileSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.idea.references
|
||||
|
||||
import com.intellij.psi.ContributedReferenceHost
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiReferenceService
|
||||
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.PsiModificationTracker
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.idea.references.*
|
||||
import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
class HLApiReferenceProviderService : KotlinReferenceProvidersService() {
|
||||
private val originalProvidersBinding: MultiMap<Class<out PsiElement>, KotlinPsiReferenceProvider>
|
||||
private val providersBindingCache: Map<Class<out PsiElement>, List<KotlinPsiReferenceProvider>>
|
||||
|
||||
init {
|
||||
val registrar = KotlinPsiReferenceRegistrar()
|
||||
KotlinReferenceProviderContributor.getInstance().registerReferenceProviders(registrar)
|
||||
originalProvidersBinding = registrar.providers
|
||||
|
||||
providersBindingCache = ConcurrentFactoryMap.createMap<Class<out PsiElement>, List<KotlinPsiReferenceProvider>> { klass ->
|
||||
val result = SmartList<KotlinPsiReferenceProvider>()
|
||||
for (bindingClass in originalProvidersBinding.keySet()) {
|
||||
if (bindingClass.isAssignableFrom(klass)) {
|
||||
result.addAll(originalProvidersBinding.get(bindingClass))
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
private fun doGetKotlinReferencesFromProviders(context: PsiElement): Array<PsiReference> {
|
||||
val providers: List<KotlinPsiReferenceProvider>? = providersBindingCache[context.javaClass]
|
||||
if (providers.isNullOrEmpty()) return PsiReference.EMPTY_ARRAY
|
||||
|
||||
val result = SmartList<PsiReference>()
|
||||
for (provider in providers) {
|
||||
result.addAll(provider.getReferencesByElement(context))
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
return PsiReference.EMPTY_ARRAY
|
||||
}
|
||||
|
||||
return result.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getReferences(psiElement: PsiElement): Array<PsiReference> {
|
||||
if (psiElement is ContributedReferenceHost) {
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(psiElement, PsiReferenceService.Hints.NO_HINTS)
|
||||
}
|
||||
|
||||
return CachedValuesManager.getCachedValue(psiElement) {
|
||||
CachedValueProvider.Result.create(
|
||||
doGetKotlinReferencesFromProviders(psiElement),
|
||||
PsiModificationTracker.MODIFICATION_COUNT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ import com.intellij.psi.impl.source.resolve.ResolveCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
|
||||
import org.jetbrains.kotlin.analysis.api.analyse
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.runInPossiblyEdtThread
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.util.runInPossiblyEdtThread
|
||||
|
||||
object KtFirReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> {
|
||||
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
|
||||
|
||||
+30
-2
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.components.RendererModifier
|
||||
import org.jetbrains.kotlin.analysis.api.fir.types.PublicTypeApproximator
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.PsiSourceNavigator.getRawName
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.renderer.render
|
||||
@@ -405,7 +406,7 @@ internal class FirIdeRenderer private constructor(
|
||||
visitEnumEntry(enumEntry, data)
|
||||
data.append(",")
|
||||
}
|
||||
partitioned.second.forEach {
|
||||
sortDeclarations(partitioned.second).forEach {
|
||||
if (!it.skipDeclarationForEnumClass()) {
|
||||
it.accept(this, data)
|
||||
}
|
||||
@@ -414,7 +415,7 @@ internal class FirIdeRenderer private constructor(
|
||||
|
||||
fun renderDeclarationForNotEnumClass() {
|
||||
check(!regularClass.isEnumClass)
|
||||
regularClass.declarations.forEach {
|
||||
sortDeclarations(regularClass.declarations).forEach {
|
||||
if (!it.isDefaultPrimaryConstructor()) {
|
||||
it.accept(this, data)
|
||||
}
|
||||
@@ -679,6 +680,33 @@ internal class FirIdeRenderer private constructor(
|
||||
supertypes.joinTo(this, ", ") { renderType(it) }
|
||||
}
|
||||
|
||||
fun sortDeclarations(declarations: List<FirDeclaration>): List<FirDeclaration> {
|
||||
if (!options.sortNestedDeclarations) return declarations
|
||||
|
||||
fun getDeclarationKind(declaration: FirDeclaration): Int = when (declaration) {
|
||||
is FirEnumEntry -> 0
|
||||
is FirConstructor -> if (declaration.isPrimary) 1 else 2
|
||||
is FirProperty -> 3
|
||||
is FirFunction -> 4
|
||||
else -> 5
|
||||
}
|
||||
|
||||
return declarations.sortedWith(Comparator { left, right ->
|
||||
val kindResult = getDeclarationKind(left) - getDeclarationKind(right)
|
||||
if (kindResult != 0) {
|
||||
return@Comparator kindResult
|
||||
}
|
||||
|
||||
val nameResult = (left.getRawName() ?: "").compareTo(right.getRawName() ?: "")
|
||||
if (nameResult != 0) {
|
||||
return@Comparator nameResult
|
||||
}
|
||||
|
||||
val leftString = StringBuilder().also { builder -> left.accept(this, builder) }.toString()
|
||||
val rightString = StringBuilder().also { builder -> right.accept(this, builder) }.toString()
|
||||
return@Comparator leftString.compareTo(rightString)
|
||||
})
|
||||
}
|
||||
|
||||
private fun getClassifierKindPrefix(classifier: FirDeclaration): String = when (classifier) {
|
||||
is FirTypeAlias -> "typealias"
|
||||
|
||||
+31
-4
@@ -7,22 +7,49 @@ package org.jetbrains.kotlin.analysis.api.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.weakRef
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.KtMapBackedSubstitutor
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
|
||||
internal class KtFirSubstitutor(
|
||||
private val _substitutor: ConeSubstitutor,
|
||||
internal abstract class AbstractKtFirSubstitutor<T : ConeSubstitutor>(
|
||||
private val _substitutor: T,
|
||||
builder: KtSymbolByFirBuilder,
|
||||
override val token: ValidityToken,
|
||||
) : KtSubstitutor {
|
||||
private val builderRef by weakRef(builder)
|
||||
val substitutor: ConeSubstitutor get() = withValidityAssertion { _substitutor }
|
||||
protected val builderRef by weakRef(builder)
|
||||
val substitutor: T get() = withValidityAssertion { _substitutor }
|
||||
|
||||
override fun substituteOrNull(type: KtType): KtType? = withValidityAssertion {
|
||||
require(type is KtFirType)
|
||||
substitutor.substituteOrNull(type.coneType)?.type?.let { builderRef.typeBuilder.buildKtType(it) }
|
||||
}
|
||||
}
|
||||
|
||||
internal class KtFirGenericSubstitutor(
|
||||
_substitutor: ConeSubstitutor,
|
||||
builder: KtSymbolByFirBuilder,
|
||||
token: ValidityToken
|
||||
) : AbstractKtFirSubstitutor<ConeSubstitutor>(_substitutor, builder, token)
|
||||
|
||||
internal class KtFirMapBackedSubstitutor(
|
||||
_substitutor: ConeSubstitutorByMap,
|
||||
builder: KtSymbolByFirBuilder,
|
||||
token: ValidityToken
|
||||
) : AbstractKtFirSubstitutor<ConeSubstitutorByMap>(_substitutor, builder, token), KtMapBackedSubstitutor {
|
||||
override fun getAsMap(): Map<KtTypeParameterSymbol, KtType> {
|
||||
val result = mutableMapOf<KtTypeParameterSymbol, KtType>()
|
||||
for ((typeParameter, type) in substitutor.substitution) {
|
||||
val typeParameterSymbol = builderRef.classifierBuilder.buildTypeParameterSymbolByLookupTag(typeParameter.toLookupTag())
|
||||
if (typeParameterSymbol != null) {
|
||||
result[typeParameterSymbol] = builderRef.typeBuilder.buildKtType(type)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.utils
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.HackToForceAllowRunningAnalyzeOnEDT
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.hackyAllowRunningOnEdt
|
||||
|
||||
@HackToForceAllowRunningAnalyzeOnEDT
|
||||
internal inline fun <R> runInPossiblyEdtThread(action: () -> R): R = when {
|
||||
!ApplicationManager.getApplication().isDispatchThread -> action()
|
||||
else -> hackyAllowRunningOnEdt(action)
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.AbstractReferenceResolveTest
|
||||
|
||||
abstract class AbstractFirReferenceResolveTest : AbstractReferenceResolveTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
-131
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir
|
||||
|
||||
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.fir.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.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
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
|
||||
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractReferenceResolveTest : AbstractHLApiSingleModuleTest() {
|
||||
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||
super.configureTest(builder)
|
||||
with(builder) {
|
||||
defaultDirectives {
|
||||
+JvmEnvironmentConfigurationDirectives.WITH_STDLIB
|
||||
}
|
||||
useDirectives(Directives)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||
val mainKtFile = ktFiles.singleOrNull() ?: ktFiles.first { it.name == "main.kt" }
|
||||
val caretPosition = testServices.expressionMarkerProvider.getCaretPosition(mainKtFile)
|
||||
val ktReferences = findReferencesAtCaret(mainKtFile, caretPosition)
|
||||
if (ktReferences.isEmpty()) {
|
||||
testServices.assertions.fail { "No references at caret found" }
|
||||
}
|
||||
|
||||
val resolvedTo =
|
||||
analyseForTest(PsiTreeUtil.findElementOfClassAtOffset(mainKtFile, caretPosition, KtDeclaration::class.java, false) ?: mainKtFile) {
|
||||
val symbols = ktReferences.flatMap { it.resolveToSymbols() }
|
||||
checkReferenceResultForValidity(module, testServices, symbols)
|
||||
renderResolvedTo(symbols)
|
||||
}
|
||||
|
||||
if (Directives.UNRESOLVED_REFERENCE in module.directives) {
|
||||
return
|
||||
}
|
||||
|
||||
val actual = "Resolved to:\n$resolvedTo"
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun findReferencesAtCaret(mainKtFile: KtFile, caretPosition: Int): List<KtReference> =
|
||||
mainKtFile.findReferenceAt(caretPosition)?.unwrapMultiReferences().orEmpty().filterIsInstance<KtReference>()
|
||||
|
||||
private fun KtAnalysisSession.checkReferenceResultForValidity(
|
||||
module: TestModule,
|
||||
testServices: TestServices,
|
||||
resolvedTo: List<KtSymbol>
|
||||
) {
|
||||
if (Directives.UNRESOLVED_REFERENCE in module.directives) {
|
||||
testServices.assertions.assertTrue(resolvedTo.isEmpty()) {
|
||||
"Reference should be unresolved, but was resolved to ${renderResolvedTo(resolvedTo)}"
|
||||
}
|
||||
} else {
|
||||
testServices.assertions.assertTrue(resolvedTo.isNotEmpty()) { "Unresolved reference" }
|
||||
}
|
||||
}
|
||||
|
||||
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) ")
|
||||
}
|
||||
append(symbol.render(renderingOptions))
|
||||
}
|
||||
}
|
||||
|
||||
@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() }
|
||||
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",
|
||||
)
|
||||
}
|
||||
|
||||
private val renderingOptions = KtDeclarationRendererOptions.DEFAULT.copy(
|
||||
modifiers = RendererModifier.DEFAULT - RendererModifier.ANNOTATIONS
|
||||
)
|
||||
|
||||
private fun PsiReference.unwrapMultiReferences(): List<PsiReference> = when (this) {
|
||||
is KtReference -> listOf(this)
|
||||
is PsiMultiReference -> references.flatMap { it.unwrapMultiReferences() }
|
||||
else -> error("Unexpected reference $this")
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir
|
||||
|
||||
import com.intellij.mock.MockApplication
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.Disposable
|
||||
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.idea.references.KotlinFirReferenceContributor
|
||||
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
|
||||
import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
|
||||
object FirFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorService {
|
||||
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
|
||||
with(FirLowLevelFrontendApiTestConfiguratorService) { configureTest(disposable) }
|
||||
}
|
||||
|
||||
override fun processTestFiles(files: List<KtFile>): List<KtFile> {
|
||||
return FirLowLevelFrontendApiTestConfiguratorService.processTestFiles(files)
|
||||
}
|
||||
|
||||
override fun getOriginalFile(file: KtFile): KtFile {
|
||||
return FirLowLevelFrontendApiTestConfiguratorService.getOriginalFile(file)
|
||||
}
|
||||
|
||||
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
||||
override fun registerProjectServices(project: MockProject) {
|
||||
FirLowLevelFrontendApiTestConfiguratorService.registerProjectServices(project)
|
||||
project.registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider::class.java)
|
||||
}
|
||||
|
||||
override fun registerApplicationServices(application: MockApplication) {
|
||||
FirLowLevelFrontendApiTestConfiguratorService.registerApplicationServices(application)
|
||||
if (application.getServiceIfCreated(KotlinReferenceProvidersService::class.java) == null) {
|
||||
application.registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
||||
application.registerService(KotlinReferenceProviderContributor::class.java, KotlinFirReferenceContributor::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/referenceResolve")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest {
|
||||
public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolveTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInReferenceResolve() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
object FirTestWithOutOfBlockModification {
|
||||
fun doOutOfBlockModification(ktFile: KtFile) {
|
||||
ServiceManager.getService(ktFile.project, KotlinModificationTrackerFactory::class.java)
|
||||
.incrementModificationsCount()
|
||||
}
|
||||
}
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
|
||||
object SymbolByFqName {
|
||||
fun getSymbolDataFromFile(filePath: Path): SymbolData {
|
||||
val testFileText = FileUtil.loadFile(filePath.toFile())
|
||||
val identifier = testFileText.lineSequence().first { line ->
|
||||
SymbolData.identifiers.any { identifier ->
|
||||
line.startsWith(identifier) || line.startsWith("// $identifier")
|
||||
}
|
||||
}
|
||||
return SymbolData.create(identifier.removePrefix("// "))
|
||||
}
|
||||
|
||||
fun textWithRenderedSymbolData(filePath: String, rendered: String): String = buildString {
|
||||
val testFileText = FileUtil.loadFile(File(filePath))
|
||||
val fileTextWithoutSymbolsData = testFileText.substringBeforeLast(SYMBOLS_TAG).trimEnd()
|
||||
appendLine(fileTextWithoutSymbolsData)
|
||||
appendLine()
|
||||
appendLine(SYMBOLS_TAG)
|
||||
append(rendered)
|
||||
}
|
||||
|
||||
|
||||
private const val SYMBOLS_TAG = "// SYMBOLS:"
|
||||
}
|
||||
|
||||
sealed class SymbolData {
|
||||
abstract fun KtAnalysisSession.toSymbols(): List<KtSymbol>
|
||||
|
||||
data class ClassData(val classId: ClassId) : SymbolData() {
|
||||
override fun KtAnalysisSession.toSymbols(): List<KtSymbol> {
|
||||
val symbol = classId.getCorrespondingToplevelClassOrObjectSymbol() ?: error("Class $classId is not found")
|
||||
return listOf(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
data class CallableData(val callableId: CallableId) : SymbolData() {
|
||||
override fun KtAnalysisSession.toSymbols(): List<KtSymbol> {
|
||||
val classId = callableId.classId
|
||||
val symbols = if (classId == null) {
|
||||
callableId.packageName.getContainingCallableSymbolsWithName(callableId.callableName).toList()
|
||||
} else {
|
||||
val classSymbol =
|
||||
classId.getCorrespondingToplevelClassOrObjectSymbol()
|
||||
?: error("Class $classId is not found")
|
||||
classSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||
.filter { (it as? KtNamedSymbol)?.name == callableId.callableName }
|
||||
.toList()
|
||||
}
|
||||
if (symbols.isEmpty()) {
|
||||
error("No callable with fqName $callableId found")
|
||||
}
|
||||
return symbols
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val identifiers = arrayOf("callable:", "class:")
|
||||
|
||||
fun create(data: String): SymbolData = when {
|
||||
data.startsWith("class:") -> ClassData(ClassId.fromString(data.removePrefix("class:").trim()))
|
||||
data.startsWith("callable:") -> {
|
||||
val fullName = data.removePrefix("callable:").trim()
|
||||
val name = if ('.' in fullName) fullName.substringAfterLast(".") else fullName.substringAfterLast('/')
|
||||
val (packageName, className) = run {
|
||||
val packageNameWithClassName = fullName.dropLast(name.length + 1)
|
||||
when {
|
||||
'.' in fullName ->
|
||||
packageNameWithClassName.substringBeforeLast('/') to packageNameWithClassName.substringAfterLast('/')
|
||||
else -> packageNameWithClassName to null
|
||||
}
|
||||
}
|
||||
CallableData(CallableId(FqName(packageName.replace('/', '.')), className?.let { FqName(it) }, Name.identifier(name)))
|
||||
}
|
||||
else -> error("Invalid symbol")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractCompileTimeConstantEvaluatorTest : AbstractHLApiSingleFileTest() {
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val element = testServices.expressionMarkerProvider.getSelectedElement(ktFile)
|
||||
val expression = when (element) {
|
||||
is KtExpression -> element
|
||||
is KtValueArgument -> element.getArgumentExpression()
|
||||
else -> null
|
||||
} ?: testServices.assertions.fail { "Unsupported expression: $element" }
|
||||
val constantValue = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(expression) { expression.evaluate() }
|
||||
}
|
||||
val actual = buildString {
|
||||
appendLine("expression: ${expression.text}")
|
||||
appendLine("constant_value: ${analyseForTest(expression) { constantValue?.stringRepresentation() }}")
|
||||
appendLine("constant: ${(constantValue as? KtLiteralConstantValue<*>)?.toConst()}")
|
||||
}
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun KtConstantValue.stringRepresentation(): String {
|
||||
return when (this) {
|
||||
is KtArrayConstantValue -> buildString {
|
||||
appendLine("KtArrayConstantValue [")
|
||||
appendLine(INDENT, values.joinToString(separator = "\n") { it.stringRepresentation() })
|
||||
append("]")
|
||||
}
|
||||
is KtAnnotationConstantValue -> buildString {
|
||||
append("KtAnnotationConstantValue(")
|
||||
append(classId?.relativeClassName)
|
||||
append(", ")
|
||||
arguments.joinTo(this, separator = ", ", prefix = "(", postfix = ")") {
|
||||
"${it.name} = ${it.expression.stringRepresentation()}"
|
||||
}
|
||||
append(")")
|
||||
}
|
||||
is KtEnumEntryConstantValue -> buildString {
|
||||
append("KtEnumEntryConstantValue(")
|
||||
append("$callableId")
|
||||
append(")")
|
||||
}
|
||||
is KtLiteralConstantValue<*> -> buildString {
|
||||
append("KtLiteralConstantValue(")
|
||||
append("constantValueKind=${constantValueKind}")
|
||||
append(", ")
|
||||
append("value=${value})")
|
||||
}
|
||||
is KtUnsupportedConstantValue -> "KtUnsupportedConstantValue"
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendLine(indent: Int, value: String) {
|
||||
appendLine(value.prependIndent(" ".repeat(indent)))
|
||||
}
|
||||
}
|
||||
|
||||
private const val INDENT = 2
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractExpectedExpressionTypeTest : AbstractHLApiSingleFileTest() {
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val expressionAtCaret = testServices.expressionMarkerProvider.getElementOfTypAtCaret(ktFile) as KtExpression
|
||||
|
||||
val actualExpectedTypeText: String? = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(expressionAtCaret) {
|
||||
expressionAtCaret.getExpectedType()?.asStringForDebugging()
|
||||
}
|
||||
}
|
||||
|
||||
val actual = buildString {
|
||||
appendLine("expression: ${expressionAtCaret.text}")
|
||||
appendLine("expected type: $actualExpectedTypeText")
|
||||
}
|
||||
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractCompileTimeConstantEvaluatorTest
|
||||
|
||||
abstract class AbstractFirCompileTimeConstantEvaluatorTest : AbstractCompileTimeConstantEvaluatorTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractExpectedExpressionTypeTest
|
||||
|
||||
abstract class AbstractFirExpectedExpressionTypeTest : AbstractExpectedExpressionTypeTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+8
-3
@@ -7,15 +7,20 @@ package org.jetbrains.kotlin.analysis.api.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.analyse
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractGetSuperTypesTest : AbstractHLApiSingleFileTest() {
|
||||
abstract class AbstractFirGetSuperTypesTest : AbstractHLApiSingleFileTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile)
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractHLExpressionTypeTest
|
||||
|
||||
abstract class AbstractFirHLExpressionTypeTest : AbstractHLExpressionTypeTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractHasCommonSubtypeTest
|
||||
|
||||
abstract class AbstractFirHasCommonSubtypeTest : AbstractHasCommonSubtypeTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractOverriddenDeclarationProviderTest
|
||||
|
||||
abstract class AbstractFirOverriddenDeclarationProviderTest : AbstractOverriddenDeclarationProviderTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.components.AbstractRendererTest
|
||||
|
||||
abstract class AbstractFirRendererTest : AbstractRendererTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.fir.AbstractResolveCallTest
|
||||
|
||||
abstract class AbstractFirResolveCallTest : AbstractResolveCallTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractHLExpressionTypeTest : AbstractHLApiSingleFileTest() {
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile) as KtExpression
|
||||
val type = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(expression) { expression.getKtType()?.render() }
|
||||
}
|
||||
val actual = buildString {
|
||||
appendLine("expression: ${expression.text}")
|
||||
appendLine("type: $type")
|
||||
}
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -5,13 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractHLImportOptimizerTest : AbstractHLApiSingleModuleTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
|
||||
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||
val mainKtFile = ktFiles.singleOrNull() ?: ktFiles.first { it.name == "main.kt" }
|
||||
val unusedImports = analyseForTest(mainKtFile) { analyseImports(mainKtFile).unusedImports }
|
||||
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.AdditionalSourceProvider
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractHasCommonSubtypeTest : AbstractHLApiSingleFileTest() {
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val errors = mutableListOf<String>()
|
||||
val originalText = ktFile.text
|
||||
val actualTextBuilder = StringBuilder()
|
||||
analyseForTest(ktFile) {
|
||||
val visitor = object : KtTreeVisitorVoid() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (element.firstChild == null) {
|
||||
actualTextBuilder.append(element.text)
|
||||
}
|
||||
super.visitElement(element)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression) {
|
||||
val haveCommonSubtype = when (expression.calleeExpression?.text) {
|
||||
"typesHaveCommonSubtype" -> true
|
||||
"typesHaveNoCommonSubtype" -> false
|
||||
else -> {
|
||||
super.visitCallExpression(expression)
|
||||
return
|
||||
}
|
||||
}
|
||||
val valueArguments = expression.valueArguments
|
||||
require(valueArguments.size == 2) {
|
||||
"Illegal call of ${expression.name} at ${expression.positionString}"
|
||||
}
|
||||
|
||||
val a = valueArguments[0]
|
||||
val aType = a.getArgumentExpression()?.getKtType()
|
||||
if (aType == null) {
|
||||
errors.add("'${a.text}' has no type at ${a.positionString}")
|
||||
super.visitCallExpression(expression)
|
||||
return
|
||||
}
|
||||
val b = valueArguments[1]
|
||||
val bType = b.getArgumentExpression()?.getKtType()
|
||||
if (bType == null) {
|
||||
errors.add("'${b.text}' has no type at ${b.positionString}")
|
||||
super.visitCallExpression(expression)
|
||||
return
|
||||
}
|
||||
if (haveCommonSubtype != aType.hasCommonSubTypeWith(bType)) {
|
||||
if (haveCommonSubtype) {
|
||||
actualTextBuilder.append("typesHaveNoCommonSubtype")
|
||||
} else {
|
||||
actualTextBuilder.append("typesHaveCommonSubtype")
|
||||
}
|
||||
actualTextBuilder.append(expression.valueArgumentList!!.text)
|
||||
} else {
|
||||
super.visitCallExpression(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
visitor.visitFile(ktFile)
|
||||
}
|
||||
if (errors.isNotEmpty()) {
|
||||
testServices.assertions.fail { errors.joinToString("\n") }
|
||||
}
|
||||
val actualText = actualTextBuilder.toString()
|
||||
if (actualText != originalText) {
|
||||
testServices.assertions.assertEqualsToFile(testDataPath, actualText)
|
||||
}
|
||||
}
|
||||
|
||||
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||
super.configureTest(builder)
|
||||
builder.useAdditionalSourceProviders(::TestHelperProvider)
|
||||
builder.defaultDirectives {
|
||||
+JvmEnvironmentConfigurationDirectives.WITH_STDLIB
|
||||
}
|
||||
}
|
||||
|
||||
private class TestHelperProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
|
||||
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
|
||||
return listOf(File("analysis/analysis-api/testData/helpers/hasCommonSubtype/helpers.kt").toTestFile())
|
||||
}
|
||||
}
|
||||
|
||||
private val PsiElement.positionString: String
|
||||
get() {
|
||||
val illegalCallPos = StringUtil.offsetToLineColumn(containingFile.text, textRange.startOffset)
|
||||
return "${containingFile.virtualFile.path}:${illegalCallPos.line + 1}:${illegalCallPos.column + 1}"
|
||||
}
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentsOfType
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSyntheticJavaPropertySymbol
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractOverriddenDeclarationProviderTest : AbstractHLApiSingleModuleTest() {
|
||||
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||
val declaration = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtDeclaration>(ktFiles.first())
|
||||
|
||||
val actual = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(declaration) {
|
||||
val symbol = declaration.getSymbol() as KtCallableSymbol
|
||||
val allOverriddenSymbols = symbol.getAllOverriddenSymbols().map { renderSignature(it) }
|
||||
val directlyOverriddenSymbols = symbol.getDirectlyOverriddenSymbols().map { renderSignature(it) }
|
||||
buildString {
|
||||
appendLine("ALL:")
|
||||
allOverriddenSymbols.forEach { appendLine(" $it") }
|
||||
appendLine("DIRECT:")
|
||||
directlyOverriddenSymbols.forEach { appendLine(" $it") }
|
||||
}
|
||||
}
|
||||
}
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun KtAnalysisSession.renderSignature(symbol: KtCallableSymbol): String = buildString {
|
||||
append(getPath(symbol))
|
||||
if (symbol is KtFunctionSymbol) {
|
||||
append("(")
|
||||
symbol.valueParameters.forEachIndexed { index, parameter ->
|
||||
append(parameter.name.identifier)
|
||||
append(": ")
|
||||
append(parameter.annotatedType.type.render(KtTypeRendererOptions.SHORT_NAMES))
|
||||
if (index != symbol.valueParameters.lastIndex) {
|
||||
append(", ")
|
||||
}
|
||||
}
|
||||
append(")")
|
||||
}
|
||||
append(": ")
|
||||
append(symbol.annotatedType.type.render(KtTypeRendererOptions.SHORT_NAMES))
|
||||
}
|
||||
|
||||
private fun getPath(symbol: KtCallableSymbol): String = when (symbol) {
|
||||
is KtSyntheticJavaPropertySymbol -> symbol.callableIdIfNonLocal?.toString()!!
|
||||
else -> {
|
||||
val ktDeclaration = symbol.psi as KtDeclaration
|
||||
ktDeclaration
|
||||
.parentsOfType<KtDeclaration>(withSelf = true)
|
||||
.map { it.name ?: "<no name>" }
|
||||
.toList()
|
||||
.asReversed()
|
||||
.joinToString(separator = ".")
|
||||
}
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtDeclarationRendererOptions
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtTypeRendererOptions
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractRendererTest : AbstractHLApiSingleFileTest() {
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val options = KtDeclarationRendererOptions.DEFAULT.copy(
|
||||
approximateTypes = true,
|
||||
renderContainingDeclarations = true,
|
||||
typeRendererOptions = KtTypeRendererOptions.SHORT_NAMES
|
||||
)
|
||||
|
||||
val actual = executeOnPooledThreadInReadAction {
|
||||
buildString {
|
||||
ktFile.declarations.forEach {
|
||||
analyseForTest(it) {
|
||||
append(it.getSymbol().render(options))
|
||||
appendLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".rendered"), actual)
|
||||
}
|
||||
}
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.components
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.calls.KtCall
|
||||
import org.jetbrains.kotlin.analysis.api.calls.KtDelegatedConstructorCallKind
|
||||
import org.jetbrains.kotlin.analysis.api.calls.KtErrorCallTarget
|
||||
import org.jetbrains.kotlin.analysis.api.calls.KtSuccessCallTarget
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleModuleTest
|
||||
import org.jetbrains.kotlin.analysis.api.fir.types.KtFirSubstitutor
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossibleMemberSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
import kotlin.reflect.jvm.javaGetter
|
||||
|
||||
abstract class AbstractResolveCallTest : AbstractHLApiSingleModuleTest() {
|
||||
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||
val ktFile = ktFiles.first()
|
||||
val expression = testServices.expressionMarkerProvider.getSelectedElement(ktFile)
|
||||
|
||||
val actual = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(expression) {
|
||||
resolveCall(expression)?.stringRepresentation()
|
||||
}
|
||||
} ?: "null"
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun KtAnalysisSession.resolveCall(element: PsiElement): KtCall? = when (element) {
|
||||
is KtCallElement -> element.resolveCall()
|
||||
is KtBinaryExpression -> element.resolveCall()
|
||||
is KtUnaryExpression -> element.resolveCall()
|
||||
is KtArrayAccessExpression -> element.resolveCall()
|
||||
is KtSimpleNameExpression -> element.resolveAccessorCall()
|
||||
is KtValueArgument -> resolveCall(element.getArgumentExpression()!!)
|
||||
is KtDeclarationModifierList -> {
|
||||
val annotationEntry = element.annotationEntries.singleOrNull()
|
||||
?: error("Only single annotation entry is supported for now")
|
||||
annotationEntry.resolveCall()
|
||||
}
|
||||
is KtFileAnnotationList -> {
|
||||
val annotationEntry = element.annotationEntries.singleOrNull()
|
||||
?: error("Only single annotation entry is supported for now")
|
||||
annotationEntry.resolveCall()
|
||||
}
|
||||
else -> error("Selected element type (${element::class.simpleName}) is not supported for resolveCall()")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun KtCall.stringRepresentation(): String {
|
||||
fun KtType.render() = substitutor.substituteOrSelf(this).asStringForDebugging().replace('/', '.')
|
||||
fun Any.stringValue(): String = when (this) {
|
||||
is KtFunctionLikeSymbol -> buildString {
|
||||
append(
|
||||
when (this@stringValue) {
|
||||
is KtFunctionSymbol -> callableIdIfNonLocal ?: name
|
||||
is KtSamConstructorSymbol -> callableIdIfNonLocal ?: name
|
||||
is KtConstructorSymbol -> "<constructor>"
|
||||
is KtPropertyGetterSymbol -> callableIdIfNonLocal ?: "<getter>"
|
||||
is KtPropertySetterSymbol -> callableIdIfNonLocal ?: "<setter>"
|
||||
else -> error("unexpected symbol kind in KtCall: ${this@stringValue::class.java}")
|
||||
}
|
||||
)
|
||||
append("(")
|
||||
(this@stringValue as? KtFunctionSymbol)?.receiverType?.let { receiver ->
|
||||
append("<extension receiver>: ${receiver.type.render()}")
|
||||
if (valueParameters.isNotEmpty()) append(", ")
|
||||
}
|
||||
(this@stringValue as? KtPossibleMemberSymbol)?.dispatchType?.let { dispatchReceiverType ->
|
||||
append("<dispatch receiver>: ${dispatchReceiverType.render()}")
|
||||
if (valueParameters.isNotEmpty()) append(", ")
|
||||
}
|
||||
valueParameters.joinTo(this) { it.stringValue() }
|
||||
append(")")
|
||||
append(": ${annotatedType.type.render()}")
|
||||
}
|
||||
is KtValueParameterSymbol -> "${if (isVararg) "vararg " else ""}$name: ${annotatedType.type.render()}"
|
||||
is KtVariableSymbol -> "${if (isVal) "val" else "var"} $name: ${annotatedType.type.render()}"
|
||||
is KtSuccessCallTarget -> symbol.stringValue()
|
||||
is KtErrorCallTarget -> "ERR<${this.diagnostic.defaultMessage}, [${candidates.joinToString { it.stringValue() }}]>"
|
||||
is Boolean -> toString()
|
||||
is Map<*, *> -> entries.joinToString(prefix = "{ ", postfix = " }") { (k, v) -> "${k?.stringValue()} -> (${v?.stringValue()})" }
|
||||
is KtExpression -> this.text
|
||||
is KtDelegatedConstructorCallKind -> toString()
|
||||
is KtSubstitutor.Empty -> "<empty substitutor>"
|
||||
is KtFirSubstitutor -> {
|
||||
when (val substitutor = substitutor) {
|
||||
is ConeSubstitutorByMap -> "<map substitutor: ${substitutor.substitution}>"
|
||||
else -> "<complex substitutor>"
|
||||
}
|
||||
}
|
||||
else -> error("unexpected parameter type ${this::class}")
|
||||
}
|
||||
|
||||
val callInfoClass = this::class
|
||||
return buildString {
|
||||
append(callInfoClass.simpleName!!)
|
||||
append(":\n")
|
||||
val propertyByName =
|
||||
callInfoClass.memberProperties.associateBy(KProperty1<*, *>::name)
|
||||
callInfoClass.primaryConstructor!!.parameters
|
||||
.filter { it.name != "token" }
|
||||
.joinTo(this, separator = "\n") { parameter ->
|
||||
val name = parameter.name!!.removePrefix("_")
|
||||
val value = propertyByName[name]!!.javaGetter!!(this@stringRepresentation)?.stringValue()
|
||||
"$name = $value"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/compileTimeConstantEvaluator")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class CompileTimeConstantEvaluatorTestGenerated extends AbstractCompileTimeConstantEvaluatorTest {
|
||||
public class FirCompileTimeConstantEvaluatorTestGenerated extends AbstractFirCompileTimeConstantEvaluatorTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInCompileTimeConstantEvaluator() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/compileTimeConstantEvaluator"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/expectedExpressionType")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ExpectedExpressionTypeTestGenerated extends AbstractExpectedExpressionTypeTest {
|
||||
public class FirExpectedExpressionTypeTestGenerated extends AbstractFirExpectedExpressionTypeTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInExpectedExpressionType() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expectedExpressionType"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/getSuperTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class GetSuperTypesTestGenerated extends AbstractGetSuperTypesTest {
|
||||
public class FirGetSuperTypesTestGenerated extends AbstractFirGetSuperTypesTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInGetSuperTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/getSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/expressionType")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class HLExpressionTypeTestGenerated extends AbstractHLExpressionTypeTest {
|
||||
public class FirHLExpressionTypeTestGenerated extends AbstractFirHLExpressionTypeTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInExpressionType() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/expressionType"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/hasCommonSubtype")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class HasCommonSubtypeTestGenerated extends AbstractHasCommonSubtypeTest {
|
||||
public class FirHasCommonSubtypeTestGenerated extends AbstractFirHasCommonSubtypeTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInHasCommonSubtype() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/hasCommonSubtype"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/overridenDeclarations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class OverriddenDeclarationProviderTestGenerated extends AbstractOverriddenDeclarationProviderTest {
|
||||
public class FirOverriddenDeclarationProviderTestGenerated extends AbstractFirOverriddenDeclarationProviderTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInOverridenDeclarations() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/overridenDeclarations"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/components/declarationRenderer")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class RendererTestGenerated extends AbstractRendererTest {
|
||||
public class FirRendererTestGenerated extends AbstractFirRendererTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInDeclarationRenderer() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/declarationRenderer"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/analysisSession/resolveCall")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class ResolveCallTestGenerated extends AbstractResolveCallTest {
|
||||
public class FirResolveCallTestGenerated extends AbstractFirResolveCallTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInResolveCall() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/analysisSession/resolveCall"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractFileScopeTest : AbstractHLApiSingleFileTest() {
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val actual = executeOnPooledThreadInReadAction {
|
||||
analyseForTest(ktFile) {
|
||||
val symbol = ktFile.getFileSymbol()
|
||||
val scope = symbol.getFileScope()
|
||||
with(DebugSymbolRenderer) {
|
||||
val renderedSymbol = renderExtra(symbol)
|
||||
val callableNames = scope.getPossibleCallableNames()
|
||||
val renderedCallables = scope.getCallableSymbols().map { renderExtra(it) }
|
||||
val classifierNames = scope.getPossibleClassifierNames()
|
||||
val renderedClassifiers = scope.getClassifierSymbols().map { renderExtra(it) }
|
||||
|
||||
"FILE SYMBOL:\n" + renderedSymbol +
|
||||
"\nCALLABLE NAMES:\n" + callableNames.joinToString(prefix = "[", postfix = "]\n", separator = ", ") +
|
||||
"\nCALLABLE SYMBOLS:\n" + renderedCallables.joinToString(separator = "\n") +
|
||||
"\nCLASSIFIER NAMES:\n" + classifierNames.joinToString(prefix = "[", postfix = "]\n", separator = ", ") +
|
||||
"\nCLASSIFIER SYMBOLS:\n" + renderedClassifiers.joinToString(separator = "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractFileScopeTest
|
||||
|
||||
abstract class AbstractFirFileScopeTest : AbstractFileScopeTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirTestWithOutOfBlockModification
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.scopes.AbstractMemberScopeByFqNameTest
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class AbstractFirMemberScopeByFqNameTest : AbstractMemberScopeByFqNameTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
|
||||
override fun doOutOfBlockModification(ktFile: KtFile) {
|
||||
FirTestWithOutOfBlockModification.doOutOfBlockModification(ktFile)
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.SymbolByFqName
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.AbstractSymbolByFqNameTest
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractMemberScopeByFqNameTest : AbstractSymbolByFqNameTest() {
|
||||
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List<KtSymbol> {
|
||||
val symbolData = SymbolByFqName.getSymbolDataFromFile(testDataPath)
|
||||
val symbols = with(symbolData) { toSymbols() }
|
||||
val classSymbol = symbols.singleOrNull() as? KtClassOrObjectSymbol
|
||||
?: error("Should be a single class symbol, but $symbols found")
|
||||
return classSymbol.getMemberScope().getAllSymbols().toList()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/fileScopeTest")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class FileScopeTestGenerated extends AbstractFileScopeTest {
|
||||
public class FirFileScopeTestGenerated extends AbstractFirFileScopeTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInFileScopeTest() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/fileScopeTest"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/memberScopeByFqName")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class MemberScopeByFqNameTestGenerated extends AbstractMemberScopeByFqNameTest {
|
||||
public class FirMemberScopeByFqNameTestGenerated extends AbstractFirMemberScopeByFqNameTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInMemberScopeByFqName() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/memberScopeByFqName"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirTestWithOutOfBlockModification
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByFqNameTest
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class AbstractFirSymbolByFqNameTest : AbstractSymbolByFqNameTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
|
||||
override fun doOutOfBlockModification(ktFile: KtFile) {
|
||||
FirTestWithOutOfBlockModification.doOutOfBlockModification(ktFile)
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirTestWithOutOfBlockModification
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByPsiTest
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class AbstractFirSymbolByPsiTest : AbstractSymbolByPsiTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
|
||||
override fun doOutOfBlockModification(ktFile: KtFile) {
|
||||
FirTestWithOutOfBlockModification.doOutOfBlockModification(ktFile)
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.fir.FirTestWithOutOfBlockModification
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.test.symbols.AbstractSymbolByReferenceTest
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class AbstractFirSymbolByReferenceTest : AbstractSymbolByReferenceTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirFrontendApiTestConfiguratorService
|
||||
|
||||
override fun doOutOfBlockModification(ktFile: KtFile) {
|
||||
FirTestWithOutOfBlockModification.doOutOfBlockModification(ktFile)
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.SymbolByFqName
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractSymbolByFqNameTest : AbstractSymbolTest() {
|
||||
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List<KtSymbol> {
|
||||
val symbolData = SymbolByFqName.getSymbolDataFromFile(testDataPath)
|
||||
return with(symbolData) { toSymbols() }
|
||||
}
|
||||
|
||||
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||
super.configureTest(builder)
|
||||
with(builder) {
|
||||
defaultDirectives {
|
||||
+JvmEnvironmentConfigurationDirectives.WITH_STDLIB
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractSymbolByPsiTest : AbstractSymbolTest() {
|
||||
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List<KtSymbol> {
|
||||
return ktFile.collectDescendantsOfType<KtDeclaration> { it.isValidForSymbolCreation }.map { declaration ->
|
||||
declaration.getSymbol()
|
||||
}
|
||||
}
|
||||
|
||||
private val KtDeclaration.isValidForSymbolCreation
|
||||
get() =
|
||||
when (this) {
|
||||
is KtParameter -> !this.isFunctionTypeParameter
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.symbols
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractSymbolByReferenceTest : AbstractSymbolTest() {
|
||||
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List<KtSymbol> {
|
||||
val referenceExpression = testServices.expressionMarkerProvider.getElementOfTypAtCaret<KtNameReferenceExpression>(ktFile)
|
||||
return listOfNotNull(referenceExpression.mainReference.resolveToSymbol())
|
||||
}
|
||||
}
|
||||
-91
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.symbols
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
|
||||
import org.jetbrains.kotlin.analysis.api.fir.test.framework.AbstractHLApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.DebugSymbolRenderer
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability
|
||||
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractSymbolTest : AbstractHLApiSingleFileTest() {
|
||||
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||
super.configureTest(builder)
|
||||
with(builder) {
|
||||
useDirectives(SymbolTestDirectives)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): List<KtSymbol>
|
||||
|
||||
override fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices) {
|
||||
val createPointers = SymbolTestDirectives.DO_NOT_CHECK_SYMBOL_RESTORE !in module.directives
|
||||
val pointersWithRendered = analyseOnPooledThreadInReadAction(ktFile) {
|
||||
collectSymbols(ktFile, testServices).map { symbol ->
|
||||
PointerWithRenderedSymbol(
|
||||
if (createPointers) symbol.createPointer() else null,
|
||||
with(DebugSymbolRenderer) { renderExtra(symbol) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
compareResults(pointersWithRendered, testServices)
|
||||
|
||||
doOutOfBlockModification(ktFile)
|
||||
|
||||
|
||||
if (createPointers) {
|
||||
restoreSymbolsInOtherReadActionAndCompareResults(ktFile, pointersWithRendered, testServices)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareResults(
|
||||
pointersWithRendered: List<PointerWithRenderedSymbol>,
|
||||
testServices: TestServices,
|
||||
) {
|
||||
val actual = pointersWithRendered.joinToString(separator = "\n") { it.rendered }
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun restoreSymbolsInOtherReadActionAndCompareResults(
|
||||
ktFile: KtFile,
|
||||
pointersWithRendered: List<PointerWithRenderedSymbol>,
|
||||
testServices: TestServices,
|
||||
) {
|
||||
val restored = analyseOnPooledThreadInReadAction(ktFile) {
|
||||
pointersWithRendered.map { (pointer, expectedRender) ->
|
||||
val restored = pointer!!.restoreSymbol()
|
||||
?: error("Symbol $expectedRender was not restored")
|
||||
with(DebugSymbolRenderer) { renderExtra(restored) }
|
||||
}
|
||||
}
|
||||
val actual = restored.joinToString(separator = "\n")
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun doOutOfBlockModification(ktFile: KtFile) {
|
||||
ServiceManager.getService(ktFile.project, KotlinModificationTrackerFactory::class.java)
|
||||
.incrementModificationsCount()
|
||||
}
|
||||
}
|
||||
|
||||
private object SymbolTestDirectives : SimpleDirectivesContainer() {
|
||||
val DO_NOT_CHECK_SYMBOL_RESTORE by directive(
|
||||
description = "Symbol restoring for some symbols in current test is not supported yet",
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
}
|
||||
|
||||
private data class PointerWithRenderedSymbol(val pointer: KtSymbolPointer<*>?, val rendered: String)
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/symbols/symbolByFqName")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SymbolByFqNameTestGenerated extends AbstractSymbolByFqNameTest {
|
||||
public class FirSymbolByFqNameTestGenerated extends AbstractFirSymbolByFqNameTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInSymbolByFqName() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/symbolByFqName"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/symbols/symbolByPsi")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SymbolByPsiTestGenerated extends AbstractSymbolByPsiTest {
|
||||
public class FirSymbolByPsiTestGenerated extends AbstractFirSymbolByPsiTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInSymbolByPsi() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/symbols/symbolByPsi"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
+1
-1
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("analysis/analysis-api/testData/symbols/symbolByReference")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class SymbolByReferenceTestGenerated extends AbstractSymbolByReferenceTest {
|
||||
public class FirSymbolByReferenceTestGenerated extends AbstractFirSymbolByReferenceTest {
|
||||
@Test
|
||||
@TestMetadata("accessorField.kt")
|
||||
public void testAccessorField() throws Exception {
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.test.framework
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractHLApiSingleFileTest : AbstractHLApiSingleModuleTest() {
|
||||
final override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
|
||||
val singleFile = ktFiles.single()
|
||||
doTestByFileStructure(singleFile, module, testServices)
|
||||
}
|
||||
|
||||
protected abstract fun doTestByFileStructure(ktFile: KtFile, module: TestModule, testServices: TestServices)
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.test.framework
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
abstract class AbstractHLApiSingleModuleTest : AbstractHLApiTest() {
|
||||
final override fun doTestByFileStructure(ktFiles: List<KtFile>, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||
val singleModule = moduleStructure.modules.single()
|
||||
doTestByFileStructure(ktFiles, singleModule, testServices)
|
||||
}
|
||||
|
||||
protected abstract fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices)
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.fir.test.framework
|
||||
|
||||
import com.intellij.mock.MockApplication
|
||||
import com.intellij.mock.MockProject
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiTest
|
||||
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.idea.references.HLApiReferenceProviderService
|
||||
import org.jetbrains.kotlin.idea.references.KotlinFirReferenceContributor
|
||||
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
|
||||
import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
|
||||
|
||||
abstract class AbstractHLApiTest : AbstractLowLevelApiTest() {
|
||||
@OptIn(InvalidWayOfUsingAnalysisSession::class)
|
||||
override fun registerServicesForProject(project: MockProject) {
|
||||
super.registerServicesForProject(project)
|
||||
project.registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider::class.java)
|
||||
}
|
||||
|
||||
override fun registerApplicationServices(application: MockApplication) {
|
||||
super.registerApplicationServices(application)
|
||||
if (application.getServiceIfCreated(KotlinReferenceProvidersService::class.java) != null) return
|
||||
application.registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
||||
application.registerService(KotlinReferenceProviderContributor::class.java, KotlinFirReferenceContributor::class.java)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.DuplicatedFirSourceElementsException
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
|
||||
/**
|
||||
* Temporary
|
||||
* @see org.jetbrains.kotlin.analysis.low.level.api.fir.DuplicatedFirSourceElementsException.IS_ENABLED
|
||||
*/
|
||||
inline fun <T> withPossiblyDisabledDuplicatedFirSourceElementsException(fileText: String, action: () -> T): T {
|
||||
val isDisabled = InTextDirectivesUtils.isDirectiveDefined(fileText, "IGNORE_DUPLICATED_FIR_SOURCE_EXCEPTION")
|
||||
|
||||
@Suppress("LiftReturnOrAssignment")
|
||||
if (isDisabled) {
|
||||
val wasEnabled = DuplicatedFirSourceElementsException.IS_ENABLED
|
||||
DuplicatedFirSourceElementsException.IS_ENABLED = false
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
DuplicatedFirSourceElementsException.IS_ENABLED = wasEnabled
|
||||
}
|
||||
} else {
|
||||
return action()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user