Skip to content

Commit ccdc504

Browse files
t-regbsegorikftp
authored andcommitted
refactor: replace cached value retrieval with getOrCreateCachedIcon extension functions for improved performance and code clarity
1 parent 3a99785 commit ccdc504

File tree

4 files changed

+78
-82
lines changed

4 files changed

+78
-82
lines changed

tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/completion/ImageVectorCompletionContributor.kt

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@ import com.intellij.codeInsight.completion.CompletionResultSet
66
import com.intellij.codeInsight.lookup.LookupElement
77
import com.intellij.codeInsight.lookup.LookupElementDecorator
88
import com.intellij.codeInsight.lookup.LookupElementPresentation
9-
import com.intellij.psi.util.CachedValueProvider
10-
import com.intellij.psi.util.CachedValuesManager
119
import io.github.composegears.valkyrie.sdk.core.extensions.safeAs
12-
import io.github.composegears.valkyrie.util.createImageVectorIcon
10+
import io.github.composegears.valkyrie.util.getOrCreateCachedIcon
1311
import javax.swing.Icon
14-
import org.jetbrains.kotlin.psi.KtFile
1512
import org.jetbrains.kotlin.psi.KtProperty
1613

1714
class ImageVectorCompletionContributor : CompletionContributor() {
@@ -29,7 +26,7 @@ class ImageVectorCompletionContributor : CompletionContributor() {
2926
?.safeAs<KtProperty>()
3027
?.let { element ->
3128
if (!element.isVar) {
32-
getOrCreateCachedIcon(element.containingKtFile)
29+
element.containingKtFile.getOrCreateCachedIcon()
3330
} else {
3431
null
3532
}
@@ -47,15 +44,6 @@ class ImageVectorCompletionContributor : CompletionContributor() {
4744
}
4845
}
4946

50-
private fun getOrCreateCachedIcon(ktFile: KtFile): Icon? {
51-
val cachedValuesManager = CachedValuesManager.getManager(ktFile.project)
52-
53-
return cachedValuesManager.getCachedValue(ktFile) {
54-
val icon = ktFile.createImageVectorIcon()
55-
CachedValueProvider.Result.create(icon, ktFile)
56-
}
57-
}
58-
5947
private class ComposeColorLookupElementDecorator(
6048
delegate: LookupElement,
6149
private val icon: Icon,

tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/gutter/ImageVectorGutterProvider.kt

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,8 @@ import com.intellij.openapi.editor.markup.GutterIconRenderer
77
import com.intellij.pom.Navigatable
88
import com.intellij.psi.PsiElement
99
import com.intellij.psi.createSmartPointer
10-
import com.intellij.psi.util.CachedValueProvider
11-
import com.intellij.psi.util.CachedValuesManager
12-
import io.github.composegears.valkyrie.completion.ImageVectorIcon
13-
import io.github.composegears.valkyrie.psi.imagevector.ImageVectorPsiParser
1410
import io.github.composegears.valkyrie.sdk.core.extensions.safeAs
15-
import io.github.composegears.valkyrie.sdk.ir.core.IrImageVector
16-
import io.github.composegears.valkyrie.sdk.ir.util.aspectRatio
17-
import io.github.composegears.valkyrie.sdk.ir.util.dominantShadeColor
18-
import io.github.composegears.valkyrie.sdk.ir.xml.toVectorXmlString
11+
import io.github.composegears.valkyrie.util.getOrCreateGutterIcon
1912
import io.github.composegears.valkyrie.util.isImageVector
2013
import javax.swing.Icon
2114
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
@@ -33,8 +26,7 @@ class ImageVectorGutterProvider : LineMarkerProvider {
3326
elements.filterIsInstance<KtProperty>()
3427
.filter { it.isImageVector() }
3528
.forEach { property ->
36-
val icon = getOrCreateGutterIcon(property)
37-
29+
val icon = property.getOrCreateGutterIcon()
3830
icon?.let {
3931
property.nameIdentifier?.let { identifier ->
4032
// nameIdentifier is already a leaf (LeafPsiElement)
@@ -56,7 +48,7 @@ class ImageVectorGutterProvider : LineMarkerProvider {
5648
.firstOrNull { it.isImageVector() }
5749
?: return@mapNotNull null
5850

59-
val icon = getOrCreateGutterIcon(referencedProperty) ?: return@mapNotNull null
51+
val icon = referencedProperty.getOrCreateGutterIcon() ?: return@mapNotNull null
6052

6153
// Get the leaf element (identifier) from the reference expression
6254
// due to LineMarker is supposed to be registered for leaf elements only
@@ -72,46 +64,6 @@ class ImageVectorGutterProvider : LineMarkerProvider {
7264
.forEach(result::add)
7365
}
7466

75-
private fun getOrCreateGutterIcon(ktProperty: KtProperty): Icon? {
76-
val cachedValuesManager = CachedValuesManager.getManager(ktProperty.project)
77-
78-
return cachedValuesManager.getCachedValue(ktProperty) {
79-
val icon = ktProperty.createIcon()
80-
81-
CachedValueProvider.Result.create(icon, ktProperty)
82-
}
83-
}
84-
85-
private fun KtProperty.createIcon(): Icon? {
86-
val irImageVector = parseImageVectorProperty(this) ?: return null
87-
val vectorXml = irImageVector.toVectorXmlString()
88-
89-
return ImageVectorIcon(
90-
vectorXml = vectorXml,
91-
aspectRatio = irImageVector.aspectRatio,
92-
dominantShade = irImageVector.dominantShadeColor,
93-
)
94-
}
95-
96-
private fun parseImageVectorProperty(property: KtProperty): IrImageVector? {
97-
// Try parsing the current file
98-
val containingFile = property.containingKtFile
99-
ImageVectorPsiParser.parseToIrImageVector(containingFile)?.let { return it }
100-
101-
// For properties from libraries, navigate to decompiled/attached source
102-
val navigationElement = property.navigationElement
103-
if (navigationElement is KtProperty && navigationElement != property) {
104-
val sourceFile = navigationElement.containingKtFile
105-
106-
// Only parse if we have actual source code (not a stub)
107-
if (COMPILED_CODE_MARKER !in sourceFile.text) {
108-
return ImageVectorPsiParser.parseToIrImageVector(sourceFile)
109-
}
110-
}
111-
112-
return null
113-
}
114-
11567
private fun <T : PsiElement> createGutterIcon(
11668
element: T,
11769
icon: Icon,
@@ -133,8 +85,4 @@ class ImageVectorGutterProvider : LineMarkerProvider {
13385
GutterIconRenderer.Alignment.LEFT,
13486
{ "ImageVector Icon: $name" },
13587
)
136-
137-
private companion object {
138-
private const val COMPILED_CODE_MARKER = "/* compiled code */"
139-
}
14088
}

tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/icon/ImageVectorIconProvider.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import com.intellij.ide.IconProvider
44
import com.intellij.openapi.project.DumbAware
55
import com.intellij.psi.PsiElement
66
import com.intellij.psi.PsiFile
7-
import com.intellij.psi.util.CachedValueProvider
8-
import com.intellij.psi.util.CachedValuesManager
9-
import io.github.composegears.valkyrie.util.createImageVectorIcon
7+
import io.github.composegears.valkyrie.util.getOrCreateCachedIcon
108
import io.github.composegears.valkyrie.util.hasImageVectorProperties
119
import javax.swing.Icon
1210
import org.jetbrains.kotlin.psi.KtFile
@@ -26,9 +24,6 @@ class ImageVectorIconProvider :
2624
return null
2725
}
2826

29-
return CachedValuesManager.getCachedValue(ktFile) {
30-
val icon = ktFile.createImageVectorIcon()
31-
CachedValueProvider.Result.create(icon, ktFile)
32-
}
27+
return ktFile.getOrCreateCachedIcon()
3328
}
3429
}

tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/util/ImageVectorPsiUtil.kt

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
package io.github.composegears.valkyrie.util
22

3+
import com.intellij.psi.util.CachedValueProvider
4+
import com.intellij.psi.util.CachedValuesManager
35
import io.github.composegears.valkyrie.completion.ImageVectorIcon
46
import io.github.composegears.valkyrie.psi.imagevector.ImageVectorPsiParser
7+
import io.github.composegears.valkyrie.sdk.ir.core.IrImageVector
58
import io.github.composegears.valkyrie.sdk.ir.util.aspectRatio
69
import io.github.composegears.valkyrie.sdk.ir.util.dominantShadeColor
710
import io.github.composegears.valkyrie.sdk.ir.xml.toVectorXmlString
811
import javax.swing.Icon
912
import org.jetbrains.kotlin.psi.KtFile
1013
import org.jetbrains.kotlin.psi.KtProperty
1114

12-
val IMAGE_VECTOR_TYPES = setOf(
13-
"ImageVector",
14-
"androidx.compose.ui.graphics.vector.ImageVector",
15-
)
16-
1715
/**
1816
* Checks if this property is an ImageVector based on its type reference.
1917
*/
@@ -35,13 +33,43 @@ fun KtFile.hasImageVectorProperties(): Boolean {
3533
return properties.any { it.isImageVector() }
3634
}
3735

36+
/**
37+
* Gets or creates a cached gutter icon for an ImageVector property.
38+
*
39+
* This function uses the PSI caching mechanism to avoid recreating icons repeatedly
40+
* for the same property, improving performance.
41+
*/
42+
fun KtFile.getOrCreateCachedIcon(): Icon? {
43+
return CachedValuesManager
44+
.getManager(project).getCachedValue(this) {
45+
val icon = createImageVectorIcon()
46+
CachedValueProvider.Result.create(icon, this)
47+
}
48+
}
49+
50+
/**
51+
* Gets or creates a cached gutter icon for an ImageVector property.
52+
*
53+
* This function uses the PSI caching mechanism to avoid recreating icons repeatedly
54+
* for the same property, improving performance.
55+
*/
56+
fun KtProperty.getOrCreateGutterIcon(): Icon? {
57+
val cachedValuesManager = CachedValuesManager.getManager(project)
58+
59+
return cachedValuesManager.getCachedValue(this) {
60+
val icon = createIcon()
61+
62+
CachedValueProvider.Result.create(icon, this)
63+
}
64+
}
65+
3866
/**
3967
* Creates an icon representation from this Kotlin file containing an ImageVector.
4068
*
4169
* This function parses the ImageVector definition and renders it as a Swing Icon
4270
* suitable for display in the IDE UI (project view, gutter, completion, etc.).
4371
*/
44-
fun KtFile.createImageVectorIcon(): Icon? {
72+
private fun KtFile.createImageVectorIcon(): Icon? {
4573
val irImageVector = ImageVectorPsiParser.parseToIrImageVector(this) ?: return null
4674
val vectorXml = irImageVector.toVectorXmlString()
4775

@@ -51,3 +79,40 @@ fun KtFile.createImageVectorIcon(): Icon? {
5179
dominantShade = irImageVector.dominantShadeColor,
5280
)
5381
}
82+
83+
private fun KtProperty.createIcon(): Icon? {
84+
val irImageVector = parseImageVectorProperty(this) ?: return null
85+
val vectorXml = irImageVector.toVectorXmlString()
86+
87+
return ImageVectorIcon(
88+
vectorXml = vectorXml,
89+
aspectRatio = irImageVector.aspectRatio,
90+
dominantShade = irImageVector.dominantShadeColor,
91+
)
92+
}
93+
94+
private fun parseImageVectorProperty(property: KtProperty): IrImageVector? {
95+
// Try parsing the current file
96+
val containingFile = property.containingKtFile
97+
ImageVectorPsiParser.parseToIrImageVector(containingFile)?.let { return it }
98+
99+
// For properties from libraries, navigate to decompiled/attached source
100+
val navigationElement = property.navigationElement
101+
if (navigationElement is KtProperty && navigationElement != property) {
102+
val sourceFile = navigationElement.containingKtFile
103+
104+
// Only parse if we have actual source code (not a stub)
105+
if (COMPILED_CODE_MARKER !in sourceFile.text) {
106+
return ImageVectorPsiParser.parseToIrImageVector(sourceFile)
107+
}
108+
}
109+
110+
return null
111+
}
112+
113+
private val IMAGE_VECTOR_TYPES = setOf(
114+
"ImageVector",
115+
"androidx.compose.ui.graphics.vector.ImageVector",
116+
)
117+
118+
private const val COMPILED_CODE_MARKER = "/* compiled code */"

0 commit comments

Comments
 (0)