diff --git a/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/Accessor.kt b/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/Accessor.kt index b304719..a06365e 100644 --- a/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/Accessor.kt +++ b/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/Accessor.kt @@ -2,6 +2,7 @@ package com.faendir.intellij.gradleVersionCatalogs.kotlin import com.faendir.intellij.gradleVersionCatalogs.VCElementType import com.intellij.psi.* +import org.jetbrains.kotlin.utils.addToStdlib.applyIf import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull private const val PROVIDER = "org.gradle.api.provider.Provider" @@ -15,11 +16,22 @@ private const val BUNDLE_SUPPLIER = "org.gradle.api.internal.catalog.ExternalMod private const val PLUGIN_SUPPLIER = "org.gradle.api.internal.catalog.ExternalModuleDependencyFactory.PluginNotationSupplier" +@Suppress("SpellCheckingInspection") data class Accessor(val element: PsiElement, val id: String, val type: VCElementType) { companion object { fun find(element: PsiElement): Accessor? { - val returnType = element.lastChild.references.map { it.resolve() }.firstIsInstanceOrNull()?.returnType ?: return null - val segments by lazy { element.text.replace(Regex("\\s+"), "").split(".").drop(1) } + val references = if (element.lastChild.references.mapNotNull(PsiReference::resolve).isEmpty()) { + element.lastChild.firstChild.references + } else element.lastChild.references + val returnType = references.map { it.resolve() }.firstIsInstanceOrNull()?.returnType ?: return null + val segments by lazy { element.text.replace(Regex("\\s+"), "").split(".").drop(1) + // e.g. libs.map.get3dmap() -> [libs, map, get3dmap()] -> [map, get3dmap()] -> [map, 3dmap] + .map { + it.applyIf(it.matches(Regex("^get.*\\(\\s*\\)\$"))) { + removePrefix("get").removeSuffix("()") + } + } + } val type = when { returnType.extendsFrom(createGenericType(PROVIDER, element, createType(LIBRARY_DEPENDENCY, element))) || returnType.extendsFrom(createType(LIBRARY_SUPPLIER, element)) -> VCElementType.LIBRARY diff --git a/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/inlayhints/VersionCatalogInlayHintsProvider.kt b/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/inlayhints/VersionCatalogInlayHintsProvider.kt index 6dac067..c8783b8 100644 --- a/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/inlayhints/VersionCatalogInlayHintsProvider.kt +++ b/src/main/kotlin/com/faendir/intellij/gradleVersionCatalogs/kotlin/inlayhints/VersionCatalogInlayHintsProvider.kt @@ -37,7 +37,7 @@ class VersionCatalogInlayHintsProvider : InlayHintsProvider { val accessor = BuildGradleKtsPsiCache.findAccessor(element) if (accessor != null && BuildGradleKtsPsiCache.findAccessor(element.parent) == null) { val referencedElement = element.project.findInVersionsTomlKeyValues({ VersionsTomlPsiCache.getDefinitions(it, accessor.type) }, accessor.id) - .firstOrNull() + .firstOrNull() if (referencedElement != null) { val referencedValue = referencedElement.value if (referencedValue != null) { @@ -45,6 +45,7 @@ class VersionCatalogInlayHintsProvider : InlayHintsProvider { VCElementType.LIBRARY -> resolvePotentiallyTabledDefinition(referencedValue, "module") VCElementType.VERSION -> referencedValue.text?.unquote() VCElementType.PLUGIN -> resolvePotentiallyTabledDefinition(referencedValue, "id") + VCElementType.BUNDLE -> resolveBundlesDefinition(referencedValue) else -> null } if (inlayText != null) { @@ -66,10 +67,36 @@ class VersionCatalogInlayHintsProvider : InlayHintsProvider { return null } + /** + * handle the definition of libs.bundles.xxx + * + * @since 1.3.2 + */ + private fun resolveBundlesDefinition(referencedValue: TomlValue): String? { + return if (referencedValue is TomlArray) { + val size = referencedValue.elements.size + referencedValue.elements.take(3).mapNotNull { value -> + VersionsTomlPsiCache.getDefinitions( + referencedValue.containingFile as TomlFile, + VCElementType.LIBRARY + ).find { + it.key.textMatches(value.text.unquote()) + }?.value?.let { + resolvePotentiallyTabledDefinition(it, "module") + } + }.joinToString(separator = "➕", postfix = if (size > 3) "..." else "") + } else null + } + private fun resolvePotentiallyTabledDefinition(referencedValue: TomlValue, moduleTableKey: String) = when (referencedValue) { is TomlTable, is TomlInlineTable -> { val keys = referencedValue.childrenOfType() - keys.find { it.key.textMatches(moduleTableKey) }?.value?.text?.unquote()?.let { module -> + val identifier = if (referencedValue.text.contains(moduleTableKey)) { + keys.find { it.key.textMatches(moduleTableKey) }?.value?.text?.unquote() + } else { + keys.filterNot { it.text.contains("version") }.joinToString(":") { it.value?.text?.unquote().orEmpty() } + } + identifier?.let { module -> ( keys.find { it.key.textMatches("version") }?.value?.text?.unquote() ?: keys.find { it.isVersionRef() }?.value?.text?.unquote()?.let { search ->