Skip to content

Commit 60e8519

Browse files
scheglovCommit Queue
authored andcommitted
Rewrite test_fileSystem_changeFile_buildFile_legacy
Change-Id: Idb764aa7b2aa36a9191e10d68cb6a2351f986d46 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/339343 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 6dc6ebf commit 60e8519

File tree

2 files changed

+214
-22
lines changed

2 files changed

+214
-22
lines changed

pkg/analysis_server/test/domain_analysis_test.dart

Lines changed: 130 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ import 'package:analysis_server/src/analysis_server.dart';
1111
import 'package:analyzer/file_system/file_system.dart';
1212
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
1313
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
14+
import 'package:analyzer/src/utilities/extensions/file_system.dart';
1415
import 'package:analyzer_plugin/protocol/protocol_common.dart';
1516
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
17+
import 'package:collection/collection.dart';
1618
import 'package:test/test.dart';
1719
import 'package:test_reflective_loader/test_reflective_loader.dart';
1820

1921
import 'analysis_server_base.dart';
2022
import 'mocks.dart';
23+
import 'utils/tree_string_sink.dart';
2124

2225
void main() {
2326
defineReflectiveSuite(() {
@@ -42,9 +45,9 @@ class AnalysisDomainBlazeTest extends _AnalysisDomainTest {
4245
}
4346

4447
Future<void> test_fileSystem_changeFile_buildFile_legacy() async {
45-
// This BUILD file disables null safety.
48+
// Make it a Blaze package.
4649
newBlazeBuildFile(myPackageRootPath, r'''
47-
dart_package(null_safety = False)
50+
# foo
4851
''');
4952

5053
newFile(myPackageTestFilePath, '''
@@ -54,37 +57,54 @@ void f(int? a) {}
5457
await setRoots(included: [myPackageRootPath], excluded: []);
5558
await server.onAnalysisComplete;
5659

57-
// Cannot use `int?` without null safety.
58-
assertHasErrors(myPackageTestFilePath);
60+
// No errors after initial analysis.
61+
assertNotificationsText(r'''
62+
AnalysisErrors
63+
file: /home/dart/my/lib/test.dart
64+
errors: empty
65+
''');
5966

60-
// Stop disabling null safety.
61-
newBlazeBuildFile(myPackageRootPath, '');
67+
// Change BUILD file, nothing interesting.
68+
newBlazeBuildFile(myPackageRootPath, r'''
69+
# bar
70+
''');
6271

6372
await pumpEventQueue(times: 5000);
6473
await server.onAnalysisComplete;
6574

66-
// We have null safety enabled, so no errors.
67-
assertNoErrors(myPackageTestFilePath);
75+
// BUILD file change caused rebuilding analysis contexts.
76+
assertNotificationsText(r'''
77+
AnalysisFlush
78+
/home/dart/my/lib/test.dart
79+
AnalysisErrors
80+
file: /home/dart/my/lib/test.dart
81+
errors: empty
82+
''');
6883
}
6984
}
7085

7186
@reflectiveTest
7287
class AnalysisDomainPubTest extends _AnalysisDomainTest {
7388
Future<void> test_fileSystem_addFile_analysisOptions() async {
7489
deleteTestPackageAnalysisOptionsFile();
75-
var a_path = '$testPackageLibPath/a.dart';
76-
var b_path = '$testPackageLibPath/b.dart';
7790

78-
_createFilesWithErrors([a_path, b_path]);
91+
_createFilesWithErrors([
92+
'$testPackageLibPath/a.dart',
93+
'$testPackageLibPath/b.dart',
94+
]);
7995

8096
await setRoots(included: [workspaceRootPath], excluded: []);
8197
await server.onAnalysisComplete;
8298

8399
// Both a.dart and b.dart are analyzed.
84-
_assertAnalyzedFiles(
85-
hasErrors: [a_path, b_path],
86-
notAnalyzed: [],
87-
);
100+
assertNotificationsText(r'''
101+
AnalysisErrors
102+
file: /home/test/lib/a.dart
103+
errors: notEmpty
104+
AnalysisErrors
105+
file: /home/test/lib/b.dart
106+
errors: notEmpty
107+
''');
88108

89109
// Write the options file that excludes b.dart
90110
newAnalysisOptionsYamlFile(testPackageRootPath, r'''
@@ -93,15 +113,21 @@ analyzer:
93113
- lib/b.dart
94114
''');
95115

96-
await pumpEventQueue();
116+
await pumpEventQueue(times: 5000);
97117
await server.onAnalysisComplete;
98118

99-
// Errors for all files were flushed, and only a.dart is reported again.
100-
_assertFlushedResults([a_path, b_path]);
101-
_assertAnalyzedFiles(
102-
hasErrors: [a_path],
103-
notAnalyzed: [b_path],
104-
);
119+
// Errors for all files were flushed, b.dart is not reported.
120+
assertNotificationsText(r'''
121+
AnalysisFlush
122+
/home/test/lib/a.dart
123+
/home/test/lib/b.dart
124+
AnalysisErrors
125+
file: /home/test/analysis_options.yaml
126+
errors: empty
127+
AnalysisErrors
128+
file: /home/test/lib/a.dart
129+
errors: notEmpty
130+
''');
105131
}
106132

107133
Future<void> test_fileSystem_addFile_analysisOptions_analysis() async {
@@ -1681,6 +1707,8 @@ class _AnalysisDomainTest extends PubPackageAnalysisServerTest {
16811707
/// The files for which `analysis.flushResults` was received.
16821708
final List<String> flushResults = [];
16831709

1710+
final List<(String, Object)> notifications = [];
1711+
16841712
void assertHasErrors(String path) {
16851713
path = convertPath(path);
16861714
expect(filesErrors[path], isNotEmpty, reason: path);
@@ -1696,6 +1724,30 @@ class _AnalysisDomainTest extends PubPackageAnalysisServerTest {
16961724
expect(filesErrors[path], isNull, reason: path);
16971725
}
16981726

1727+
void assertNotificationsText(
1728+
String expected, {
1729+
void Function(_NotificationPrinterConfiguration)? configure,
1730+
}) {
1731+
final configuration = _NotificationPrinterConfiguration();
1732+
configure?.call(configuration);
1733+
1734+
final buffer = StringBuffer();
1735+
final sink = TreeStringSink(sink: buffer, indent: '');
1736+
_NotificationPrinter(
1737+
configuration: configuration,
1738+
resourceProvider: resourceProvider,
1739+
sink: sink,
1740+
).writeNotifications(notifications);
1741+
notifications.clear();
1742+
1743+
final actual = buffer.toString();
1744+
if (actual != expected) {
1745+
print('-------- Actual --------');
1746+
print('$actual------------------------');
1747+
}
1748+
expect(actual, expected);
1749+
}
1750+
16991751
void forgetReceivedErrors() {
17001752
filesErrors.clear();
17011753
}
@@ -1704,11 +1756,13 @@ class _AnalysisDomainTest extends PubPackageAnalysisServerTest {
17041756
void processNotification(Notification notification) {
17051757
if (notification.event == ANALYSIS_NOTIFICATION_FLUSH_RESULTS) {
17061758
var decoded = AnalysisFlushResultsParams.fromNotification(notification);
1759+
notifications.add((notification.event, decoded));
17071760
flushResults.addAll(decoded.files);
17081761
decoded.files.forEach(filesErrors.remove);
17091762
}
17101763
if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
17111764
var decoded = AnalysisErrorsParams.fromNotification(notification);
1765+
notifications.add((notification.event, decoded));
17121766
analysisErrorsNotifications.add(decoded);
17131767
filesErrors[decoded.file] = decoded.errors;
17141768
}
@@ -1748,3 +1802,57 @@ class _AnalysisDomainTest extends PubPackageAnalysisServerTest {
17481802
}
17491803
}
17501804
}
1805+
1806+
class _NotificationPrinter {
1807+
final _NotificationPrinterConfiguration configuration;
1808+
final ResourceProvider resourceProvider;
1809+
final TreeStringSink sink;
1810+
1811+
_NotificationPrinter({
1812+
required this.configuration,
1813+
required this.resourceProvider,
1814+
required this.sink,
1815+
});
1816+
1817+
void writeNotifications(List<(String, Object)> notifications) {
1818+
for (final entry in notifications) {
1819+
_writeNotification(entry.$1, entry.$2);
1820+
}
1821+
}
1822+
1823+
void _writelnFile(String path, {String? name}) {
1824+
sink.writeIndentedLine(() {
1825+
if (name != null) {
1826+
sink.write('$name: ');
1827+
}
1828+
final file = resourceProvider.getFile(path);
1829+
sink.write(file.posixPath);
1830+
});
1831+
}
1832+
1833+
void _writeNotification(String event, Object notification) {
1834+
switch (notification) {
1835+
case AnalysisFlushResultsParams():
1836+
final files = notification.files.sorted();
1837+
sink.writeElements('AnalysisFlush', files, _writelnFile);
1838+
case AnalysisErrorsParams():
1839+
sink.writelnWithIndent('AnalysisErrors');
1840+
sink.withIndent(() {
1841+
_writelnFile(name: 'file', notification.file);
1842+
if (configuration.withAnalysisErrorDetails) {
1843+
throw UnimplementedError();
1844+
} else if (notification.errors.isNotEmpty) {
1845+
sink.writelnWithIndent('errors: notEmpty');
1846+
} else {
1847+
sink.writelnWithIndent('errors: empty');
1848+
}
1849+
});
1850+
default:
1851+
throw UnimplementedError('${notification.runtimeType}');
1852+
}
1853+
}
1854+
}
1855+
1856+
class _NotificationPrinterConfiguration {
1857+
bool withAnalysisErrorDetails = false;
1858+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// Wrapper around a [StringSink] for writing tree structures.
6+
class TreeStringSink {
7+
final StringSink _sink;
8+
String _indent = '';
9+
10+
TreeStringSink({
11+
required StringSink sink,
12+
required String indent,
13+
}) : _sink = sink,
14+
_indent = indent;
15+
16+
void withIndent(void Function() f) {
17+
final indent = _indent;
18+
_indent = '$indent ';
19+
f();
20+
_indent = indent;
21+
}
22+
23+
void write(Object object) {
24+
_sink.write(object);
25+
}
26+
27+
void writeElements<T extends Object>(
28+
String name,
29+
List<T> elements,
30+
void Function(T) f,
31+
) {
32+
if (elements.isNotEmpty) {
33+
writelnWithIndent(name);
34+
withIndent(() {
35+
for (var element in elements) {
36+
f(element);
37+
}
38+
});
39+
}
40+
}
41+
42+
Future<void> writeFlags(Map<String, bool> flags) async {
43+
if (flags.values.any((flag) => flag)) {
44+
writeIndentedLine(() {
45+
write('flags:');
46+
for (final entry in flags.entries) {
47+
if (entry.value) {
48+
write(' ${entry.key}');
49+
}
50+
}
51+
});
52+
}
53+
}
54+
55+
void writeIf(bool flag, Object object) {
56+
if (flag) {
57+
write(object);
58+
}
59+
}
60+
61+
void writeIndent() {
62+
_sink.write(_indent);
63+
}
64+
65+
void writeIndentedLine(void Function() f) {
66+
writeIndent();
67+
f();
68+
writeln();
69+
}
70+
71+
void writeln([Object? object = '']) {
72+
_sink.writeln(object);
73+
}
74+
75+
void writelnWithIndent(Object object) {
76+
_sink.write(_indent);
77+
_sink.writeln(object);
78+
}
79+
80+
void writeWithIndent(Object object) {
81+
_sink.write(_indent);
82+
_sink.write(object);
83+
}
84+
}

0 commit comments

Comments
 (0)