Skip to content

Commit c8adf3d

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Update color handling for recent Flutter Color class changes
In flutter/engine#54714 the "int value" that was used for storing the color values for a Flutter color was removed and replaced with `double red, double green` etc. The color computer used the `value` field so this stopped it from computing any colors for previews in LSP clients. No tests broke because the tests here use a mock version of the Color class that still had `value`. This change updates the mock Color class to match the new Flutter implementation, and updates the computer to use the red/green/blue doubles instead of parsing from an int. It also adds support for the new `Color.from()` constructor that was also recently added. Fixes Dart-Code/Dart-Code#5289 Change-Id: I3ff20bda0cc848e028822cfcb5a14e6a8f6934d5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386802 Commit-Queue: Phil Quitslund <pquitslund@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Phil Quitslund <pquitslund@google.com>
1 parent ef5295d commit c8adf3d

File tree

6 files changed

+344
-114
lines changed

6 files changed

+344
-114
lines changed

pkg/analysis_server/lib/src/computer/computer_color.dart

Lines changed: 110 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class ColorComputer {
5858
if (memberName != null) {
5959
colorConst = _getMember(colorConst, memberName);
6060
} else if (index != null) {
61-
colorConst = _getSwatchValue(colorConst, index);
61+
colorConst = _getSwatchColor(colorConst, index);
6262
}
6363

6464
return _tryRecordColor(expression, colorConst);
@@ -77,37 +77,56 @@ class ColorComputer {
7777
var classElement = staticElement?.enclosingElement3;
7878
var className = classElement?.name;
7979
var constructorName = constructor.name?.name;
80-
var constructorArgs = expression.argumentList.arguments
81-
.map((e) => e is Literal ? e : null)
82-
.toList();
80+
var constructorArgs = expression.argumentList.arguments.toList();
8381

84-
int? colorValue;
82+
ColorInformation? color;
8583
if (_isDartUi(classElement) && className == 'Color') {
86-
colorValue = _getDartUiColorValue(constructorName, constructorArgs);
84+
color = _getDartUiColor(constructorName, constructorArgs);
8785
} else if (_isFlutterPainting(classElement) && className == 'ColorSwatch') {
88-
colorValue =
89-
_getFlutterSwatchColorValue(constructorName, constructorArgs);
86+
color = _getFlutterSwatchColor(constructorName, constructorArgs);
9087
} else if (_isFlutterMaterial(classElement) &&
9188
className == 'MaterialAccentColor') {
92-
colorValue =
93-
_getFlutterMaterialAccentColorValue(constructorName, constructorArgs);
89+
color = _getFlutterMaterialAccentColor(constructorName, constructorArgs);
9490
}
9591

96-
return _tryRecordColorValue(expression, colorValue);
92+
return _tryRecordColorInformation(expression, color);
9793
}
9894

99-
/// Converts ARGB values into a single int value as 0xAARRGGBB as used by
100-
/// the dart:ui Color class.
101-
int _colorValueForComponents(int alpha, int red, int green, int blue) {
102-
return (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
103-
}
104-
105-
/// Extracts the color value from dart:ui Color constructor args.
106-
int? _getDartUiColorValue(String? name, List<Literal?> args) {
95+
/// Extracts the color information from dart:ui Color constructor args.
96+
ColorInformation? _getDartUiColor(String? name, List<Expression> args) {
10797
if (name == null && args.length == 1) {
98+
// Color(0xFF000000).
10899
var arg0 = args[0];
109-
return arg0 is IntegerLiteral ? arg0.value : null;
100+
return arg0 is IntegerLiteral ? getColorForInt(arg0.value) : null;
101+
} else if (name == 'from') {
102+
// Color.from(alpha: 1, red: 1, green: 1, blue: 1).
103+
double? alpha, red, green, blue;
104+
for (var arg in args.whereType<NamedExpression>()) {
105+
var expression = arg.expression;
106+
var value = expression is DoubleLiteral
107+
? expression.value
108+
: expression is IntegerLiteral
109+
? expression.value?.toDouble()
110+
: null;
111+
switch (arg.name.label.name) {
112+
case 'alpha':
113+
alpha = value;
114+
case 'red':
115+
red = value;
116+
case 'green':
117+
green = value;
118+
case 'blue':
119+
blue = value;
120+
}
121+
}
122+
return getColorForDoubles(
123+
alpha: alpha,
124+
red: red,
125+
green: green,
126+
blue: blue,
127+
);
110128
} else if (name == 'fromARGB' && args.length == 4) {
129+
// Color.fromARGB(255, 255, 255, 255).
111130
var arg0 = args[0];
112131
var arg1 = args[1];
113132
var arg2 = args[2];
@@ -119,9 +138,10 @@ class ColorComputer {
119138
var blue = arg3 is IntegerLiteral ? arg3.value : null;
120139

121140
return alpha != null && red != null && green != null && blue != null
122-
? _colorValueForComponents(alpha, red, green, blue)
141+
? ColorInformation(alpha, red, green, blue)
123142
: null;
124143
} else if (name == 'fromRGBO' && args.length == 4) {
144+
// Color.fromRGBO(255, 255, 255, 1.0).
125145
var arg0 = args[0];
126146
var arg1 = args[1];
127147
var arg2 = args[2];
@@ -138,24 +158,26 @@ class ColorComputer {
138158
var alpha = opacity != null ? (opacity * 255).toInt() : null;
139159

140160
return alpha != null && red != null && green != null && blue != null
141-
? _colorValueForComponents(alpha, red, green, blue)
161+
? ColorInformation(alpha, red, green, blue)
142162
: null;
143163
} else {
144164
return null;
145165
}
146166
}
147167

148-
/// Extracts the color value from Flutter MaterialAccentColor constructor args.
149-
int? _getFlutterMaterialAccentColorValue(String? name, List<Literal?> args) =>
168+
/// Extracts the color from Flutter MaterialAccentColor constructor args.
169+
ColorInformation? _getFlutterMaterialAccentColor(
170+
String? name, List<Expression> args) =>
150171
// MaterialAccentColor is a subclass of SwatchColor and has the same
151172
// constructor.
152-
_getFlutterSwatchColorValue(name, args);
173+
_getFlutterSwatchColor(name, args);
153174

154-
/// Extracts the color value from Flutter ColorSwatch constructor args.
155-
int? _getFlutterSwatchColorValue(String? name, List<Literal?> args) {
175+
/// Extracts the color information from Flutter ColorSwatch constructor args.
176+
ColorInformation? _getFlutterSwatchColor(
177+
String? name, List<Expression> args) {
156178
if (name == null && args.isNotEmpty) {
157179
var arg0 = args[0];
158-
return arg0 is IntegerLiteral ? arg0.value : null;
180+
return arg0 is IntegerLiteral ? getColorForInt(arg0.value) : null;
159181
} else {
160182
return null;
161183
}
@@ -166,25 +188,25 @@ class ColorComputer {
166188
/// Well-known getters like `shade500` will be mapped onto the swatch value
167189
/// with a matching index.
168190
DartObject? _getMember(DartObject target, String memberName) {
169-
var colorValue = target.getFieldFromHierarchy(memberName);
170-
if (colorValue != null) {
171-
return colorValue;
191+
var color = target.getFieldFromHierarchy(memberName);
192+
if (color != null) {
193+
return color;
172194
}
173195

174-
// If we didn't get a value but it's a getter we know how to read from a
196+
// If we didn't get a color but it's a getter we know how to read from a
175197
// swatch, try that.
176198
if (memberName.startsWith('shade')) {
177199
var shadeNumber = int.tryParse(memberName.substring(5));
178200
if (shadeNumber != null) {
179-
return _getSwatchValue(target, shadeNumber);
201+
return _getSwatchColor(target, shadeNumber);
180202
}
181203
}
182204

183205
return null;
184206
}
185207

186208
/// Extracts a specific shade index from a Flutter SwatchColor.
187-
DartObject? _getSwatchValue(DartObject target, int swatchValue) {
209+
DartObject? _getSwatchColor(DartObject target, int swatchValue) {
188210
var swatch = target.getFieldFromHierarchy('_swatch')?.toMapValue();
189211
if (swatch == null) return null;
190212

@@ -209,66 +231,90 @@ class ColorComputer {
209231
element?.library?.identifier ==
210232
'package:flutter/src/painting/colors.dart';
211233

212-
/// Tries to record a color value from [colorConst] for [expression].
234+
/// Tries to record a color from [colorConst] for [expression].
213235
///
214236
/// Returns whether a valid color was found and recorded.
215237
bool _tryRecordColor(Expression expression, DartObject? colorConst) =>
216-
_tryRecordColorValue(expression, _colorValueForColorConst(colorConst));
238+
_tryRecordColorInformation(expression, getColorForObject(colorConst));
217239

218-
/// Tries to record the [colorValue] for [expression].
240+
/// Tries to record the [color] for [expression].
219241
///
220242
/// Returns whether a valid color was found and recorded.
221-
bool _tryRecordColorValue(Expression expression, int? colorValue) {
222-
if (colorValue == null) return false;
223-
224-
// Build color information from the Color value.
225-
var color = _colorInformationForColorValue(colorValue);
243+
bool _tryRecordColorInformation(
244+
Expression expression, ColorInformation? color) {
245+
if (color == null) return false;
226246

227247
// Record the color against the original entire expression.
228248
_colors.add(ColorReference(expression.offset, expression.length, color));
229249
return true;
230250
}
231251

232-
static ColorInformation? getColorForValue(DartObject object) {
233-
if (object.type.isColor) {
234-
var colorValue = _colorValueForColorConst(object);
235-
if (colorValue != null) {
236-
return _colorInformationForColorValue(colorValue);
237-
}
238-
}
239-
return null;
252+
/// Gets [ColorInformation] from a set of doubles that are stored internally
253+
/// in a dart:ui Color object.
254+
static ColorInformation? getColorForDoubles({
255+
required double? alpha,
256+
required double? red,
257+
required double? green,
258+
required double? blue,
259+
}) {
260+
return alpha != null && red != null && green != null && blue != null
261+
? ColorInformation(
262+
(alpha * 255.0).round() & 0xff,
263+
(red * 255.0).round() & 0xff,
264+
(green * 255.0).round() & 0xff,
265+
(blue * 255.0).round() & 0xff,
266+
)
267+
: null;
240268
}
241269

242-
/// Creates a [ColorInformation] by extracting the argb values from
243-
/// [value] encoded as 0xAARRGGBB as in the dart:ui Color class.
244-
static ColorInformation _colorInformationForColorValue(int value) {
245-
// Extract color information according to dart:ui Color values.
246-
var alpha = (0xff000000 & value) >> 24;
247-
var red = (0x00ff0000 & value) >> 16;
248-
var blue = (0x000000ff & value) >> 0;
249-
var green = (0x0000ff00 & value) >> 8;
250-
251-
return ColorInformation(alpha, red, green, blue);
270+
/// Gets [ColorInformation] from a value like `0xFFFF9000` which is used in
271+
/// the default `Color()` constructor.
272+
static ColorInformation? getColorForInt(int? value) {
273+
return value != null
274+
? ColorInformation(
275+
(value >> 24) & 0xff,
276+
(value >> 16) & 0xff,
277+
(value >> 8) & 0xff,
278+
value & 0xff,
279+
)
280+
: null;
252281
}
253282

254-
/// Extracts the integer color value from the dart:ui Color constant [color].
255-
static int? _colorValueForColorConst(DartObject? color) {
256-
if (color == null || color.isNull) return null;
283+
/// Gets [ColorInformation] from the dart:ui Color object [color].
284+
static ColorInformation? getColorForObject(DartObject? color) {
285+
if (color == null || color.isNull || !color.type.isColor) return null;
257286

258287
// If the object has a "color" field, walk down to that, because some colors
259288
// like CupertinoColors have a "value=0" with an overridden getter that
260289
// would always result in a value representing black.
261290
color = color.getFieldFromHierarchy('color') ?? color;
262291

263-
return color.getFieldFromHierarchy('value')?.toIntValue();
292+
var alpha = color.getFieldFromHierarchy('a')?.toDoubleValue();
293+
var red = color.getFieldFromHierarchy('r')?.toDoubleValue();
294+
var green = color.getFieldFromHierarchy('g')?.toDoubleValue();
295+
var blue = color.getFieldFromHierarchy('b')?.toDoubleValue();
296+
297+
return getColorForDoubles(
298+
alpha: alpha,
299+
red: red,
300+
green: green,
301+
blue: blue,
302+
);
264303
}
265304
}
266305

267306
/// Information about a color that is present in a document.
268307
class ColorInformation {
308+
/// Alpha as a value from 0 to 255.
269309
final int alpha;
310+
311+
/// Red as a value from 0 to 255.
270312
final int red;
313+
314+
/// Green as a value from 0 to 255.
271315
final int green;
316+
317+
/// Blue as a value from 0 to 255.
272318
final int blue;
273319

274320
ColorInformation(this.alpha, this.red, this.green, this.blue);

0 commit comments

Comments
 (0)