[LL API] Replace configuration lambdas with extensions
Caching 'LLFirSession' that is modified in arbitrary way is not safe. The new approach is less ad-hoc, as extensions are applied to all sessions.
This commit is contained in:
+6
-12
@@ -10,7 +10,6 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProviderStorage
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProviderStorage
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableResolveSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableResolveSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolveSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolveSession
|
||||||
@@ -46,10 +45,9 @@ internal class LLFirResolveSessionService(project: Project) {
|
|||||||
|
|
||||||
internal fun createFirResolveSessionFor(
|
internal fun createFirResolveSessionFor(
|
||||||
useSiteKtModule: KtModule,
|
useSiteKtModule: KtModule,
|
||||||
sessionProviderStorage: LLFirSessionProviderStorage,
|
sessionProviderStorage: LLFirSessionProviderStorage
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null,
|
|
||||||
): LLFirResolvableResolveSession {
|
): LLFirResolvableResolveSession {
|
||||||
val sessionProvider = sessionProviderStorage.getSessionProvider(useSiteKtModule, configureSession)
|
val sessionProvider = sessionProviderStorage.getSessionProvider(useSiteKtModule)
|
||||||
val useSiteSession = sessionProvider.rootModuleSession
|
val useSiteSession = sessionProvider.rootModuleSession
|
||||||
return when (useSiteKtModule) {
|
return when (useSiteKtModule) {
|
||||||
is KtSourceModule -> {
|
is KtSourceModule -> {
|
||||||
@@ -100,15 +98,11 @@ internal class LLFirResolveSessionService(project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun createFirResolveSessionForNoCaching(
|
fun createFirResolveSessionForNoCaching(useSiteKtModule: KtModule, project: Project): LLFirResolveSession {
|
||||||
useSiteKtModule: KtModule,
|
return LLFirResolveSessionService.createFirResolveSessionFor(
|
||||||
project: Project,
|
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null,
|
|
||||||
): LLFirResolveSession =
|
|
||||||
LLFirResolveSessionService.createFirResolveSessionFor(
|
|
||||||
useSiteKtModule = useSiteKtModule,
|
useSiteKtModule = useSiteKtModule,
|
||||||
sessionProviderStorage = LLFirSessionProviderStorage(project),
|
sessionProviderStorage = LLFirSessionProviderStorage(project)
|
||||||
configureSession = configureSession
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.low.level.api.fir.sessions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||||
|
|
||||||
|
interface LLFirSessionConfigurator {
|
||||||
|
companion object : ProjectExtensionDescriptor<LLFirSessionConfigurator>(
|
||||||
|
"org.jetbrains.kotlin.llFirSessionConfigurator",
|
||||||
|
LLFirSessionConfigurator::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
fun configure(session: LLFirSession)
|
||||||
|
}
|
||||||
+20
-20
@@ -50,8 +50,7 @@ internal object LLFirSessionFactory {
|
|||||||
globalResolveComponents: LLFirGlobalResolveComponents,
|
globalResolveComponents: LLFirGlobalResolveComponents,
|
||||||
sessionInvalidator: LLFirSessionInvalidator,
|
sessionInvalidator: LLFirSessionInvalidator,
|
||||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||||
librariesSessionFactory: LLFirLibrarySessionFactory,
|
librariesSessionFactory: LLFirLibrarySessionFactory
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null
|
|
||||||
): LLFirSourcesSession {
|
): LLFirSourcesSession {
|
||||||
sessionsCache[module]?.let { return it as LLFirSourcesSession }
|
sessionsCache[module]?.let { return it as LLFirSourcesSession }
|
||||||
checkCanceled()
|
checkCanceled()
|
||||||
@@ -110,8 +109,7 @@ internal object LLFirSessionFactory {
|
|||||||
sessionsCache,
|
sessionsCache,
|
||||||
globalResolveComponents,
|
globalResolveComponents,
|
||||||
sessionInvalidator,
|
sessionInvalidator,
|
||||||
librariesSessionFactory,
|
librariesSessionFactory
|
||||||
configureSession
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add(builtinsSession)
|
add(builtinsSession)
|
||||||
@@ -138,7 +136,8 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||||
|
|
||||||
configureSession?.invoke(this)
|
LLFirSessionConfigurator.configure(this)
|
||||||
|
|
||||||
extensionService.additionalCheckers.forEach(session.checkersComponent::register)
|
extensionService.additionalCheckers.forEach(session.checkersComponent::register)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,8 +150,7 @@ internal object LLFirSessionFactory {
|
|||||||
sessionInvalidator: LLFirSessionInvalidator,
|
sessionInvalidator: LLFirSessionInvalidator,
|
||||||
builtinSession: LLFirBuiltinsAndCloneableSession,
|
builtinSession: LLFirBuiltinsAndCloneableSession,
|
||||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||||
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
|
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null
|
|
||||||
): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||||
LLFirLibraryOrLibrarySourceResolvableModuleSession.checkIsValidKtModule(module)
|
LLFirLibraryOrLibrarySourceResolvableModuleSession.checkIsValidKtModule(module)
|
||||||
sessionsCache[module]?.let { return it as LLFirLibraryOrLibrarySourceResolvableModuleSession }
|
sessionsCache[module]?.let { return it as LLFirLibraryOrLibrarySourceResolvableModuleSession }
|
||||||
@@ -237,7 +235,7 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||||
|
|
||||||
configureSession?.invoke(this)
|
LLFirSessionConfigurator.configure(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,8 +244,7 @@ internal object LLFirSessionFactory {
|
|||||||
module: KtScriptModule,
|
module: KtScriptModule,
|
||||||
sessionInvalidator: LLFirSessionInvalidator,
|
sessionInvalidator: LLFirSessionInvalidator,
|
||||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||||
librariesSessionFactory: LLFirLibrarySessionFactory,
|
librariesSessionFactory: LLFirLibrarySessionFactory
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null
|
|
||||||
): LLFirScriptSession {
|
): LLFirScriptSession {
|
||||||
sessionsCache[module]?.let { return it as LLFirScriptSession }
|
sessionsCache[module]?.let { return it as LLFirScriptSession }
|
||||||
checkCanceled()
|
checkCanceled()
|
||||||
@@ -294,8 +291,7 @@ internal object LLFirSessionFactory {
|
|||||||
sessionsCache,
|
sessionsCache,
|
||||||
globalResolveComponents,
|
globalResolveComponents,
|
||||||
sessionInvalidator,
|
sessionInvalidator,
|
||||||
librariesSessionFactory,
|
librariesSessionFactory
|
||||||
configureSession
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add(builtinsSession)
|
add(builtinsSession)
|
||||||
@@ -321,7 +317,7 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
||||||
|
|
||||||
configureSession?.invoke(this)
|
LLFirSessionConfigurator.configure(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,8 +325,7 @@ internal object LLFirSessionFactory {
|
|||||||
project: Project,
|
project: Project,
|
||||||
module: KtNotUnderContentRootModule,
|
module: KtNotUnderContentRootModule,
|
||||||
sessionInvalidator: LLFirSessionInvalidator,
|
sessionInvalidator: LLFirSessionInvalidator,
|
||||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
sessionsCache: MutableMap<KtModule, LLFirSession>
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null
|
|
||||||
): LLFirNonUnderContentRootResolvableModuleSession {
|
): LLFirNonUnderContentRootResolvableModuleSession {
|
||||||
sessionsCache[module]?.let { return it as LLFirNonUnderContentRootResolvableModuleSession }
|
sessionsCache[module]?.let { return it as LLFirNonUnderContentRootResolvableModuleSession }
|
||||||
checkCanceled()
|
checkCanceled()
|
||||||
@@ -391,7 +386,7 @@ internal object LLFirSessionFactory {
|
|||||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
||||||
|
|
||||||
configureSession?.invoke(this)
|
LLFirSessionConfigurator.configure(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,8 +413,7 @@ internal object LLFirSessionFactory {
|
|||||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||||
globalResolveComponents: LLFirGlobalResolveComponents,
|
globalResolveComponents: LLFirGlobalResolveComponents,
|
||||||
sessionInvalidator: LLFirSessionInvalidator,
|
sessionInvalidator: LLFirSessionInvalidator,
|
||||||
librariesSessionFactory: LLFirLibrarySessionFactory,
|
librariesSessionFactory: LLFirLibrarySessionFactory
|
||||||
configureSession: (LLFirSession.() -> Unit)?
|
|
||||||
) {
|
) {
|
||||||
val project = module.project
|
val project = module.project
|
||||||
|
|
||||||
@@ -440,8 +434,7 @@ internal object LLFirSessionFactory {
|
|||||||
globalResolveComponents,
|
globalResolveComponents,
|
||||||
sessionInvalidator,
|
sessionInvalidator,
|
||||||
sessionsCache,
|
sessionsCache,
|
||||||
librariesSessionFactory = librariesSessionFactory,
|
librariesSessionFactory = librariesSessionFactory
|
||||||
configureSession = configureSession,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,6 +459,13 @@ internal object LLFirSessionFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun LLFirSessionConfigurator.Companion.configure(session: LLFirSession) {
|
||||||
|
val project = session.project
|
||||||
|
for (extension in extensionPointName.getExtensionList(project)) {
|
||||||
|
extension.configure(session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"This is a dirty hack used only for one usage (building fir for psi from stubs) and it should be removed after fix of that usage",
|
"This is a dirty hack used only for one usage (building fir for psi from stubs) and it should be removed after fix of that usage",
|
||||||
level = DeprecationLevel.ERROR
|
level = DeprecationLevel.ERROR
|
||||||
|
|||||||
+13
-32
@@ -24,33 +24,27 @@ class LLFirSessionProviderStorage(val project: Project) {
|
|||||||
|
|
||||||
private val globalComponents = LLFirGlobalResolveComponents(project)
|
private val globalComponents = LLFirGlobalResolveComponents(project)
|
||||||
|
|
||||||
fun getSessionProvider(
|
fun getSessionProvider(useSiteKtModule: KtModule): LLFirSessionProvider = when (useSiteKtModule) {
|
||||||
useSiteKtModule: KtModule,
|
|
||||||
configureSession: (LLFirSession.() -> Unit)? = null
|
|
||||||
): LLFirSessionProvider = when (useSiteKtModule) {
|
|
||||||
is KtSourceModule -> {
|
is KtSourceModule -> {
|
||||||
createSessionProviderForSourceSession(useSiteKtModule, configureSession)
|
createSessionProviderForSourceSession(useSiteKtModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtLibraryModule, is KtLibrarySourceModule -> {
|
is KtLibraryModule, is KtLibrarySourceModule -> {
|
||||||
createSessionProviderForLibraryOrLibrarySource(useSiteKtModule, configureSession)
|
createSessionProviderForLibraryOrLibrarySource(useSiteKtModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtScriptModule -> {
|
is KtScriptModule -> {
|
||||||
createSessionProviderForScriptSession(useSiteKtModule, configureSession)
|
createSessionProviderForScriptSession(useSiteKtModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtNotUnderContentRootModule -> {
|
is KtNotUnderContentRootModule -> {
|
||||||
createSessionProviderForNotUnderContentRootSession(useSiteKtModule, configureSession)
|
createSessionProviderForNotUnderContentRootSession(useSiteKtModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> error("Unexpected ${useSiteKtModule::class.simpleName}")
|
else -> error("Unexpected ${useSiteKtModule::class.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSessionProviderForSourceSession(
|
private fun createSessionProviderForSourceSession(useSiteKtModule: KtSourceModule): LLFirSessionProvider {
|
||||||
useSiteKtModule: KtSourceModule,
|
|
||||||
configureSession: (LLFirSession.() -> Unit)?
|
|
||||||
): LLFirSessionProvider {
|
|
||||||
val (sessions, session) = sourceAsUseSiteSessionCache.withMappings { mappings ->
|
val (sessions, session) = sourceAsUseSiteSessionCache.withMappings { mappings ->
|
||||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||||
val session = LLFirSessionFactory.createSourcesSession(
|
val session = LLFirSessionFactory.createSourcesSession(
|
||||||
@@ -59,8 +53,7 @@ class LLFirSessionProviderStorage(val project: Project) {
|
|||||||
globalComponents,
|
globalComponents,
|
||||||
sourceAsUseSiteSessionCache.sessionInvalidator,
|
sourceAsUseSiteSessionCache.sessionInvalidator,
|
||||||
sessions,
|
sessions,
|
||||||
librariesSessionFactory,
|
librariesSessionFactory
|
||||||
configureSession = configureSession,
|
|
||||||
)
|
)
|
||||||
sessions to session
|
sessions to session
|
||||||
}
|
}
|
||||||
@@ -68,10 +61,7 @@ class LLFirSessionProviderStorage(val project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun createSessionProviderForLibraryOrLibrarySource(
|
private fun createSessionProviderForLibraryOrLibrarySource(useSiteKtModule: KtModule): LLFirSessionProvider {
|
||||||
useSiteKtModule: KtModule,
|
|
||||||
configureSession: (LLFirSession.() -> Unit)?
|
|
||||||
): LLFirSessionProvider {
|
|
||||||
val (sessions, session) = libraryAsUseSiteSessionCache.withMappings { mappings ->
|
val (sessions, session) = libraryAsUseSiteSessionCache.withMappings { mappings ->
|
||||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||||
val session = LLFirSessionFactory.createLibraryOrLibrarySourceResolvableSession(
|
val session = LLFirSessionFactory.createLibraryOrLibrarySourceResolvableSession(
|
||||||
@@ -80,18 +70,14 @@ class LLFirSessionProviderStorage(val project: Project) {
|
|||||||
globalComponents,
|
globalComponents,
|
||||||
libraryAsUseSiteSessionCache.sessionInvalidator,
|
libraryAsUseSiteSessionCache.sessionInvalidator,
|
||||||
builtInsSessionFactory.getBuiltinsSession(useSiteKtModule.platform),
|
builtInsSessionFactory.getBuiltinsSession(useSiteKtModule.platform),
|
||||||
sessions,
|
sessions
|
||||||
configureSession = configureSession,
|
|
||||||
)
|
)
|
||||||
sessions to session
|
sessions to session
|
||||||
}
|
}
|
||||||
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSessionProviderForScriptSession(
|
private fun createSessionProviderForScriptSession(useSiteKtModule: KtScriptModule): LLFirSessionProvider {
|
||||||
useSiteKtModule: KtScriptModule,
|
|
||||||
configureSession: (LLFirSession.() -> Unit)?
|
|
||||||
): LLFirSessionProvider {
|
|
||||||
val (sessions, session) = sourceAsUseSiteSessionCache.withMappings { mappings ->
|
val (sessions, session) = sourceAsUseSiteSessionCache.withMappings { mappings ->
|
||||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||||
val session = LLFirSessionFactory.createScriptSession(
|
val session = LLFirSessionFactory.createScriptSession(
|
||||||
@@ -99,26 +85,21 @@ class LLFirSessionProviderStorage(val project: Project) {
|
|||||||
useSiteKtModule,
|
useSiteKtModule,
|
||||||
sourceAsUseSiteSessionCache.sessionInvalidator,
|
sourceAsUseSiteSessionCache.sessionInvalidator,
|
||||||
sessions,
|
sessions,
|
||||||
librariesSessionFactory,
|
librariesSessionFactory
|
||||||
configureSession = configureSession,
|
|
||||||
)
|
)
|
||||||
sessions to session
|
sessions to session
|
||||||
}
|
}
|
||||||
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSessionProviderForNotUnderContentRootSession(
|
private fun createSessionProviderForNotUnderContentRootSession(useSiteKtModule: KtNotUnderContentRootModule): LLFirSessionProvider {
|
||||||
useSiteKtModule: KtNotUnderContentRootModule,
|
|
||||||
configureSession: (LLFirSession.() -> Unit)?
|
|
||||||
): LLFirSessionProvider {
|
|
||||||
val (sessions, session) = notUnderContentRootSessionCache.withMappings { mappings ->
|
val (sessions, session) = notUnderContentRootSessionCache.withMappings { mappings ->
|
||||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||||
val session = LLFirSessionFactory.createNotUnderContentRootResolvableSession(
|
val session = LLFirSessionFactory.createNotUnderContentRootResolvableSession(
|
||||||
project,
|
project,
|
||||||
useSiteKtModule,
|
useSiteKtModule,
|
||||||
notUnderContentRootSessionCache.sessionInvalidator,
|
notUnderContentRootSessionCache.sessionInvalidator,
|
||||||
sessions,
|
sessions
|
||||||
configureSession = configureSession,
|
|
||||||
)
|
)
|
||||||
sessions to session
|
sessions to session
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-13
@@ -11,11 +11,16 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsFor
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.beforeElementDiagnosticCollectionHandler
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistentCheckerContextFactory
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistentCheckerContextFactory
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.renderWithClassName
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.renderWithClassName
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithClearCaches
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithClearCaches
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.useFirSessionConfigurator
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
|
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
|
||||||
@@ -26,6 +31,7 @@ import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl
|
|||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlin.test.services.assertions
|
import org.jetbrains.kotlin.test.services.assertions
|
||||||
@@ -36,21 +42,21 @@ import org.jetbrains.kotlin.test.services.assertions
|
|||||||
abstract class AbstractDiagnosticTraversalCounterTest : AbstractLowLevelApiSingleFileTest() {
|
abstract class AbstractDiagnosticTraversalCounterTest : AbstractLowLevelApiSingleFileTest() {
|
||||||
override val configurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
|
override val configurator = AnalysisApiFirSourceTestConfigurator(analyseInDependentSession = false)
|
||||||
|
|
||||||
|
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||||
|
super.configureTest(builder)
|
||||||
|
builder.apply {
|
||||||
|
useFirSessionConfigurator { BeforeElementLLFirSessionConfigurator() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||||
val handler = BeforeElementTestDiagnosticCollectionHandler()
|
resolveWithClearCaches(ktFile) { firResolveSession ->
|
||||||
resolveWithClearCaches(
|
|
||||||
ktFile,
|
|
||||||
configureSession = {
|
|
||||||
@OptIn(SessionConfiguration::class)
|
|
||||||
register(BeforeElementDiagnosticCollectionHandler::class, handler)
|
|
||||||
}
|
|
||||||
) { firResolveSession ->
|
|
||||||
// we should get diagnostics before we resolve the whole file by ktFile.getOrBuildFir
|
// we should get diagnostics before we resolve the whole file by ktFile.getOrBuildFir
|
||||||
ktFile.collectDiagnosticsForFile(firResolveSession, DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS)
|
ktFile.collectDiagnosticsForFile(firResolveSession, DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS)
|
||||||
|
|
||||||
val firFile = ktFile.getOrBuildFirOfType<FirFile>(firResolveSession)
|
val firFile = ktFile.getOrBuildFirOfType<FirFile>(firResolveSession)
|
||||||
|
|
||||||
val errorElements = collectErrorElements(firFile, handler)
|
val errorElements = collectErrorElements(firFile)
|
||||||
|
|
||||||
if (errorElements.isNotEmpty()) {
|
if (errorElements.isNotEmpty()) {
|
||||||
val zeroElements = errorElements.filter { it.second == 0 }
|
val zeroElements = errorElements.filter { it.second == 0 }
|
||||||
@@ -77,10 +83,8 @@ abstract class AbstractDiagnosticTraversalCounterTest : AbstractLowLevelApiSingl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectErrorElements(
|
private fun collectErrorElements(firFile: FirFile): List<Pair<FirElement, Int>> {
|
||||||
firFile: FirElement,
|
val handler = firFile.llFirSession.beforeElementDiagnosticCollectionHandler as BeforeElementTestDiagnosticCollectionHandler
|
||||||
handler: BeforeElementTestDiagnosticCollectionHandler
|
|
||||||
): List<Pair<FirElement, Int>> {
|
|
||||||
val errorElements = mutableListOf<Pair<FirElement, Int>>()
|
val errorElements = mutableListOf<Pair<FirElement, Int>>()
|
||||||
val nonDuplicatingElements = findNonDuplicatingFirElements(firFile).filter { element ->
|
val nonDuplicatingElements = findNonDuplicatingFirElements(firFile).filter { element ->
|
||||||
when {
|
when {
|
||||||
@@ -128,6 +132,13 @@ abstract class AbstractDiagnosticTraversalCounterTest : AbstractLowLevelApiSingl
|
|||||||
return elementUsageCount.filterValues { it == 1 }.keys
|
return elementUsageCount.filterValues { it == 1 }.keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class BeforeElementLLFirSessionConfigurator : LLFirSessionConfigurator {
|
||||||
|
@OptIn(SessionConfiguration::class)
|
||||||
|
override fun configure(session: LLFirSession) {
|
||||||
|
val handler = BeforeElementTestDiagnosticCollectionHandler()
|
||||||
|
session.register(BeforeElementDiagnosticCollectionHandler::class, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class BeforeElementTestDiagnosticCollectionHandler : BeforeElementDiagnosticCollectionHandler() {
|
class BeforeElementTestDiagnosticCollectionHandler : BeforeElementDiagnosticCollectionHandler() {
|
||||||
val visitedTimes = mutableMapOf<FirElement, Int>()
|
val visitedTimes = mutableMapOf<FirElement, Int>()
|
||||||
|
|||||||
+24
-14
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilt
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.beforeElementDiagnosticCollectionHandler
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.*
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.*
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.DanglingTopLevelModifierListStructureElement
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.DanglingTopLevelModifierListStructureElement
|
||||||
@@ -26,29 +27,32 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.isSourceSession
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.name
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.name
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithClearCaches
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithClearCaches
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirOutOfContentRootTestConfigurator
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirOutOfContentRootTestConfigurator
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.configurators.AnalysisApiFirSourceTestConfigurator
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.useFirSessionConfigurator
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.services.AssertionsService
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
import org.jetbrains.kotlin.test.services.*
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
|
||||||
import org.jetbrains.kotlin.test.services.assertions
|
|
||||||
|
|
||||||
abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileTest() {
|
abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileTest() {
|
||||||
|
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||||
|
super.configureTest(builder)
|
||||||
|
builder.apply {
|
||||||
|
useFirSessionConfigurator(::BeforeElementLLFirSessionConfigurator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||||
val handler = BeforeElementTestDiagnosticCollectionHandler(testServices.assertions)
|
resolveWithClearCaches(ktFile) { firResolveSession ->
|
||||||
resolveWithClearCaches(
|
|
||||||
ktFile,
|
|
||||||
configureSession = {
|
|
||||||
@OptIn(SessionConfiguration::class)
|
|
||||||
register(BeforeElementDiagnosticCollectionHandler::class, handler)
|
|
||||||
}
|
|
||||||
) { firResolveSession ->
|
|
||||||
check(firResolveSession.isSourceSession)
|
check(firResolveSession.isSourceSession)
|
||||||
|
|
||||||
val session = firResolveSession.getSessionFor(ktFile.getKtModule()) as LLFirResolvableModuleSession
|
val session = firResolveSession.getSessionFor(ktFile.getKtModule()) as LLFirResolvableModuleSession
|
||||||
|
val handler = session.beforeElementDiagnosticCollectionHandler as BeforeElementTestDiagnosticCollectionHandler
|
||||||
|
|
||||||
val fileStructureCache = session.moduleComponents.fileStructureCache
|
val fileStructureCache = session.moduleComponents.fileStructureCache
|
||||||
|
|
||||||
val fileStructure = fileStructureCache.getFileStructure(ktFile)
|
val fileStructure = fileStructureCache.getFileStructure(ktFile)
|
||||||
@@ -68,11 +72,17 @@ abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileT
|
|||||||
is DanglingTopLevelModifierListStructureElement -> fir
|
is DanglingTopLevelModifierListStructureElement -> fir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class BeforeElementLLFirSessionConfigurator(private val testServices: TestServices) : LLFirSessionConfigurator {
|
||||||
|
@OptIn(SessionConfiguration::class)
|
||||||
|
override fun configure(session: LLFirSession) {
|
||||||
|
val handler = BeforeElementTestDiagnosticCollectionHandler(testServices.assertions)
|
||||||
|
session.register(BeforeElementDiagnosticCollectionHandler::class, handler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class BeforeElementTestDiagnosticCollectionHandler(
|
private class BeforeElementTestDiagnosticCollectionHandler(
|
||||||
private val assertions: AssertionsService
|
private val assertions: AssertionsService
|
||||||
) :
|
) : BeforeElementDiagnosticCollectionHandler() {
|
||||||
BeforeElementDiagnosticCollectionHandler() {
|
|
||||||
lateinit var elementsToCheckContext: List<FirDeclaration>
|
lateinit var elementsToCheckContext: List<FirDeclaration>
|
||||||
lateinit var firFile: FirFile
|
lateinit var firFile: FirFile
|
||||||
|
|
||||||
|
|||||||
+19
-8
@@ -6,20 +6,24 @@
|
|||||||
package org.jetbrains.kotlin.analysis.low.level.api.fir
|
package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolveSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolveSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||||
|
import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.renderer.FirRenderer
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFileSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFileSymbol
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||||
|
import org.jetbrains.kotlin.test.services.PreAnalysisHandler
|
||||||
|
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||||
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
|
||||||
|
|
||||||
internal fun FirElement.renderWithClassName(): String =
|
internal fun FirElement.renderWithClassName(): String =
|
||||||
@@ -36,13 +40,9 @@ internal fun FirBasedSymbol<*>.name(): String = when (this) {
|
|||||||
|
|
||||||
internal fun FirDeclaration.name(): String = symbol.name()
|
internal fun FirDeclaration.name(): String = symbol.name()
|
||||||
|
|
||||||
internal inline fun <R> resolveWithClearCaches(
|
internal inline fun <R> resolveWithClearCaches(context: KtElement, action: (LLFirResolveSession) -> R): R {
|
||||||
context: KtElement,
|
|
||||||
noinline configureSession: LLFirSession.() -> Unit = {},
|
|
||||||
action: (LLFirResolveSession) -> R,
|
|
||||||
): R {
|
|
||||||
val project = context.project
|
val project = context.project
|
||||||
val firResolveSession = createFirResolveSessionForNoCaching(context.getKtModule(project), project, configureSession)
|
val firResolveSession = createFirResolveSessionForNoCaching(context.getKtModule(project), project)
|
||||||
return action(firResolveSession)
|
return action(firResolveSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,3 +53,14 @@ internal val LLFirResolveSession.isSourceSession: Boolean
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun TestConfigurationBuilder.useFirSessionConfigurator(configurator: (TestServices) -> LLFirSessionConfigurator) {
|
||||||
|
class ConfiguratorPreAnalysisHandler(testServices: TestServices) : PreAnalysisHandler(testServices) {
|
||||||
|
override fun preprocessModuleStructure(moduleStructure: TestModuleStructure) {
|
||||||
|
val project = testServices.environmentManager.getProject()
|
||||||
|
LLFirSessionConfigurator.registerExtension(project, configurator(testServices))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usePreAnalysisHandlers(::ConfiguratorPreAnalysisHandler)
|
||||||
|
}
|
||||||
+2
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLi
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.KtCompilerPluginsProviderForTests
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.KtCompilerPluginsProviderForTests
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLFirSealedClassInheritorsProcessorFactoryForTests
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLFirSealedClassInheritorsProcessorFactoryForTests
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.PackagePartProviderTestImpl
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.PackagePartProviderTestImpl
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtCompilerPluginsProvider
|
import org.jetbrains.kotlin.analysis.project.structure.KtCompilerPluginsProvider
|
||||||
import org.jetbrains.kotlin.analysis.providers.PackagePartProviderFactory
|
import org.jetbrains.kotlin.analysis.providers.PackagePartProviderFactory
|
||||||
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
|
import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar
|
||||||
@@ -39,6 +40,7 @@ object AnalysisApiFirTestServiceRegistrar : AnalysisApiTestServiceRegistrar() {
|
|||||||
override fun registerProjectExtensionPoints(project: MockProject, testServices: TestServices) {
|
override fun registerProjectExtensionPoints(project: MockProject, testServices: TestServices) {
|
||||||
IrGenerationExtension.registerExtensionPoint(project)
|
IrGenerationExtension.registerExtensionPoint(project)
|
||||||
FirExtensionRegistrarAdapter.registerExtensionPoint(project)
|
FirExtensionRegistrarAdapter.registerExtensionPoint(project)
|
||||||
|
LLFirSessionConfigurator.registerExtensionPoint(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(KtAnalysisApiInternals::class)
|
@OptIn(KtAnalysisApiInternals::class)
|
||||||
|
|||||||
Reference in New Issue
Block a user