Version 2.16.0-12.0.dev
Merge commit '39d930305c40b3a33ef73360d2232e3be7dcaba8' into 'dev'
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart
index 52f09fb..06fdd44 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_color_presentation.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@@ -49,24 +50,68 @@
return (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
}
- /// Builds a list of valid color presentations for the requested color.
+ /// Creates a [ColorPresentation] for inserting code to produce a dart:ui
+ /// or Flutter Color at [editRange].
///
- /// Currently only a single presentation (`Color(0xAARRGGBB)`) is provided.
+ /// [colorType] is the Type of the Color class whose constructor will be
+ /// called. This will be replaced into [editRange] and any required import
+ /// statement will produce additional edits.
+ ///
+ /// [label] is the visible label shown to the user and should roughly reflect
+ /// the code that will be inserted.
+ ///
+ /// [invocationString] is written immediately after [colorType] in [editRange].
+ Future<ColorPresentation> _createColorPresentation(
+ ResolvedUnitResult unit,
+ SourceRange editRange,
+ ClassElement colorType,
+ String label,
+ String invocationString,
+ ) async {
+ final builder = ChangeBuilder(session: unit.session);
+ await builder.addDartFileEdit(unit.path, (builder) {
+ builder.addReplacement(editRange, (builder) {
+ builder.writeType(colorType.thisType);
+ builder.write(invocationString);
+ });
+ });
+
+ // We can only apply changes to the same file, so filter any change from the
+ // builder to only include this file, otherwise we may corrupt the users
+ // source (although hopefully we don't produce edits for other files).
+ final editsForThisFile = builder.sourceChange.edits
+ .where((edit) => edit.file == unit.path)
+ .expand((edit) => edit.edits)
+ .toList();
+
+ // LSP requires that we separate the main edit (changing the color code)
+ // from anything else (imports).
+ final mainEdit =
+ editsForThisFile.singleWhere((edit) => edit.offset == editRange.offset);
+ final otherEdits =
+ editsForThisFile.where((edit) => edit.offset != editRange.offset);
+
+ return ColorPresentation(
+ label: label,
+ textEdit: toTextEdit(unit.lineInfo, mainEdit),
+ additionalTextEdits: otherEdits.isNotEmpty
+ ? otherEdits.map((edit) => toTextEdit(unit.lineInfo, edit)).toList()
+ : null,
+ );
+ }
+
+ /// Builds a list of valid color presentations for the requested color.
Future<ErrorOr<List<ColorPresentation>>> _getPresentations(
ColorPresentationParams params,
ResolvedUnitResult unit,
) async {
// The values in LSP are decimals 0-1 so should be scaled up to 255 that
- // we use internally.
- final colorValue = _colorValueForComponents(
- (params.color.alpha * 255).toInt(),
- (params.color.red * 255).toInt(),
- (params.color.green * 255).toInt(),
- (params.color.blue * 255).toInt(),
- );
-
- final colorValueHex =
- '0x${colorValue.toRadixString(16).toUpperCase().padLeft(8, '0')}';
+ // we use internally (except for opacity is which 0-1).
+ final alpha = (params.color.alpha * 255).toInt();
+ final red = (params.color.red * 255).toInt();
+ final green = (params.color.green * 255).toInt();
+ final blue = (params.color.blue * 255).toInt();
+ final opacity = params.color.alpha;
final editStart = toOffset(unit.lineInfo, params.range.start);
final editEnd = toOffset(unit.lineInfo, params.range.end);
@@ -87,36 +132,38 @@
return success([]);
}
- final builder = ChangeBuilder(session: unit.session);
- await builder.addDartFileEdit(unit.path, (builder) {
- builder.addReplacement(editRange, (builder) {
- builder.writeType(colorType.thisType);
- builder.write('($colorValueHex)');
- });
- });
+ final colorValue = _colorValueForComponents(alpha, red, green, blue);
+ final colorValueHex =
+ '0x${colorValue.toRadixString(16).toUpperCase().padLeft(8, '0')}';
- // We can only apply changes to the same file, so filter any change from the
- // builder to only include this file, otherwise we may corrupt the users
- // source (although hopefully we don't produce edits for other files).
- final editsForThisFile = builder.sourceChange.edits
- .where((edit) => edit.file == unit.path)
- .expand((edit) => edit.edits)
- .toList();
+ final colorFromARGB = await _createColorPresentation(
+ unit,
+ editRange,
+ colorType,
+ 'Color.fromARGB($alpha, $red, $green, $blue)',
+ '.fromARGB($alpha, $red, $green, $blue)',
+ );
- // LSP requires that we separate the main edit (changing the color code)
- // from anything else (imports).
- final mainEdit =
- editsForThisFile.singleWhere((edit) => edit.offset == editRange.offset);
- final otherEdits =
- editsForThisFile.where((edit) => edit.offset != editRange.offset);
+ final colorFromRGBO = await _createColorPresentation(
+ unit,
+ editRange,
+ colorType,
+ 'Color.fromRGBO($red, $green, $blue, $opacity)',
+ '.fromRGBO($red, $green, $blue, $opacity)',
+ );
+
+ final colorDefault = await _createColorPresentation(
+ unit,
+ editRange,
+ colorType,
+ 'Color($colorValueHex)',
+ '($colorValueHex)',
+ );
return success([
- ColorPresentation(
- label: 'Color($colorValueHex)',
- textEdit: toTextEdit(unit.lineInfo, mainEdit),
- additionalTextEdits:
- otherEdits.map((edit) => toTextEdit(unit.lineInfo, edit)).toList(),
- ),
+ colorFromARGB,
+ colorFromRGBO,
+ colorDefault,
]);
}
}
diff --git a/pkg/analysis_server/test/lsp/document_color_test.dart b/pkg/analysis_server/test/lsp/document_color_test.dart
index 12dd16d..55dbf74 100644
--- a/pkg/analysis_server/test/lsp/document_color_test.dart
+++ b/pkg/analysis_server/test/lsp/document_color_test.dart
@@ -17,6 +17,9 @@
@reflectiveTest
class DocumentColorPresentationTest extends AbstractLspAnalysisServerTest {
+ late Range colorRange, importRange;
+ final uiImportUri = 'package:ui/ui.dart';
+
@override
void setUp() {
super.setUp();
@@ -30,45 +33,30 @@
// calling colorPresentation directly to get the new code (and not fetching
// colors already in the file).
const content = '''
-const white = [[]];
+[[]]const white = [[]];
''';
- const expectedMainEdit = '''
-const white = Color(0xFFFFFFFF);
-''';
-
- const expectedAllEdits = '''
-import 'package:ui/ui.dart';
-
-const white = Color(0xFFFFFFFF);
-''';
+ final ranges = rangesFromMarkers(content);
+ importRange = ranges[0];
+ colorRange = ranges[1];
newFile(mainFilePath, content: withoutMarkers(content));
await initialize();
final colorPresentations = await getColorPresentation(
mainFileUri.toString(),
- rangeFromMarkers(content),
+ colorRange,
Color(alpha: 1, red: 1, green: 1, blue: 1),
);
- expect(colorPresentations, hasLength(1));
- final colorPresentation = colorPresentations[0];
- expect(colorPresentation.label, 'Color(0xFFFFFFFF)');
-
- // Test the main edit just replaces the color.
- final contentWithMainEdit = applyTextEdits(
- withoutMarkers(content),
- [colorPresentation.textEdit!],
+ expect(
+ colorPresentations,
+ equals([
+ _color('Color.fromARGB(255, 255, 255, 255)', importUri: uiImportUri),
+ _color('Color.fromRGBO(255, 255, 255, 1)', importUri: uiImportUri),
+ _color('Color(0xFFFFFFFF)', importUri: uiImportUri),
+ ]),
);
- expect(contentWithMainEdit, equals(expectedMainEdit));
-
- // Test all of the edits also adds the import.
- final contentWithAllEdits = applyTextEdits(
- withoutMarkers(content),
- [colorPresentation.textEdit!, ...colorPresentation.additionalTextEdits!],
- );
- expect(contentWithAllEdits, equals(expectedAllEdits));
}
Future<void> test_nonDartFile() async {
@@ -89,21 +77,46 @@
const white = [[Color(0xFFFFFFFF)]];
''';
+ colorRange = rangeFromMarkers(content);
+
newFile(mainFilePath, content: withoutMarkers(content));
await initialize();
final colorPresentations = await getColorPresentation(
mainFileUri.toString(),
- rangeFromMarkers(content),
+ colorRange,
// Send a different color to what's in the source to simulate the user
// having changed in the color picker. This is the one that we should be
// creating a presentation for, not the one in the source.
Color(alpha: 1, red: 1, green: 0, blue: 0),
);
- expect(colorPresentations, hasLength(1));
- final colorPresentation = colorPresentations[0];
- expect(colorPresentation.label, 'Color(0xFFFF0000)');
+ expect(
+ colorPresentations,
+ equals([
+ _color('Color.fromARGB(255, 255, 0, 0)'),
+ _color('Color.fromRGBO(255, 0, 0, 1)'),
+ _color('Color(0xFFFF0000)'),
+ ]),
+ );
+ }
+
+ /// Creates a [ColorPresentation] for comparing against actual results.
+ ColorPresentation _color(
+ String label, {
+ String? colorCode,
+ String? importUri,
+ }) {
+ final edit = TextEdit(range: colorRange, newText: colorCode ?? label);
+ final additionalEdits = importUri != null
+ ? [TextEdit(range: importRange, newText: "import '$importUri';\n\n")]
+ : null;
+
+ return ColorPresentation(
+ label: label,
+ textEdit: edit,
+ additionalTextEdits: additionalEdits,
+ );
}
}
diff --git a/pkg/dart_internal/CHANGELOG.md b/pkg/dart_internal/CHANGELOG.md
index c49fe05..8894fed 100644
--- a/pkg/dart_internal/CHANGELOG.md
+++ b/pkg/dart_internal/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.2.3
+
+- Support the latest Dart SDK.
+
+## 0.2.2
+
+- Support the latest Dart SDK.
+
## 0.2.1
- Support the latest Dart SDK.
diff --git a/tools/VERSION b/tools/VERSION
index 6a1784b..72690ae 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 11
+PRERELEASE 12
PRERELEASE_PATCH 0
\ No newline at end of file