Skip to content

Commit 554a5f5

Browse files
authored
Resolve color constants references (#848)
1 parent 4ca6215 commit 554a5f5

File tree

2 files changed

+58
-11
lines changed

2 files changed

+58
-11
lines changed

src/main/kotlin/insight/ColorLineMarkerProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class ColorLineMarkerProvider : LineMarkerProvider {
118118
element,
119119
color,
120120
GutterIconNavigationHandler handler@{ _, _ ->
121-
if (!element.isWritable) {
121+
if (!element.isWritable || !element.isValid) {
122122
return@handler
123123
}
124124

src/main/kotlin/insight/ColorUtil.kt

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,38 @@ import kotlin.math.round
2424
import org.jetbrains.uast.UCallExpression
2525
import org.jetbrains.uast.UElement
2626
import org.jetbrains.uast.UExpression
27+
import org.jetbrains.uast.UField
2728
import org.jetbrains.uast.UIdentifier
2829
import org.jetbrains.uast.ULiteralExpression
2930
import org.jetbrains.uast.UQualifiedReferenceExpression
3031
import org.jetbrains.uast.UReferenceExpression
32+
import org.jetbrains.uast.UResolvable
3133
import org.jetbrains.uast.generate.generationPlugin
3234
import org.jetbrains.uast.generate.replace
35+
import org.jetbrains.uast.resolveToUElement
3336

3437
fun <T> UIdentifier.findColor(function: (Map<String, Color>, Map.Entry<String, Color>) -> T): T? {
3538
val parent = this.uastParent
3639
val expression = parent as? UReferenceExpression ?: return null
37-
val type = expression.getExpressionType() ?: return null
40+
return findColorFromExpression(expression, function)
41+
}
42+
43+
private fun <T> findColorFromExpression(
44+
expression: UReferenceExpression,
45+
function: (Map<String, Color>, Map.Entry<String, Color>) -> T
46+
): T? {
47+
val referencedElement = expression.resolveToUElement()
48+
if (referencedElement is UField) {
49+
val referencedFieldInitializer = referencedElement.uastInitializer
50+
if (referencedFieldInitializer is UReferenceExpression) {
51+
return findColorFromExpression(referencedFieldInitializer, function)
52+
}
53+
}
3854

39-
val module = this.sourcePsi?.findModule() ?: return null
55+
val type = expression.getExpressionType() ?: return null
56+
val module = expression.sourcePsi?.findModule() ?: return null
4057
val facet = MinecraftFacet.getInstance(module) ?: return null
58+
val resolvedName = expression.resolvedName ?: return null
4159
for (abstractModuleType in facet.types) {
4260
val map = abstractModuleType.classToColorMappings
4361
for (entry in map.entries) {
@@ -47,7 +65,7 @@ fun <T> UIdentifier.findColor(function: (Map<String, Color>, Map.Entry<String, C
4765
// So we combine those checks and get this
4866
val colorClass = entry.key.substringBeforeLast('.')
4967
val colorName = entry.key.substringAfterLast('.')
50-
if (colorClass.startsWith(type.canonicalText) && colorName == expression.resolvedName ?: continue) {
68+
if (colorClass.startsWith(type.canonicalText) && colorName == resolvedName) {
5169
return function(map.filterKeys { key -> key.startsWith(colorClass) }, entry)
5270
}
5371
}
@@ -61,21 +79,50 @@ fun UIdentifier.findColor(
6179
vectorClasses: Array<String>?
6280
): Pair<Color, UElement>? {
6381
val sourcePsi = this.sourcePsi ?: return null
64-
val project = sourcePsi.project
65-
6682
val module = ModuleUtilCore.findModuleForPsiElement(sourcePsi) ?: return null
67-
6883
val facet = MinecraftFacet.getInstance(module) ?: return null
69-
7084
if (!facet.isOfType(moduleType)) {
7185
return null
7286
}
7387

74-
val methodExpression = uastParent as? UCallExpression ?: return null
75-
if (methodExpression.resolve()?.containingClass?.qualifiedName != className) {
76-
return null
88+
val methodExpression = uastParent as? UCallExpression
89+
if (methodExpression?.resolve()?.containingClass?.qualifiedName == className) {
90+
return findColorFromCallExpression(methodExpression, vectorClasses)
7791
}
7892

93+
var referencedElement = (uastParent as? UResolvable)?.resolveToUElement()
94+
while (referencedElement is UField) {
95+
val referencedFieldInitializer: UExpression? = referencedElement.uastInitializer
96+
if (referencedFieldInitializer is UCallExpression) {
97+
// The field is initialized with a method call
98+
return referencedFieldInitializer.methodIdentifier?.findColor(moduleType, className, vectorClasses)
99+
}
100+
101+
if (referencedFieldInitializer is UReferenceExpression) {
102+
// The field is probably initialized with a reference to another field
103+
val referenceNameElement = referencedFieldInitializer.referenceNameElement
104+
if (referenceNameElement is UIdentifier) {
105+
// The expression was simple enough
106+
return referenceNameElement.findColor(moduleType, className, vectorClasses)
107+
} else if (referenceNameElement is UResolvable) {
108+
// The expression is complex, so we resolve it. If it is a field we're on for another round
109+
referencedElement = referenceNameElement.resolveToUElement()
110+
continue
111+
}
112+
}
113+
114+
break
115+
}
116+
117+
return null
118+
}
119+
120+
private fun findColorFromCallExpression(
121+
methodExpression: UCallExpression,
122+
vectorClasses: Array<String>?
123+
): Pair<Color, UElement>? {
124+
val project = methodExpression.sourcePsi?.project ?: return null
125+
79126
val arguments = methodExpression.valueArguments
80127
val types = arguments.map(UExpression::getExpressionType)
81128

0 commit comments

Comments
 (0)