[kotlin] add some debug info for could not resolve *Id exception

KTIJ-33638
KTIJ-33640
KTIJ-33642

GitOrigin-RevId: c788badc08d6acf840a3b0cadec618cbd752e648
This commit is contained in:
Ilya Kirillov
2025-04-02 13:34:26 +02:00
committed by intellij-monorepo-bot
parent f45f504a20
commit 131b3c9567
6 changed files with 86 additions and 10 deletions

View File

@@ -38,7 +38,7 @@ abstract class KaEntityBasedModule<E : WorkspaceEntityWithSymbolicId, EID : Symb
internal val entity: E
get() = entityId.resolve(currentSnapshot)
?: error("Could not resolve $entityId")
?: couldNotResolveEntityError(this)
/**
* Should be directly overridden by the final inheritor.

View File

@@ -0,0 +1,46 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.base.fir.projectStructure.modules
import com.intellij.platform.backend.workspace.workspaceModel
import com.intellij.platform.workspace.storage.WorkspaceEntity
import org.jetbrains.kotlin.idea.base.fir.projectStructure.provider.K2IDEProjectStructureProviderCache
internal fun <M> couldNotResolveEntityError(
owner: M,
): Nothing where M: KaEntityBasedModule<*, *> {
error(buildString {
appendLine("Could not resolve `${owner.entityId}` ")
appendLine("for `$owner` ")
if (owner is KaModuleWithDebugData) {
val project = owner.project
val cache = K2IDEProjectStructureProviderCache.getInstance(project)
val data = owner.creationData
val entityClass = owner.entityInterface
appendLine("[createdWithoutCaching=${data.createdWithoutCaching}] ")
appendLine("[createdSource=${data.createdWithoutCaching}, currentSource=${cache.getCacheSourcesTracker().modificationCount}] ")
appendLine("[createdLibs=${data.createdLibrariesTrackerValue}, currentLibs=${cache.getCacheSdkAndLibrariesTracker().modificationCount}] ")
runCatching {
val allEntries = project.workspaceModel.currentSnapshot.entities(entityClass).toList()
appendLine("[allEntries=${allEntries}] ")
}.onFailure {
appendLine("error while collecting all entries: ${it.message}")
appendLine(it.message)
appendLine(it.stackTraceToString())
}
}
})
}
internal interface KaModuleWithDebugData {
val creationData: KaEntityBasedModuleCreationData
val entityInterface: Class<out WorkspaceEntity>
}
internal data class KaEntityBasedModuleCreationData(
val createdWithoutCaching: Boolean,
val createdSourceTrackerValue: Long,
val createdLibrariesTrackerValue: Long,
)

View File

@@ -3,9 +3,13 @@ package org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.library
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.platform.workspace.jps.entities.LibraryEntity
import com.intellij.platform.workspace.jps.entities.LibraryId
import com.intellij.platform.workspace.storage.WorkspaceEntity
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.analysis.api.projectStructure.KaLibrarySourceModule
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaEntityBasedModuleCreationData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaModuleWithDebugData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.librarySource.KaLibrarySourceModuleImpl
import org.jetbrains.kotlin.idea.base.fir.projectStructure.provider.InternalKaModuleConstructor
import org.jetbrains.kotlin.idea.base.platforms.*
@@ -30,7 +34,9 @@ import org.jetbrains.kotlin.konan.file.File as KonanFile
internal class KaLibraryModuleImpl @InternalKaModuleConstructor constructor(
override val entityId: LibraryId,
override val project: Project,
) : KaLibraryEntityBasedLibraryModuleBase() {
override val creationData: KaEntityBasedModuleCreationData,
) : KaLibraryEntityBasedLibraryModuleBase(), KaModuleWithDebugData {
override val librarySources: KaLibrarySourceModule? by lazy(LazyThreadSafetyMode.PUBLICATION) {
KaLibrarySourceModuleImpl(this)
@@ -76,6 +82,8 @@ internal class KaLibraryModuleImpl @InternalKaModuleConstructor constructor(
}
}
override val entityInterface: Class<out WorkspaceEntity> get() = LibraryEntity::class.java
override fun equals(other: Any?): Boolean {
if (this === other) return true
return other is KaLibraryModuleImpl

View File

@@ -5,11 +5,15 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.platform.workspace.jps.entities.LibraryEntity
import com.intellij.platform.workspace.jps.entities.SdkEntity
import com.intellij.platform.workspace.jps.entities.SdkId
import com.intellij.platform.workspace.storage.WorkspaceEntity
import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
import org.jetbrains.kotlin.analysis.api.KaPlatformInterface
import org.jetbrains.kotlin.analysis.api.projectStructure.KaLibrarySourceModule
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaEntityBasedModuleCreationData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaModuleWithDebugData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.librarySource.KaLibrarySdkSourceModuleImpl
import org.jetbrains.kotlin.idea.base.fir.projectStructure.provider.InternalKaModuleConstructor
import org.jetbrains.kotlin.idea.base.util.caching.findSdkBridge
@@ -21,7 +25,8 @@ import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
internal class KaLibrarySdkModuleImpl @InternalKaModuleConstructor constructor(
override val project: Project,
override val entityId: SdkId,
) : KaLibraryModuleBase<SdkEntity, SdkId>() {
override val creationData: KaEntityBasedModuleCreationData
) : KaLibraryModuleBase<SdkEntity, SdkId>(), KaModuleWithDebugData {
val sdk: Sdk
get() = entity.findSdkBridge(currentSnapshot)
@@ -47,6 +52,8 @@ internal class KaLibrarySdkModuleImpl @InternalKaModuleConstructor constructor(
else -> JvmPlatforms.unspecifiedJvmPlatform
}
override val entityInterface: Class<out WorkspaceEntity> get() = SdkEntity::class.java
override fun equals(other: Any?): Boolean {
if (this === other) return true
return other is KaLibrarySdkModuleImpl

View File

@@ -2,7 +2,12 @@
package org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.source
import com.intellij.openapi.project.Project
import com.intellij.platform.workspace.jps.entities.LibraryEntity
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.jps.entities.ModuleId
import com.intellij.platform.workspace.storage.WorkspaceEntity
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaEntityBasedModuleCreationData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaModuleWithDebugData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.provider.InternalKaModuleConstructor
import org.jetbrains.kotlin.idea.base.projectStructure.KaSourceModuleKind
@@ -10,7 +15,10 @@ internal class KaSourceModuleImpl @InternalKaModuleConstructor constructor(
override val entityId: ModuleId,
override val kind: KaSourceModuleKind,
override val project: Project,
) : KaSourceModuleBase() {
override val creationData: KaEntityBasedModuleCreationData,
) : KaSourceModuleBase(), KaModuleWithDebugData {
override val entityInterface: Class<out WorkspaceEntity> get() = ModuleEntity::class.java
override fun equals(other: Any?): Boolean {
if (this === other) return true
return other is KaSourceModuleImpl

View File

@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.api.platform.analysisMessageBus
import org.jetbrains.kotlin.analysis.api.platform.modification.*
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
import org.jetbrains.kotlin.analysis.api.projectStructure.KaSourceModule
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.KaEntityBasedModuleCreationData
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.library.KaLibraryModuleImpl
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.library.KaLibrarySdkModuleImpl
import org.jetbrains.kotlin.idea.base.fir.projectStructure.modules.source.KaSourceModuleImpl
@@ -120,23 +121,29 @@ internal class K2IDEProjectStructureProviderCache(
@OptIn(InternalKaModuleConstructor::class)
fun cachedKaLibraryModule(id: LibraryId): KaLibraryModuleImpl {
if (!isItSafeToCacheModules()) return KaLibraryModuleImpl(id, project)
return libraryCache.computeIfAbsent(id) { KaLibraryModuleImpl(id, project) }
if (!isItSafeToCacheModules()) return KaLibraryModuleImpl(id, project, creationData())
return libraryCache.computeIfAbsent(id) { KaLibraryModuleImpl(id, project, creationData()) }
}
@OptIn(InternalKaModuleConstructor::class)
fun cachedKaSdkModule(id: SdkId): KaLibrarySdkModuleImpl {
if (!isItSafeToCacheModules()) return KaLibrarySdkModuleImpl(project, id)
return sdkCache.computeIfAbsent(id) { KaLibrarySdkModuleImpl(project, id) }
if (!isItSafeToCacheModules()) return KaLibrarySdkModuleImpl(project, id, creationData())
return sdkCache.computeIfAbsent(id) { KaLibrarySdkModuleImpl(project, id, creationData()) }
}
@OptIn(InternalKaModuleConstructor::class)
fun cachedKaSourceModule(id: ModuleId, kind: KaSourceModuleKind): KaSourceModule {
if (!isItSafeToCacheModules()) return KaSourceModuleImpl(id, kind, project)
if (!isItSafeToCacheModules()) return KaSourceModuleImpl(id, kind, project, creationData())
val cache = moduleCacheForKind(kind)
return cache.computeIfAbsent(id) { KaSourceModuleImpl(id, kind, project) }
return cache.computeIfAbsent(id) { KaSourceModuleImpl(id, kind, project, creationData()) }
}
private fun creationData() = KaEntityBasedModuleCreationData(
createdWithoutCaching = isItSafeToCacheModules(),
createdSourceTrackerValue = sourcesTracker.modificationCount,
createdLibrariesTrackerValue = sdkAndLibrariesTracker.modificationCount,
)
/**
* Checks if it is safe to cache a `KaModule` inside `K2IDEProjectStructureProviderCache` and `K2IDEProjectStructureProvider`.
*