Skip to content

Commit ad31c10

Browse files
authored
🐛 Resolves the referenced element before parsing colors (#6768)
Fixes #5436. | Before | After | |------|------| | ![image](https://github.com/flutter/flutter-intellij/assets/15884415/632e3d1c-9bf4-4ff9-9b87-dd79930a5830) | ![image](https://github.com/flutter/flutter-intellij/assets/15884415/c9188e22-4e93-4bc8-a0ab-756b5aec6f43) | ## Implementation details - `Colors` and `CupertinoColors` are hard-coded to determine *colored element*. The condition has been removed, which means all elements will be predicated. - Referenced will be resolved before the element gets parsed by text directly. - All the additional checks will be called only if the element type is `VAR_INIT` (for declarations) or `FUNCTION_BODY` (for getters) to avoid too much performance regression. Test case: ```dart import 'package:flutter/material.dart' hide Colors; const Color _c1 = Color(0xff000000); final _c2 = _c1; Color get _c3 => _c2; void test() { const Color c1 = _c1; const Color c2 = Color(0xffffffff); const Color c3 = Color.fromARGB(255, 123, 231, 31); const Color c4 = Color(0xff923998); const Color c5 = c2; const Color c6 = TC.c1; const Color c7 = TC.c2; const Color c8 = TC.c3; const Color c9 = Colors.black; } class TC { static const Color c1 = Color(0xff449978); static const Color c2 = Color(0xffdb2f7f); static const Color c3 = Color.fromARGB(150, 66, 231, 31); } class Colors { static const Color white = Color(0xffaa9933); static const Color tests = Colors.white; static const Color black = Colors.tests; static const Color tcC1 = TC.c1; final Color tcC2 = TC.c2; Color get tcC3 => TC.c3; } ``` ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read the [Flutter Style Guide] _recently_, and have followed its advice. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
1 parent da4d38a commit ad31c10

File tree

1 file changed

+53
-5
lines changed

1 file changed

+53
-5
lines changed

flutter-idea/src/io/flutter/editor/FlutterColorProvider.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
import com.intellij.psi.impl.source.tree.AstBufferUtil;
1515
import com.jetbrains.lang.dart.DartLanguage;
1616
import com.jetbrains.lang.dart.DartTokenTypes;
17-
import com.jetbrains.lang.dart.psi.DartArgumentList;
18-
import com.jetbrains.lang.dart.psi.DartArguments;
19-
import com.jetbrains.lang.dart.psi.DartExpression;
20-
import com.jetbrains.lang.dart.psi.DartLiteralExpression;
17+
import com.jetbrains.lang.dart.psi.*;
2118
import io.flutter.FlutterBundle;
2219
import org.jetbrains.annotations.NotNull;
2320
import org.jetbrains.annotations.Nullable;
@@ -38,7 +35,6 @@ public Color getColorFrom(@NotNull PsiElement element) {
3835
if (element.getNode().getElementType() != DartTokenTypes.IDENTIFIER) return null;
3936

4037
final String name = element.getText();
41-
if (!(name.equals("Colors") || name.equals("CupertinoColors") || name.equals("Color"))) return null;
4238

4339
final PsiElement refExpr = topmostReferenceExpression(element);
4440
if (refExpr == null) return null;
@@ -62,6 +58,28 @@ else if (parent.getNode().getElementType() == DartTokenTypes.SIMPLE_TYPE) {
6258
return parseColorElements(parent, refExpr);
6359
}
6460
else {
61+
if (parent.getNode().getElementType() == DartTokenTypes.VAR_INIT ||
62+
parent.getNode().getElementType() == DartTokenTypes.FUNCTION_BODY) {
63+
final PsiElement reference = resolveReferencedElement(refExpr);
64+
if (reference != null && reference.getLastChild() != null) {
65+
Color tryParseColor = null;
66+
if (reference instanceof DartCallExpression) {
67+
final DartExpression expression = ((DartCallExpression)reference).getExpression();
68+
if (expression != null && expression.getLastChild() instanceof DartReferenceExpression) {
69+
tryParseColor = parseColorElements(reference, expression);
70+
if (tryParseColor != null) return tryParseColor;
71+
}
72+
}
73+
final PsiElement lastChild = reference.getLastChild();
74+
if (lastChild instanceof DartArguments && reference.getParent() != null) {
75+
tryParseColor = parseColorElements(reference, reference.getParent());
76+
}
77+
else {
78+
tryParseColor = parseColorElements(reference, reference.getLastChild());
79+
}
80+
if (tryParseColor != null) return tryParseColor;
81+
}
82+
}
6583
// name.equals(refExpr.getFirstChild().getText()) -> Colors.blue
6684
final PsiElement idNode = refExpr.getFirstChild();
6785
if (idNode == null) return null;
@@ -82,6 +100,36 @@ else if (parent.getNode().getElementType() == DartTokenTypes.SIMPLE_TYPE) {
82100
return null;
83101
}
84102

103+
@Nullable
104+
private PsiElement resolveReferencedElement(@NotNull PsiElement element) {
105+
if (element instanceof DartCallExpression && element.getFirstChild().getText().equals("Color")) {
106+
return element;
107+
}
108+
final PsiElement symbol = element.getLastChild();
109+
final PsiElement result;
110+
if (symbol instanceof DartReference) {
111+
result = ((DartReference)symbol).resolve();
112+
}
113+
else if (element instanceof DartReference) {
114+
result = ((DartReference)element).resolve();
115+
}
116+
else {
117+
return null;
118+
}
119+
if (!(result instanceof DartComponentName) || result.getParent() == null) return null;
120+
final PsiElement declaration = result.getParent().getParent();
121+
if (!(declaration instanceof DartVarDeclarationList)) return null;
122+
final PsiElement lastChild = declaration.getLastChild();
123+
if (!(lastChild instanceof DartVarInit)) return null;
124+
125+
final PsiElement effectiveElement = lastChild.getLastChild();
126+
// Recursively determine reference if the initialization is still a `DartReference`.
127+
if (effectiveElement instanceof DartReference && !(effectiveElement instanceof DartCallExpression)) {
128+
return resolveReferencedElement(effectiveElement);
129+
}
130+
return effectiveElement;
131+
}
132+
85133
@Nullable
86134
private Color parseColorElements(@NotNull PsiElement parent, @NotNull PsiElement refExpr) {
87135
final PsiElement selectorNode = refExpr.getLastChild();

0 commit comments

Comments
 (0)