Add highlighting support for code-as-ui
Change-Id: I5f3b9274ab8ce0ce4259e273c5ea69585467df21
Reviewed-on: https://dart-review.googlesource.com/c/90783
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index 39c1e8e..dddc8b4 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -415,6 +415,20 @@
}
@override
+ void visitCollectionForElement(CollectionForElement node) {
+ computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+ super.visitCollectionForElement(node);
+ }
+
+ @override
+ void visitCollectionIfElement(CollectionIfElement node) {
+ computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+ computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+ super.visitCollectionIfElement(node);
+ }
+
+ @override
void visitConstructorDeclaration(ConstructorDeclaration node) {
computer._addRegion_token(
node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -475,6 +489,18 @@
}
@override
+ void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+ computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
+ super.visitForEachPartsWithDeclaration(node);
+ }
+
+ @override
+ void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+ computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
+ super.visitForEachPartsWithIdentifier(node);
+ }
+
+ @override
void visitForEachStatement(ForEachStatement node) {
computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
@@ -489,6 +515,13 @@
}
@override
+ void visitForStatement2(ForStatement2 node) {
+ computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+ super.visitForStatement2(node);
+ }
+
+ @override
void visitFunctionDeclaration(FunctionDeclaration node) {
computer._addRegion_token(
node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -526,6 +559,7 @@
@override
void visitIfStatement(IfStatement node) {
computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+ computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
super.visitIfStatement(node);
}
@@ -581,6 +615,27 @@
}
@override
+ void visitListLiteral2(ListLiteral2 node) {
+ computer._addRegion_node(node, HighlightRegionType.LITERAL_LIST);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitListLiteral2(node);
+ }
+
+ @override
+ void visitMapForElement(MapForElement node) {
+ computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+ super.visitMapForElement(node);
+ }
+
+ @override
+ void visitMapIfElement(MapIfElement node) {
+ computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+ computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+ super.visitMapIfElement(node);
+ }
+
+ @override
void visitMapLiteral(MapLiteral node) {
computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
@@ -588,6 +643,13 @@
}
@override
+ void visitMapLiteral2(MapLiteral2 node) {
+ computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitMapLiteral2(node);
+ }
+
+ @override
void visitMethodDeclaration(MethodDeclaration node) {
computer._addRegion_token(
node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -652,6 +714,20 @@
}
@override
+ void visitSetLiteral(SetLiteral node) {
+// computer._addRegion_node(node, HighlightRegionType.LITERAL_SET);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitSetLiteral(node);
+ }
+
+ @override
+ void visitSetLiteral2(SetLiteral2 node) {
+// computer._addRegion_node(node, HighlightRegionType.LITERAL_SET);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitSetLiteral2(node);
+ }
+
+ @override
void visitShowCombinator(ShowCombinator node) {
computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
super.visitShowCombinator(node);
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
index 6ae85e2..aaea61e 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
@@ -506,6 +506,20 @@
}
@override
+ void visitCollectionForElement(CollectionForElement node) {
+ computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+ super.visitCollectionForElement(node);
+ }
+
+ @override
+ void visitCollectionIfElement(CollectionIfElement node) {
+ computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+ computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+ super.visitCollectionIfElement(node);
+ }
+
+ @override
void visitConstructorDeclaration(ConstructorDeclaration node) {
computer._addRegion_token(
node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -566,6 +580,18 @@
}
@override
+ void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+ computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
+ super.visitForEachPartsWithDeclaration(node);
+ }
+
+ @override
+ void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+ computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
+ super.visitForEachPartsWithIdentifier(node);
+ }
+
+ @override
void visitForEachStatement(ForEachStatement node) {
computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
@@ -580,6 +606,13 @@
}
@override
+ void visitForStatement2(ForStatement2 node) {
+ computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+ super.visitForStatement2(node);
+ }
+
+ @override
void visitFunctionDeclaration(FunctionDeclaration node) {
computer._addRegion_token(
node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -617,6 +650,7 @@
@override
void visitIfStatement(IfStatement node) {
computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+ computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
super.visitIfStatement(node);
}
@@ -678,6 +712,27 @@
}
@override
+ void visitListLiteral2(ListLiteral2 node) {
+ computer._addRegion_node(node, HighlightRegionType.LITERAL_LIST);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitListLiteral2(node);
+ }
+
+ @override
+ void visitMapForElement(MapForElement node) {
+ computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+ super.visitMapForElement(node);
+ }
+
+ @override
+ void visitMapIfElement(MapIfElement node) {
+ computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+ computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+ super.visitMapIfElement(node);
+ }
+
+ @override
void visitMapLiteral(MapLiteral node) {
computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
@@ -685,6 +740,13 @@
}
@override
+ void visitMapLiteral2(MapLiteral2 node) {
+ computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitMapLiteral2(node);
+ }
+
+ @override
void visitMethodDeclaration(MethodDeclaration node) {
computer._addRegion_token(
node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -749,6 +811,20 @@
}
@override
+ void visitSetLiteral(SetLiteral node) {
+// computer._addRegion_node(node, HighlightRegionType.LITERAL_SET);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitSetLiteral(node);
+ }
+
+ @override
+ void visitSetLiteral2(SetLiteral2 node) {
+// computer._addRegion_node(node, HighlightRegionType.LITERAL_SET);
+ computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
+ super.visitSetLiteral2(node);
+ }
+
+ @override
void visitShowCombinator(ShowCombinator node) {
computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
super.visitShowCombinator(node);
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 1046cbe..88972ed 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -16,102 +16,13 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisNotificationHighlightsTest);
+ defineReflectiveTests(HighlightsWithControlFlowCollectionsTest);
defineReflectiveTests(HighlightTypeTest);
});
}
@reflectiveTest
-class AnalysisNotificationHighlightsTest extends AbstractAnalysisTest {
- List<HighlightRegion> regions;
-
- Completer _resultsAvailable = new Completer();
-
- void assertHasRawRegion(HighlightRegionType type, int offset, int length) {
- for (HighlightRegion region in regions) {
- if (region.offset == offset &&
- region.length == length &&
- region.type == type) {
- return;
- }
- }
- fail('Expected to find (offset=$offset; length=$length; type=$type) in\n'
- '${regions.join('\n')}');
- }
-
- void assertHasRegion(HighlightRegionType type, String search,
- [int length = -1]) {
- int offset = findOffset(search);
- length = findRegionLength(search, length);
- assertHasRawRegion(type, offset, length);
- }
-
- void assertHasStringRegion(HighlightRegionType type, String str) {
- int offset = findOffset(str);
- int length = str.length;
- assertHasRawRegion(type, offset, length);
- }
-
- void assertNoRawRegion(HighlightRegionType type, int offset, int length) {
- for (HighlightRegion region in regions) {
- if (region.offset == offset &&
- region.length == length &&
- region.type == type) {
- fail(
- 'Not expected to find (offset=$offset; length=$length; type=$type) in\n'
- '${regions.join('\n')}');
- }
- }
- }
-
- void assertNoRegion(HighlightRegionType type, String search,
- [int length = -1]) {
- int offset = findOffset(search);
- length = findRegionLength(search, length);
- assertNoRawRegion(type, offset, length);
- }
-
- int findRegionLength(String search, int length) {
- if (length == -1) {
- length = 0;
- while (length < search.length) {
- int c = search.codeUnitAt(length);
- if (length == 0 && c == '@'.codeUnitAt(0)) {
- length++;
- continue;
- }
- if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
- c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
- c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
- break;
- }
- length++;
- }
- }
- return length;
- }
-
- Future prepareHighlights() {
- addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
- return _resultsAvailable.future;
- }
-
- void processNotification(Notification notification) {
- if (notification.event == ANALYSIS_NOTIFICATION_HIGHLIGHTS) {
- var params = new AnalysisHighlightsParams.fromNotification(notification);
- if (params.file == testFile) {
- regions = params.regions;
- _resultsAvailable.complete(null);
- }
- }
- }
-
- @override
- void setUp() {
- super.setUp();
- server.options.useAnalysisHighlight2 = true;
- createProject();
- }
-
+class AnalysisNotificationHighlightsTest extends HighlightsTestSupport {
test_ANNOTATION_hasArguments() async {
addTestFile('''
class AAA {
@@ -791,6 +702,17 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'with A;');
}
+ test_KEYWORD_ifElse_statement() async {
+ addTestFile('''
+f(a, b) {
+ if (a < b) {} else {}
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
test_KEYWORD_mixin() async {
addTestFile('''
mixin M {}
@@ -1122,6 +1044,98 @@
assertHasRegion(type, 'unresolved(2)');
assertHasRegion(type, 'unresolved(3)');
}
+}
+
+class HighlightsTestSupport extends AbstractAnalysisTest {
+ List<HighlightRegion> regions;
+
+ Completer _resultsAvailable = new Completer();
+
+ void assertHasRawRegion(HighlightRegionType type, int offset, int length) {
+ for (HighlightRegion region in regions) {
+ if (region.offset == offset &&
+ region.length == length &&
+ region.type == type) {
+ return;
+ }
+ }
+ fail('Expected to find (offset=$offset; length=$length; type=$type) in\n'
+ '${regions.join('\n')}');
+ }
+
+ void assertHasRegion(HighlightRegionType type, String search,
+ [int length = -1]) {
+ int offset = findOffset(search);
+ length = findRegionLength(search, length);
+ assertHasRawRegion(type, offset, length);
+ }
+
+ void assertHasStringRegion(HighlightRegionType type, String str) {
+ int offset = findOffset(str);
+ int length = str.length;
+ assertHasRawRegion(type, offset, length);
+ }
+
+ void assertNoRawRegion(HighlightRegionType type, int offset, int length) {
+ for (HighlightRegion region in regions) {
+ if (region.offset == offset &&
+ region.length == length &&
+ region.type == type) {
+ fail(
+ 'Not expected to find (offset=$offset; length=$length; type=$type) in\n'
+ '${regions.join('\n')}');
+ }
+ }
+ }
+
+ void assertNoRegion(HighlightRegionType type, String search,
+ [int length = -1]) {
+ int offset = findOffset(search);
+ length = findRegionLength(search, length);
+ assertNoRawRegion(type, offset, length);
+ }
+
+ int findRegionLength(String search, int length) {
+ if (length == -1) {
+ length = 0;
+ while (length < search.length) {
+ int c = search.codeUnitAt(length);
+ if (length == 0 && c == '@'.codeUnitAt(0)) {
+ length++;
+ continue;
+ }
+ if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
+ c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
+ c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
+ break;
+ }
+ length++;
+ }
+ }
+ return length;
+ }
+
+ Future prepareHighlights() {
+ addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
+ return _resultsAvailable.future;
+ }
+
+ void processNotification(Notification notification) {
+ if (notification.event == ANALYSIS_NOTIFICATION_HIGHLIGHTS) {
+ var params = new AnalysisHighlightsParams.fromNotification(notification);
+ if (params.file == testFile) {
+ regions = params.regions;
+ _resultsAvailable.complete(null);
+ }
+ }
+ }
+
+ @override
+ void setUp() {
+ super.setUp();
+ server.options.useAnalysisHighlight2 = true;
+ createProject();
+ }
void _addLibraryForTestPart() {
newFile(join(testFolder, 'my_lib.dart'), content: '''
@@ -1132,6 +1146,163 @@
}
@reflectiveTest
+class HighlightsWithControlFlowCollectionsTest extends HighlightsTestSupport {
+ @override
+ void createProject({Map<String, String> packageRoots}) {
+ addAnalysisOptionsFile('''
+analyzer:
+ enable-experiment:
+ - control-flow-collections
+''');
+ super.createProject(packageRoots: packageRoots);
+ }
+
+ @failingTest
+ test_KEYWORD_awaitForIn_list() async {
+ addTestFile('''
+f(a) async {
+ return [await for(var b in a) b];
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'await');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+ }
+
+ @failingTest
+ test_KEYWORD_awaitForIn_map() async {
+ addTestFile('''
+f(a, b) async {
+ return {await for(var b in a) b};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'await');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+ }
+
+ @failingTest
+ test_KEYWORD_awaitForIn_set() async {
+ addTestFile('''
+f(a, b) async {
+ return {await for(var b in a) b};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'await');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+ }
+
+ test_KEYWORD_const_list() async {
+ addTestFile('''
+var v = const [];
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+ }
+
+ test_KEYWORD_const_map() async {
+ addTestFile('''
+var v = const {0 : 1};
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+ }
+
+ test_KEYWORD_const_set() async {
+ addTestFile('''
+var v = const {0};
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+ }
+
+ test_KEYWORD_if_list() async {
+ addTestFile('''
+f(a, b) {
+ return [if (a < b) 'a'];
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ }
+
+ @failingTest
+ test_KEYWORD_if_map() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a' : 1};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ }
+
+ @failingTest
+ test_KEYWORD_if_set() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a'};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ }
+
+ @failingTest
+ test_KEYWORD_ifElse_list() async {
+ addTestFile('''
+f(a, b) {
+ return [if (a < b) 'a' else 'b'];
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
+ @failingTest
+ test_KEYWORD_ifElse_map() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a' : 1 else 'b' : 2};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
+ @failingTest
+ test_KEYWORD_ifElse_set() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a' else 'b'};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
+ test_LITERAL_LIST() async {
+ addTestFile('var V = <int>[1, 2, 3];');
+ await prepareHighlights();
+ assertHasStringRegion(HighlightRegionType.LITERAL_LIST, '<int>[1, 2, 3]');
+ }
+
+ test_LITERAL_MAP() async {
+ addTestFile("var V = const <int, String>{1: 'a', 2: 'b', 3: 'c'};");
+ await prepareHighlights();
+ assertHasStringRegion(HighlightRegionType.LITERAL_MAP,
+ "const <int, String>{1: 'a', 2: 'b', 3: 'c'}");
+ }
+}
+
+@reflectiveTest
class HighlightTypeTest {
void test_constructor() {
expect(HighlightRegionType.CLASS,
diff --git a/pkg/analysis_server/test/analysis/notification_highlights_test.dart b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
index 030addf..7d0fba2 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
@@ -16,101 +16,13 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisNotificationHighlightsTest);
+ defineReflectiveTests(HighlightsWithControlFlowCollectionsTest);
defineReflectiveTests(HighlightTypeTest);
});
}
@reflectiveTest
-class AnalysisNotificationHighlightsTest extends AbstractAnalysisTest {
- List<HighlightRegion> regions;
-
- Completer _resultsAvailable = new Completer();
-
- void assertHasRawRegion(HighlightRegionType type, int offset, int length) {
- for (HighlightRegion region in regions) {
- if (region.offset == offset &&
- region.length == length &&
- region.type == type) {
- return;
- }
- }
- fail('Expected to find (offset=$offset; length=$length; type=$type) in\n'
- '${regions.join('\n')}');
- }
-
- void assertHasRegion(HighlightRegionType type, String search,
- [int length = -1]) {
- int offset = findOffset(search);
- length = findRegionLength(search, length);
- assertHasRawRegion(type, offset, length);
- }
-
- void assertHasStringRegion(HighlightRegionType type, String str) {
- int offset = findOffset(str);
- int length = str.length;
- assertHasRawRegion(type, offset, length);
- }
-
- void assertNoRawRegion(HighlightRegionType type, int offset, int length) {
- for (HighlightRegion region in regions) {
- if (region.offset == offset &&
- region.length == length &&
- region.type == type) {
- fail(
- 'Not expected to find (offset=$offset; length=$length; type=$type) in\n'
- '${regions.join('\n')}');
- }
- }
- }
-
- void assertNoRegion(HighlightRegionType type, String search,
- [int length = -1]) {
- int offset = findOffset(search);
- length = findRegionLength(search, length);
- assertNoRawRegion(type, offset, length);
- }
-
- int findRegionLength(String search, int length) {
- if (length == -1) {
- length = 0;
- while (length < search.length) {
- int c = search.codeUnitAt(length);
- if (length == 0 && c == '@'.codeUnitAt(0)) {
- length++;
- continue;
- }
- if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
- c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
- c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
- break;
- }
- length++;
- }
- }
- return length;
- }
-
- Future prepareHighlights() {
- addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
- return _resultsAvailable.future;
- }
-
- void processNotification(Notification notification) {
- if (notification.event == ANALYSIS_NOTIFICATION_HIGHLIGHTS) {
- var params = new AnalysisHighlightsParams.fromNotification(notification);
- if (params.file == testFile) {
- regions = params.regions;
- _resultsAvailable.complete(null);
- }
- }
- }
-
- @override
- void setUp() {
- super.setUp();
- createProject();
- }
-
+class AnalysisNotificationHighlightsTest extends HighlightsTestSupport {
test_ANNOTATION_hasArguments() async {
addTestFile('''
class AAA {
@@ -781,6 +693,17 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'with A;');
}
+ test_KEYWORD_ifElse_statement() async {
+ addTestFile('''
+f(a, b) {
+ if (a < b) {} else {}
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
test_KEYWORD_mixin() async {
addTestFile('''
mixin M {}
@@ -971,6 +894,97 @@
assertHasRegion(HighlightRegionType.TYPE_PARAMETER, 'T mmm(');
assertHasRegion(HighlightRegionType.TYPE_PARAMETER, 'T p)');
}
+}
+
+class HighlightsTestSupport extends AbstractAnalysisTest {
+ List<HighlightRegion> regions;
+
+ Completer _resultsAvailable = new Completer();
+
+ void assertHasRawRegion(HighlightRegionType type, int offset, int length) {
+ for (HighlightRegion region in regions) {
+ if (region.offset == offset &&
+ region.length == length &&
+ region.type == type) {
+ return;
+ }
+ }
+ fail('Expected to find (offset=$offset; length=$length; type=$type) in\n'
+ '${regions.join('\n')}');
+ }
+
+ void assertHasRegion(HighlightRegionType type, String search,
+ [int length = -1]) {
+ int offset = findOffset(search);
+ length = findRegionLength(search, length);
+ assertHasRawRegion(type, offset, length);
+ }
+
+ void assertHasStringRegion(HighlightRegionType type, String str) {
+ int offset = findOffset(str);
+ int length = str.length;
+ assertHasRawRegion(type, offset, length);
+ }
+
+ void assertNoRawRegion(HighlightRegionType type, int offset, int length) {
+ for (HighlightRegion region in regions) {
+ if (region.offset == offset &&
+ region.length == length &&
+ region.type == type) {
+ fail(
+ 'Not expected to find (offset=$offset; length=$length; type=$type) in\n'
+ '${regions.join('\n')}');
+ }
+ }
+ }
+
+ void assertNoRegion(HighlightRegionType type, String search,
+ [int length = -1]) {
+ int offset = findOffset(search);
+ length = findRegionLength(search, length);
+ assertNoRawRegion(type, offset, length);
+ }
+
+ int findRegionLength(String search, int length) {
+ if (length == -1) {
+ length = 0;
+ while (length < search.length) {
+ int c = search.codeUnitAt(length);
+ if (length == 0 && c == '@'.codeUnitAt(0)) {
+ length++;
+ continue;
+ }
+ if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
+ c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
+ c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
+ break;
+ }
+ length++;
+ }
+ }
+ return length;
+ }
+
+ Future prepareHighlights() {
+ addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
+ return _resultsAvailable.future;
+ }
+
+ void processNotification(Notification notification) {
+ if (notification.event == ANALYSIS_NOTIFICATION_HIGHLIGHTS) {
+ var params = new AnalysisHighlightsParams.fromNotification(notification);
+ if (params.file == testFile) {
+ regions = params.regions;
+ _resultsAvailable.complete(null);
+ }
+ }
+ }
+
+ @override
+ void setUp() {
+ super.setUp();
+ createProject();
+ }
void _addLibraryForTestPart() {
newFile(join(testFolder, 'my_lib.dart'), content: '''
@@ -981,6 +995,163 @@
}
@reflectiveTest
+class HighlightsWithControlFlowCollectionsTest extends HighlightsTestSupport {
+ @override
+ void createProject({Map<String, String> packageRoots}) {
+ addAnalysisOptionsFile('''
+analyzer:
+ enable-experiment:
+ - control-flow-collections
+''');
+ super.createProject(packageRoots: packageRoots);
+ }
+
+ @failingTest
+ test_KEYWORD_awaitForIn_list() async {
+ addTestFile('''
+f(a) async {
+ return [await for(var b in a) b];
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'await');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+ }
+
+ @failingTest
+ test_KEYWORD_awaitForIn_map() async {
+ addTestFile('''
+f(a, b) async {
+ return {await for(var b in a) b};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'await');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+ }
+
+ @failingTest
+ test_KEYWORD_awaitForIn_set() async {
+ addTestFile('''
+f(a, b) async {
+ return {await for(var b in a) b};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'await');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+ }
+
+ test_KEYWORD_const_list() async {
+ addTestFile('''
+var v = const [];
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+ }
+
+ test_KEYWORD_const_map() async {
+ addTestFile('''
+var v = const {0 : 1};
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+ }
+
+ test_KEYWORD_const_set() async {
+ addTestFile('''
+var v = const {0};
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+ }
+
+ test_KEYWORD_if_list() async {
+ addTestFile('''
+f(a, b) {
+ return [if (a < b) 'a'];
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ }
+
+ @failingTest
+ test_KEYWORD_if_map() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a' : 1};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ }
+
+ @failingTest
+ test_KEYWORD_if_set() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a'};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ }
+
+ @failingTest
+ test_KEYWORD_ifElse_list() async {
+ addTestFile('''
+f(a, b) {
+ return [if (a < b) 'a' else 'b'];
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
+ @failingTest
+ test_KEYWORD_ifElse_map() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a' : 1 else 'b' : 2};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
+ @failingTest
+ test_KEYWORD_ifElse_set() async {
+ addTestFile('''
+f(a, b) {
+ return {if (a < b) 'a' else 'b'};
+}
+''');
+ await prepareHighlights();
+ assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+ assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+ }
+
+ test_LITERAL_LIST_withControlFlow() async {
+ addTestFile('var V = <int>[1, 2, 3];');
+ await prepareHighlights();
+ assertHasStringRegion(HighlightRegionType.LITERAL_LIST, '<int>[1, 2, 3]');
+ }
+
+ test_LITERAL_MAP_withControlFlow() async {
+ addTestFile("var V = const <int, String>{1: 'a', 2: 'b', 3: 'c'};");
+ await prepareHighlights();
+ assertHasStringRegion(HighlightRegionType.LITERAL_MAP,
+ "const <int, String>{1: 'a', 2: 'b', 3: 'c'}");
+ }
+}
+
+@reflectiveTest
class HighlightTypeTest {
void test_constructor() {
expect(HighlightRegionType.CLASS,
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 8415bc9..6135864 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -73,6 +73,12 @@
AnalysisDriver get testDiver => server.getAnalysisDriver(testFile);
+ void addAnalysisOptionsFile(String content) {
+ newFile(
+ resourceProvider.pathContext.join(projectPath, 'analysis_options.yaml'),
+ content: content);
+ }
+
void addAnalysisSubscription(AnalysisService service, String file) {
// add file to subscription
var files = analysisSubscriptions[service];