[analyzer] Tidy up much benchmark and integration test code:

* Add a type argument to raw `Future` types (typically `Future<void>`)
* Add type arguments to raw `Map` types (typically Map<String, Object?>`)
* Add a type argument to raw `Completer` constructor calls.
* Use collection-elements in more places.
* Replace an implementation of `String.padLeft` and `String.padRight` with
  StringBuffer extension methods that use `String.padLeft` and
  `String.padRight`.
* Rename many `sb` variables to `buffer`, which is more idiomatic.
* Move some StringBuffer helper methods to be extensions on StringBuffer.
* Use constructor tear-offs instead of closures which call a constructor.
* Use single quotes where we can.
* Do not prefix constant names with the letter 'k' [1].
* In IntegrationTestMixin:
  * Rename to `IntegrationTest`, as it is never used as a mixin.
  * Public Stream fields are converted to be getters.
  * Private StreamController fields are initialized at their declaration [2],
    instead of an initialization method.
* Remove empty zero-parameter constructors.

[1] https://dart.dev/guides/language/effective-dart/style#dont-use-prefix-letters
[2] https://dart.dev/guides/language/effective-dart/usage#do-initialize-fields-at-their-declaration-when-possible

Change-Id: I7a923a80d32f74fbecf42a0fa35ae25285994097
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/281874
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Sam Rawlins
2023-02-09 22:41:19 +00:00
committed by Commit Queue
parent adb321a4b8
commit bb9371f255
12 changed files with 241 additions and 316 deletions
+16 -19
View File
@@ -77,9 +77,9 @@ abstract class Benchmark {
bool get needsSetup => false;
Future oneTimeCleanup() => Future.value();
Future<void> oneTimeCleanup() => Future.value();
Future oneTimeSetup() => Future.value();
Future<void> oneTimeSetup() => Future.value();
Future<BenchMarkResult> run({
required String dartSdkPath,
@@ -87,7 +87,7 @@ abstract class Benchmark {
bool verbose = false,
});
Map toJson() =>
Map<String, Object?> toJson() =>
{'id': id, 'description': description, 'enabled': enabled, 'kind': kind};
@override
@@ -106,7 +106,7 @@ class BenchMarkResult {
return BenchMarkResult(kindName, math.min(value, other.value));
}
Map toJson() => {kindName: value};
Map<String, Object?> toJson() => {kindName: value};
@override
String toString() => '$kindName: $value';
@@ -124,35 +124,32 @@ class CompoundBenchMarkResult extends BenchMarkResult {
}
@override
BenchMarkResult combine(BenchMarkResult other) {
BenchMarkResult combine(covariant CompoundBenchMarkResult other) {
BenchMarkResult combine(BenchMarkResult? a, BenchMarkResult? b) {
if (a == null) return b!;
if (b == null) return a;
return a.combine(b);
}
var o = other as CompoundBenchMarkResult;
var combined = CompoundBenchMarkResult(name);
var keys = (<String>{}
..addAll(results.keys)
..addAll(o.results.keys))
.toList();
var keys = {
...results.keys,
...other.results.keys,
}.toList();
for (var key in keys) {
combined.add(key, combine(results[key], o.results[key]));
combined.add(key, combine(results[key], other.results[key]));
}
return combined;
}
@override
Map toJson() {
var m = <String, dynamic>{};
for (var entry in results.entries) {
m['$name-${entry.key}'] = entry.value.toJson();
}
return m;
Map<String, Object?> toJson() {
return {
for (var entry in results.entries)
'$name-${entry.key}': entry.value.toJson(),
};
}
@override
@@ -186,7 +183,7 @@ class ListCommand extends Command {
@override
void run() {
if (argResults!['machine'] as bool) {
var map = <String, dynamic>{
var map = <String, Object?>{
'benchmarks': benchmarks.map((b) => b.toJson()).toList()
};
print(JsonEncoder.withIndent(' ').convert(map));
@@ -13,28 +13,10 @@ import '../../test/integration/support/integration_test_methods.dart';
import '../../test/integration/support/integration_tests.dart';
import 'operation.dart';
final SPACE = ' '.codeUnitAt(0);
void _printColumn(StringBuffer sb, String text, int keyLen,
{bool rightJustified = false}) {
if (!rightJustified) {
sb.write(text);
sb.write(',');
}
for (var i = text.length; i < keyLen; ++i) {
sb.writeCharCode(SPACE);
}
if (rightJustified) {
sb.write(text);
sb.write(',');
}
sb.writeCharCode(SPACE);
}
/// [Driver] launches and manages an instance of analysis server,
/// reads a stream of operations, sends requests to analysis server
/// based upon those operations, and evaluates the results.
class Driver extends IntegrationTestMixin {
class Driver extends IntegrationTest {
/// The amount of time to give the server to respond to a shutdown request
/// before forcibly terminating it.
static const Duration SHUTDOWN_TIMEOUT = Duration(seconds: 5);
@@ -63,30 +45,33 @@ class Driver extends IntegrationTestMixin {
Future<Results> get runComplete => _runCompleter.future;
/// Perform the given operation.
///
/// Return a [Future] that completes when the next operation can be performed,
/// or `null` if the next operation can be performed immediately
Future<void>? perform(Operation op) {
return op.perform(this);
}
/// Send a command to the server. An 'id' will be automatically assigned.
/// The returned [Future] will be completed when the server acknowledges the
/// command with a response. If the server acknowledges the command with a
/// normal (non-error) response, the future will be completed with the
/// 'result' field from the response. If the server acknowledges the command
/// with an error response, the future will be completed with an error.
/// Send a command to the server.
///
/// An 'id' will be automatically assigned. The returned [Future] will be
/// completed when the server acknowledges the command with a response. If
/// the server acknowledges the command with a normal (non-error) response,
/// the future will be completed with the 'result' field from the response.
/// If the server acknowledges the command with an error response, the future
/// will be completed with an error.
Future<Map<String, Object?>?> send(
String method, Map<String, dynamic> params) {
return server.send(method, params);
}
/// Launch the analysis server.
///
/// Return a [Future] that completes when analysis server has started.
Future startServer() async {
Future<void> startServer() async {
logger.log(Level.FINE, 'starting server');
initializeInttestMixin();
server = Server();
var serverConnected = Completer();
var serverConnected = Completer<void>();
onServerConnected.listen((_) {
logger.log(Level.FINE, 'connected to server');
serverConnected.complete();
@@ -107,7 +92,7 @@ class Driver extends IntegrationTestMixin {
}
/// Shutdown the analysis server if it is running.
Future stopServer([Duration timeout = SHUTDOWN_TIMEOUT]) async {
Future<void> stopServer([Duration timeout = SHUTDOWN_TIMEOUT]) async {
if (running) {
logger.log(Level.FINE, 'requesting server shutdown');
// Give the server a short time to comply with the shutdown request; if it
@@ -165,19 +150,19 @@ class Measurement {
var variance = differenceFromMeanSquared / count;
var standardDeviation = sqrt(variance).round();
var sb = StringBuffer();
_printColumn(sb, tag, keyLen);
_printColumn(sb, count.toString(), 6, rightJustified: true);
_printColumn(sb, errorCount.toString(), 6, rightJustified: true);
_printColumn(sb, unexpectedResultCount.toString(), 6, rightJustified: true);
_printDuration(sb, Duration(microseconds: meanTime));
_printDuration(sb, time90th);
_printDuration(sb, time99th);
_printDuration(sb, Duration(microseconds: standardDeviation));
_printDuration(sb, minTime);
_printDuration(sb, maxTime);
_printDuration(sb, Duration(microseconds: totalTimeMicros));
print(sb.toString());
var buffer = StringBuffer();
buffer.writePadRight(tag, keyLen);
buffer.writePadLeft(count.toString(), 6);
buffer.writePadLeft(errorCount.toString(), 6);
buffer.writePadLeft(unexpectedResultCount.toString(), 6);
buffer.writeDuration(Duration(microseconds: meanTime));
buffer.writeDuration(time90th);
buffer.writeDuration(time99th);
buffer.writeDuration(Duration(microseconds: standardDeviation));
buffer.writeDuration(minTime);
buffer.writeDuration(maxTime);
buffer.writeDuration(Duration(microseconds: totalTimeMicros));
print(buffer.toString());
}
void record(bool success, Duration elapsed) {
@@ -190,15 +175,10 @@ class Measurement {
void recordUnexpectedResults() {
++unexpectedResultCount;
}
void _printDuration(StringBuffer sb, Duration duration) {
_printColumn(sb, duration.inMilliseconds.toString(), 15,
rightJustified: true);
}
}
/// [Results] contains information gathered by [Driver]
/// while running the analysis server
/// [Results] contains information gathered by [Driver] while running the
/// analysis server.
class Results {
Map<String, Measurement> measurements = <String, Measurement>{};
@@ -236,7 +216,7 @@ class Results {
}
}
/// TODO(danrubel) *** print warnings if driver caches are not empty ****
// TODO(danrubel): print warnings if driver caches are not empty.
print('''
(1) uxr = UneXpected Results or responses received from the server
@@ -259,31 +239,46 @@ class Results {
measurements[tag]!.recordUnexpectedResults();
}
void _printGroupHeader(String groupName, int keyLen) {
var sb = StringBuffer();
_printColumn(sb, groupName, keyLen);
_printColumn(sb, 'count', 6, rightJustified: true);
_printColumn(sb, 'error', 6, rightJustified: true);
_printColumn(sb, 'uxr(1)', 6, rightJustified: true);
sb.write(' ');
_printColumn(sb, 'mean(2)', 15);
_printColumn(sb, '90th', 15);
_printColumn(sb, '99th', 15);
_printColumn(sb, 'std-dev', 15);
_printColumn(sb, 'minimum', 15);
_printColumn(sb, 'maximum', 15);
_printColumn(sb, 'total', 15);
print(sb.toString());
static void _printGroupHeader(String groupName, int keyLength) {
var buffer = StringBuffer();
buffer.writePadRight(groupName, keyLength);
buffer.writePadLeft('count', 6);
buffer.writePadLeft('error', 6);
buffer.writePadLeft('uxr(1)', 6);
buffer.write(' ');
buffer.writePadRight('mean(2)', 15);
buffer.writePadRight('90th', 15);
buffer.writePadRight('99th', 15);
buffer.writePadRight('std-dev', 15);
buffer.writePadRight('minimum', 15);
buffer.writePadRight('maximum', 15);
buffer.writePadRight('total', 15);
print(buffer.toString());
}
void _printTotals(int keyLen, int totalCount, int totalErrorCount,
static void _printTotals(int keyLength, int totalCount, int totalErrorCount,
int totalUnexpectedResultCount) {
var sb = StringBuffer();
_printColumn(sb, 'Totals', keyLen);
_printColumn(sb, totalCount.toString(), 6, rightJustified: true);
_printColumn(sb, totalErrorCount.toString(), 6, rightJustified: true);
_printColumn(sb, totalUnexpectedResultCount.toString(), 6,
rightJustified: true);
print(sb.toString());
var buffer = StringBuffer();
buffer.writePadRight('Totals', keyLength);
buffer.writePadLeft(totalCount.toString(), 6);
buffer.writePadLeft(totalErrorCount.toString(), 6);
buffer.writePadLeft(totalUnexpectedResultCount.toString(), 6);
print(buffer.toString());
}
}
extension on StringBuffer {
void writeDuration(Duration duration) {
writePadLeft(duration.inMilliseconds.toString(), 15);
}
void writePadLeft(String text, int keyLength) {
write(text.padLeft(keyLength, ' '));
write(' ');
}
void writePadRight(String text, int keyLength) {
write(text.padRight(keyLength, ' '));
write(' ');
}
}
@@ -170,14 +170,14 @@ class ResponseOperation extends Operation {
class StartServerOperation extends Operation {
@override
Future perform(Driver driver) {
Future<void> perform(Driver driver) {
return driver.startServer();
}
}
class WaitForAnalysisCompleteOperation extends Operation {
@override
Future perform(Driver driver) {
Future<void> perform(Driver driver) {
var start = DateTime.now();
driver.logger.log(Level.FINE, 'waiting for analysis to complete');
late StreamSubscription<ServerStatusParams> subscription;
@@ -76,7 +76,7 @@ class AnalysisBenchmark extends Benchmark {
var completionCount = 0;
var stopwatch = Stopwatch()..start();
Future complete(int offset) async {
Future<void> complete(int offset) async {
await test.complete(filePath, offset, isWarmUp: false);
completionCount++;
}
@@ -191,10 +191,10 @@ class ColdAnalysisBenchmark extends Benchmark {
}
class ServerBenchmark {
static final das = ServerBenchmark('analysis-server', 'Analysis Server',
() => AnalysisServerBenchmarkTest());
static final das = ServerBenchmark(
'analysis-server', 'Analysis Server', AnalysisServerBenchmarkTest.new);
static final lsp = ServerBenchmark('lsp-analysis-server',
'LSP Analysis Server', () => LspAnalysisServerBenchmarkTest());
'LSP Analysis Server', LspAnalysisServerBenchmarkTest.new);
final String id;
final String name;
@@ -120,15 +120,15 @@ class CmdLineSeveralProjectsBenchmark extends AbstractCmdLineBenchmark {
@override
List<String> analyzeWhat(bool quick) => quick
? ["meta"]
? ['meta']
: [
"analysis_server",
"analysis_server_client",
"analyzer",
"analyzer_cli",
"analyzer_plugin",
"analyzer_utilities",
"_fe_analyzer_shared",
'analysis_server',
'analysis_server_client',
'analyzer',
'analyzer_cli',
'analyzer_plugin',
'analyzer_utilities',
'_fe_analyzer_shared',
];
}
@@ -144,7 +144,7 @@ class CmdLineSmallFileBenchmark extends AbstractCmdLineBenchmark {
String get workingDir => _tempDir!.path;
@override
List<String> analyzeWhat(bool quick) => ["t.dart"];
List<String> analyzeWhat(bool quick) => ['t.dart'];
@override
void cleanup() {
@@ -154,12 +154,12 @@ class CmdLineSmallFileBenchmark extends AbstractCmdLineBenchmark {
@override
void setup() {
var dir = Directory.systemTemp.createTempSync("analyzer-benchmark");
var file = File.fromUri(dir.uri.resolve("t.dart"));
file.writeAsStringSync("""
var dir = Directory.systemTemp.createTempSync('analyzer-benchmark');
var file = File.fromUri(dir.uri.resolve('t.dart'));
file.writeAsStringSync('''
void main() {
print("Hello, world!");
}""");
}''');
_tempDir = dir;
}
}
@@ -13,12 +13,12 @@ import 'memory_tests.dart';
class FlutterCompletionBenchmark extends Benchmark implements FlutterBenchmark {
static final das = FlutterCompletionBenchmark(
'das',
() => AnalysisServerBenchmarkTest(),
AnalysisServerBenchmarkTest.new,
);
static final lsp = FlutterCompletionBenchmark(
'lsp',
() => LspAnalysisServerBenchmarkTest(),
LspAnalysisServerBenchmarkTest.new,
);
final AbstractBenchmarkTest Function() testConstructor;
@@ -240,20 +240,20 @@ class FlutterCompletionBenchmark extends Benchmark implements FlutterBenchmark {
// Perform warm-up.
// The cold start does not matter.
// The sustained performance is much more important.
const kWarmUpCount = 5;
for (var i = 0; i < kWarmUpCount; i++) {
const warmUpCount = 5;
for (var i = 0; i < warmUpCount; i++) {
await perform(isWarmUp: true);
}
const kRepeatCount = 5;
const repeatCount = 5;
final timer = Stopwatch()..start();
for (var i = 0; i < kRepeatCount; i++) {
for (var i = 0; i < repeatCount; i++) {
await perform(isWarmUp: false);
}
await test.closeFile(filePath);
return timer.elapsedMicroseconds ~/ kRepeatCount;
return timer.elapsedMicroseconds ~/ repeatCount;
}
}
@@ -274,21 +274,21 @@ class ServiceProtocol {
var id = '${++_id}';
var completer = Completer<Map>();
_completers[id] = completer;
var m = <String, dynamic>{
var messageMap = <String, dynamic>{
'jsonrpc': '2.0',
'id': id,
'method': method,
'args': args
'args': args,
'params': args,
};
m['params'] = args;
var message = jsonEncode(m);
var message = jsonEncode(messageMap);
socket.add(message);
return completer.future;
}
Future dispose() => socket.close();
Future<void> dispose() => socket.close();
void _handleMessage(dynamic message) {
void _handleMessage(Object? message) {
if (message is! String) {
return;
}
@@ -27,7 +27,7 @@ class DeleteContextTest extends AbstractAnalysisServerIntegrationTest {
await sendExecutionMapUri(contextId, uri: 'package:test/main.dart');
expect(result.file, pathname);
expect(await sendExecutionDeleteContext(contextId), isNull);
await sendExecutionDeleteContext(contextId);
// After the delete, expect this to fail.
try {
@@ -11,14 +11,14 @@ import 'dart:async';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'integration_tests.dart';
import 'protocol_matchers.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
/// Convenience methods for running integration tests.
abstract class IntegrationTestMixin {
/// Base implementation for running integration tests.
abstract class IntegrationTest {
Server get server;
/// Return the version number of the analysis server.
@@ -39,10 +39,9 @@ abstract class IntegrationTestMixin {
/// this request, but for which a response has not yet been sent, will not be
/// responded to. No further responses or notifications will be sent after
/// the response to this request has been sent.
Future sendServerShutdown() async {
Future<void> sendServerShutdown() async {
var result = await server.send('server.shutdown', null);
outOfTestExpect(result, isNull);
return null;
}
/// Subscribe for services. All previous subscriptions are replaced by the
@@ -57,11 +56,11 @@ abstract class IntegrationTestMixin {
/// subscriptions: List<ServerService>
///
/// A list of the services being subscribed to.
Future sendServerSetSubscriptions(List<ServerService> subscriptions) async {
Future<void> sendServerSetSubscriptions(
List<ServerService> subscriptions) async {
var params = ServerSetSubscriptionsParams(subscriptions).toJson();
var result = await server.send('server.setSubscriptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// Requests cancellation of a request sent by the client by id. This is
@@ -77,11 +76,10 @@ abstract class IntegrationTestMixin {
/// id: String
///
/// The id of the request that should be cancelled.
Future sendServerCancelRequest(String id) async {
Future<void> sendServerCancelRequest(String id) async {
var params = ServerCancelRequestParams(id).toJson();
var result = await server.send('server.cancelRequest', params);
outOfTestExpect(result, isNull);
return null;
}
/// Reports that the server is running. This notification is issued once
@@ -99,10 +97,12 @@ abstract class IntegrationTestMixin {
/// pid: int
///
/// The process id of the analysis server process.
late Stream<ServerConnectedParams> onServerConnected;
late final Stream<ServerConnectedParams> onServerConnected =
_onServerConnected.stream.asBroadcastStream();
/// Stream controller for [onServerConnected].
late StreamController<ServerConnectedParams> _onServerConnected;
final _onServerConnected =
StreamController<ServerConnectedParams>(sync: true);
/// Reports that an unexpected error has occurred while executing the server.
/// This notification is not used for problems with specific requests (which
@@ -127,20 +127,22 @@ abstract class IntegrationTestMixin {
///
/// The stack trace associated with the generation of the error, used for
/// debugging the server.
late Stream<ServerErrorParams> onServerError;
late final Stream<ServerErrorParams> onServerError =
_onServerError.stream.asBroadcastStream();
/// Stream controller for [onServerError].
late StreamController<ServerErrorParams> _onServerError;
final _onServerError = StreamController<ServerErrorParams>(sync: true);
/// The stream of entries describing events happened in the server.
///
/// Parameters
///
/// entry: ServerLogEntry
late Stream<ServerLogParams> onServerLog;
late final Stream<ServerLogParams> onServerLog =
_onServerLog.stream.asBroadcastStream();
/// Stream controller for [onServerLog].
late StreamController<ServerLogParams> _onServerLog;
final _onServerLog = StreamController<ServerLogParams>(sync: true);
/// Reports the current status of the server. Parameters are omitted if there
/// has been no change in the status represented by that parameter.
@@ -163,10 +165,11 @@ abstract class IntegrationTestMixin {
///
/// Note: this status type is deprecated, and is no longer sent by the
/// server.
late Stream<ServerStatusParams> onServerStatus;
late final Stream<ServerStatusParams> onServerStatus =
_onServerStatus.stream.asBroadcastStream();
/// Stream controller for [onServerStatus].
late StreamController<ServerStatusParams> _onServerStatus;
final _onServerStatus = StreamController<ServerStatusParams>(sync: true);
/// Return the errors associated with the given file. If the errors for the
/// given file have not yet been computed, or the most recently computed
@@ -452,10 +455,9 @@ abstract class IntegrationTestMixin {
/// Force re-reading of all potentially changed files, re-resolving of all
/// referenced URIs, and corresponding re-analysis of everything affected in
/// the current analysis roots.
Future sendAnalysisReanalyze() async {
Future<void> sendAnalysisReanalyze() async {
var result = await server.send('analysis.reanalyze', null);
outOfTestExpect(result, isNull);
return null;
}
/// Sets the root paths used to determine which files to analyze. The set of
@@ -509,7 +511,7 @@ abstract class IntegrationTestMixin {
/// their package: URI's resolved using the normal pubspec.yaml mechanism.
/// If this field is absent, or the empty map is specified, that indicates
/// that the normal pubspec.yaml mechanism should always be used.
Future sendAnalysisSetAnalysisRoots(
Future<void> sendAnalysisSetAnalysisRoots(
List<String> included, List<String> excluded,
{Map<String, String>? packageRoots}) async {
var params = AnalysisSetAnalysisRootsParams(included, excluded,
@@ -517,7 +519,6 @@ abstract class IntegrationTestMixin {
.toJson();
var result = await server.send('analysis.setAnalysisRoots', params);
outOfTestExpect(result, isNull);
return null;
}
/// Subscribe for general services (that is, services that are not specific
@@ -533,12 +534,11 @@ abstract class IntegrationTestMixin {
/// subscriptions: List<GeneralAnalysisService>
///
/// A list of the services being subscribed to.
Future sendAnalysisSetGeneralSubscriptions(
Future<void> sendAnalysisSetGeneralSubscriptions(
List<GeneralAnalysisService> subscriptions) async {
var params = AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson();
var result = await server.send('analysis.setGeneralSubscriptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// Set the priority files to the files in the given list. A priority file is
@@ -564,11 +564,10 @@ abstract class IntegrationTestMixin {
/// files: List<FilePath>
///
/// The files that are to be a priority for analysis.
Future sendAnalysisSetPriorityFiles(List<String> files) async {
Future<void> sendAnalysisSetPriorityFiles(List<String> files) async {
var params = AnalysisSetPriorityFilesParams(files).toJson();
var result = await server.send('analysis.setPriorityFiles', params);
outOfTestExpect(result, isNull);
return null;
}
/// Subscribe for services that are specific to individual files. All
@@ -601,12 +600,11 @@ abstract class IntegrationTestMixin {
///
/// A table mapping services to a list of the files being subscribed to the
/// service.
Future sendAnalysisSetSubscriptions(
Future<void> sendAnalysisSetSubscriptions(
Map<AnalysisService, List<String>> subscriptions) async {
var params = AnalysisSetSubscriptionsParams(subscriptions).toJson();
var result = await server.send('analysis.setSubscriptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// Update the content of one or more files. Files that were previously
@@ -647,11 +645,10 @@ abstract class IntegrationTestMixin {
///
/// The options that are to be used to control analysis.
@deprecated
Future sendAnalysisUpdateOptions(AnalysisOptions options) async {
Future<void> sendAnalysisUpdateOptions(AnalysisOptions options) async {
var params = AnalysisUpdateOptionsParams(options).toJson();
var result = await server.send('analysis.updateOptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// Reports the paths of the files that are being analyzed.
@@ -665,10 +662,12 @@ abstract class IntegrationTestMixin {
/// directories: List<FilePath>
///
/// A list of the paths of the files that are being analyzed.
late Stream<AnalysisAnalyzedFilesParams> onAnalysisAnalyzedFiles;
late final Stream<AnalysisAnalyzedFilesParams> onAnalysisAnalyzedFiles =
_onAnalysisAnalyzedFiles.stream.asBroadcastStream();
/// Stream controller for [onAnalysisAnalyzedFiles].
late StreamController<AnalysisAnalyzedFilesParams> _onAnalysisAnalyzedFiles;
final _onAnalysisAnalyzedFiles =
StreamController<AnalysisAnalyzedFilesParams>(sync: true);
/// Reports closing labels relevant to a given file.
///
@@ -691,10 +690,12 @@ abstract class IntegrationTestMixin {
/// constructor/method calls and List arguments that span multiple lines.
/// Note that the ranges that are returned can overlap each other because
/// they may be associated with constructs that can be nested.
late Stream<AnalysisClosingLabelsParams> onAnalysisClosingLabels;
late final Stream<AnalysisClosingLabelsParams> onAnalysisClosingLabels =
_onAnalysisClosingLabels.stream.asBroadcastStream();
/// Stream controller for [onAnalysisClosingLabels].
late StreamController<AnalysisClosingLabelsParams> _onAnalysisClosingLabels;
final _onAnalysisClosingLabels =
StreamController<AnalysisClosingLabelsParams>(sync: true);
/// Reports the errors associated with a given file. The set of errors
/// included in the notification is always a complete list that supersedes
@@ -709,10 +710,11 @@ abstract class IntegrationTestMixin {
/// errors: List<AnalysisError>
///
/// The errors contained in the file.
late Stream<AnalysisErrorsParams> onAnalysisErrors;
late final Stream<AnalysisErrorsParams> onAnalysisErrors =
_onAnalysisErrors.stream.asBroadcastStream();
/// Stream controller for [onAnalysisErrors].
late StreamController<AnalysisErrorsParams> _onAnalysisErrors;
final _onAnalysisErrors = StreamController<AnalysisErrorsParams>(sync: true);
/// Reports that any analysis results that were previously associated with
/// the given files should be considered to be invalid because those files
@@ -732,10 +734,12 @@ abstract class IntegrationTestMixin {
/// files: List<FilePath>
///
/// The files that are no longer being analyzed.
late Stream<AnalysisFlushResultsParams> onAnalysisFlushResults;
late final Stream<AnalysisFlushResultsParams> onAnalysisFlushResults =
_onAnalysisFlushResults.stream.asBroadcastStream();
/// Stream controller for [onAnalysisFlushResults].
late StreamController<AnalysisFlushResultsParams> _onAnalysisFlushResults;
final _onAnalysisFlushResults =
StreamController<AnalysisFlushResultsParams>(sync: true);
/// Reports the folding regions associated with a given file. Folding regions
/// can be nested, but will not be overlapping. Nesting occurs when a
@@ -755,10 +759,12 @@ abstract class IntegrationTestMixin {
/// regions: List<FoldingRegion>
///
/// The folding regions contained in the file.
late Stream<AnalysisFoldingParams> onAnalysisFolding;
late final Stream<AnalysisFoldingParams> onAnalysisFolding =
_onAnalysisFolding.stream.asBroadcastStream();
/// Stream controller for [onAnalysisFolding].
late StreamController<AnalysisFoldingParams> _onAnalysisFolding;
final _onAnalysisFolding =
StreamController<AnalysisFoldingParams>(sync: true);
/// Reports the highlight regions associated with a given file.
///
@@ -779,10 +785,12 @@ abstract class IntegrationTestMixin {
/// some range. Note that the highlight regions that are returned can
/// overlap other highlight regions if there is more than one meaning
/// associated with a particular region.
late Stream<AnalysisHighlightsParams> onAnalysisHighlights;
late final Stream<AnalysisHighlightsParams> onAnalysisHighlights =
_onAnalysisHighlights.stream.asBroadcastStream();
/// Stream controller for [onAnalysisHighlights].
late StreamController<AnalysisHighlightsParams> _onAnalysisHighlights;
final _onAnalysisHighlights =
StreamController<AnalysisHighlightsParams>(sync: true);
/// Reports the classes that are implemented or extended and class members
/// that are implemented or overridden in a file.
@@ -804,10 +812,12 @@ abstract class IntegrationTestMixin {
/// members: List<ImplementedMember>
///
/// The member defined in the file that are implemented or overridden.
late Stream<AnalysisImplementedParams> onAnalysisImplemented;
late final Stream<AnalysisImplementedParams> onAnalysisImplemented =
_onAnalysisImplemented.stream.asBroadcastStream();
/// Stream controller for [onAnalysisImplemented].
late StreamController<AnalysisImplementedParams> _onAnalysisImplemented;
final _onAnalysisImplemented =
StreamController<AnalysisImplementedParams>(sync: true);
/// Reports that the navigation information associated with a region of a
/// single file has become invalid and should be re-requested.
@@ -835,10 +845,12 @@ abstract class IntegrationTestMixin {
/// The delta to be applied to the offsets in information that follows the
/// invalidated region in order to update it so that it doesn't need to be
/// re-requested.
late Stream<AnalysisInvalidateParams> onAnalysisInvalidate;
late final Stream<AnalysisInvalidateParams> onAnalysisInvalidate =
_onAnalysisInvalidate.stream.asBroadcastStream();
/// Stream controller for [onAnalysisInvalidate].
late StreamController<AnalysisInvalidateParams> _onAnalysisInvalidate;
final _onAnalysisInvalidate =
StreamController<AnalysisInvalidateParams>(sync: true);
/// Reports the navigation targets associated with a given file.
///
@@ -871,10 +883,12 @@ abstract class IntegrationTestMixin {
///
/// The files containing navigation targets referenced in the file. They
/// are referenced by NavigationTargets by their index in this array.
late Stream<AnalysisNavigationParams> onAnalysisNavigation;
late final Stream<AnalysisNavigationParams> onAnalysisNavigation =
_onAnalysisNavigation.stream.asBroadcastStream();
/// Stream controller for [onAnalysisNavigation].
late StreamController<AnalysisNavigationParams> _onAnalysisNavigation;
final _onAnalysisNavigation =
StreamController<AnalysisNavigationParams>(sync: true);
/// Reports the occurrences of references to elements within a single file.
///
@@ -891,10 +905,12 @@ abstract class IntegrationTestMixin {
/// occurrences: List<Occurrences>
///
/// The occurrences of references to elements within the file.
late Stream<AnalysisOccurrencesParams> onAnalysisOccurrences;
late final Stream<AnalysisOccurrencesParams> onAnalysisOccurrences =
_onAnalysisOccurrences.stream.asBroadcastStream();
/// Stream controller for [onAnalysisOccurrences].
late StreamController<AnalysisOccurrencesParams> _onAnalysisOccurrences;
final _onAnalysisOccurrences =
StreamController<AnalysisOccurrencesParams>(sync: true);
/// Reports the outline associated with a single file.
///
@@ -923,10 +939,12 @@ abstract class IntegrationTestMixin {
/// outline: Outline
///
/// The outline associated with the file.
late Stream<AnalysisOutlineParams> onAnalysisOutline;
late final Stream<AnalysisOutlineParams> onAnalysisOutline =
_onAnalysisOutline.stream.asBroadcastStream();
/// Stream controller for [onAnalysisOutline].
late StreamController<AnalysisOutlineParams> _onAnalysisOutline;
final _onAnalysisOutline =
StreamController<AnalysisOutlineParams>(sync: true);
/// Reports the overriding members in a file.
///
@@ -943,10 +961,12 @@ abstract class IntegrationTestMixin {
/// overrides: List<Override>
///
/// The overrides associated with the file.
late Stream<AnalysisOverridesParams> onAnalysisOverrides;
late final Stream<AnalysisOverridesParams> onAnalysisOverrides =
_onAnalysisOverrides.stream.asBroadcastStream();
/// Stream controller for [onAnalysisOverrides].
late StreamController<AnalysisOverridesParams> _onAnalysisOverrides;
final _onAnalysisOverrides =
StreamController<AnalysisOverridesParams>(sync: true);
/// Request that completion suggestions for the given offset in the given
/// file be returned.
@@ -1062,12 +1082,11 @@ abstract class IntegrationTestMixin {
/// subscriptions: List<CompletionService>
///
/// A list of the services being subscribed to.
Future sendCompletionSetSubscriptions(
Future<void> sendCompletionSetSubscriptions(
List<CompletionService> subscriptions) async {
var params = CompletionSetSubscriptionsParams(subscriptions).toJson();
var result = await server.send('completion.setSubscriptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// The client can make this request to express interest in certain libraries
@@ -1087,11 +1106,11 @@ abstract class IntegrationTestMixin {
/// suggestions. If one configured path is beneath another, the descendant
/// will override the ancestors' configured libraries of interest.
@deprecated
Future sendCompletionRegisterLibraryPaths(List<LibraryPathSet> paths) async {
Future<void> sendCompletionRegisterLibraryPaths(
List<LibraryPathSet> paths) async {
var params = CompletionRegisterLibraryPathsParams(paths).toJson();
var result = await server.send('completion.registerLibraryPaths', params);
outOfTestExpect(result, isNull);
return null;
}
/// Clients must make this request when the user has selected a completion
@@ -1267,10 +1286,12 @@ abstract class IntegrationTestMixin {
///
/// If an AvailableSuggestion has relevance tags that match more than one
/// IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
late Stream<CompletionResultsParams> onCompletionResults;
late final Stream<CompletionResultsParams> onCompletionResults =
_onCompletionResults.stream.asBroadcastStream();
/// Stream controller for [onCompletionResults].
late StreamController<CompletionResultsParams> _onCompletionResults;
final _onCompletionResults =
StreamController<CompletionResultsParams>(sync: true);
/// Reports the pre-computed, candidate completions from symbols defined in a
/// corresponding library. This notification may be sent multiple times. When
@@ -1290,12 +1311,13 @@ abstract class IntegrationTestMixin {
/// removedLibraries: List<int> (optional)
///
/// A list of library ids that no longer apply.
late Stream<CompletionAvailableSuggestionsParams>
onCompletionAvailableSuggestions;
late final Stream<CompletionAvailableSuggestionsParams>
onCompletionAvailableSuggestions =
_onCompletionAvailableSuggestions.stream.asBroadcastStream();
/// Stream controller for [onCompletionAvailableSuggestions].
late StreamController<CompletionAvailableSuggestionsParams>
_onCompletionAvailableSuggestions;
final _onCompletionAvailableSuggestions =
StreamController<CompletionAvailableSuggestionsParams>(sync: true);
/// Reports existing imports in a library. This notification may be sent
/// multiple times for a library. When a notification is processed, clients
@@ -1310,11 +1332,13 @@ abstract class IntegrationTestMixin {
/// imports: ExistingImports
///
/// The existing imports in the library.
late Stream<CompletionExistingImportsParams> onCompletionExistingImports;
late final Stream<CompletionExistingImportsParams>
onCompletionExistingImports =
_onCompletionExistingImports.stream.asBroadcastStream();
/// Stream controller for [onCompletionExistingImports].
late StreamController<CompletionExistingImportsParams>
_onCompletionExistingImports;
final _onCompletionExistingImports =
StreamController<CompletionExistingImportsParams>(sync: true);
/// Perform a search for references to the element defined or referenced at
/// the given offset in the given file.
@@ -1548,10 +1572,11 @@ abstract class IntegrationTestMixin {
///
/// True if this is that last set of results that will be returned for the
/// indicated search.
late Stream<SearchResultsParams> onSearchResults;
late final Stream<SearchResultsParams> onSearchResults =
_onSearchResults.stream.asBroadcastStream();
/// Stream controller for [onSearchResults].
late StreamController<SearchResultsParams> _onSearchResults;
final _onSearchResults = StreamController<SearchResultsParams>(sync: true);
/// Format the contents of a single file. The currently selected region of
/// text is passed in so that the selection can be preserved across the
@@ -2141,11 +2166,10 @@ abstract class IntegrationTestMixin {
/// id: ExecutionContextId
///
/// The identifier of the execution context that is to be deleted.
Future sendExecutionDeleteContext(String id) async {
Future<void> sendExecutionDeleteContext(String id) async {
var params = ExecutionDeleteContextParams(id).toJson();
var result = await server.send('execution.deleteContext', params);
outOfTestExpect(result, isNull);
return null;
}
/// Request completion suggestions for the given runtime context.
@@ -2306,12 +2330,11 @@ abstract class IntegrationTestMixin {
///
/// A list of the services being subscribed to.
@deprecated
Future sendExecutionSetSubscriptions(
Future<void> sendExecutionSetSubscriptions(
List<ExecutionService> subscriptions) async {
var params = ExecutionSetSubscriptionsParams(subscriptions).toJson();
var result = await server.send('execution.setSubscriptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// Reports information needed to allow a single file to be launched.
@@ -2336,10 +2359,12 @@ abstract class IntegrationTestMixin {
///
/// A list of the Dart files that are referenced by the file. This field is
/// omitted if the file is not an HTML file.
late Stream<ExecutionLaunchDataParams> onExecutionLaunchData;
late final Stream<ExecutionLaunchDataParams> onExecutionLaunchData =
_onExecutionLaunchData.stream.asBroadcastStream();
/// Stream controller for [onExecutionLaunchData].
late StreamController<ExecutionLaunchDataParams> _onExecutionLaunchData;
final _onExecutionLaunchData =
StreamController<ExecutionLaunchDataParams>(sync: true);
/// Return server diagnostics.
///
@@ -2407,11 +2432,10 @@ abstract class IntegrationTestMixin {
/// value: bool
///
/// Enable or disable analytics.
Future sendAnalyticsEnable(bool value) async {
Future<void> sendAnalyticsEnable(bool value) async {
var params = AnalyticsEnableParams(value).toJson();
var result = await server.send('analytics.enable', params);
outOfTestExpect(result, isNull);
return null;
}
/// Send information about client events.
@@ -2432,11 +2456,10 @@ abstract class IntegrationTestMixin {
/// action: String
///
/// The value used to indicate which action was performed.
Future sendAnalyticsSendEvent(String action) async {
Future<void> sendAnalyticsSendEvent(String action) async {
var params = AnalyticsSendEventParams(action).toJson();
var result = await server.send('analytics.sendEvent', params);
outOfTestExpect(result, isNull);
return null;
}
/// Send timing information for client events (e.g. code completions).
@@ -2460,11 +2483,10 @@ abstract class IntegrationTestMixin {
/// millis: int
///
/// The duration of the event in milliseconds.
Future sendAnalyticsSendTiming(String event, int millis) async {
Future<void> sendAnalyticsSendTiming(String event, int millis) async {
var params = AnalyticsSendTimingParams(event, millis).toJson();
var result = await server.send('analytics.sendTiming', params);
outOfTestExpect(result, isNull);
return null;
}
/// Return the description of the widget instance at the given location.
@@ -2578,12 +2600,11 @@ abstract class IntegrationTestMixin {
///
/// A table mapping services to a list of the files being subscribed to the
/// service.
Future sendFlutterSetSubscriptions(
Future<void> sendFlutterSetSubscriptions(
Map<FlutterService, List<String>> subscriptions) async {
var params = FlutterSetSubscriptionsParams(subscriptions).toJson();
var result = await server.send('flutter.setSubscriptions', params);
outOfTestExpect(result, isNull);
return null;
}
/// Reports the Flutter outline associated with a single file.
@@ -2601,76 +2622,11 @@ abstract class IntegrationTestMixin {
/// outline: FlutterOutline
///
/// The outline associated with the file.
late Stream<FlutterOutlineParams> onFlutterOutline;
late final Stream<FlutterOutlineParams> onFlutterOutline =
_onFlutterOutline.stream.asBroadcastStream();
/// Stream controller for [onFlutterOutline].
late StreamController<FlutterOutlineParams> _onFlutterOutline;
/// Initialize the fields in InttestMixin, and ensure that notifications will
/// be handled.
void initializeInttestMixin() {
_onServerConnected = StreamController<ServerConnectedParams>(sync: true);
onServerConnected = _onServerConnected.stream.asBroadcastStream();
_onServerError = StreamController<ServerErrorParams>(sync: true);
onServerError = _onServerError.stream.asBroadcastStream();
_onServerLog = StreamController<ServerLogParams>(sync: true);
onServerLog = _onServerLog.stream.asBroadcastStream();
_onServerStatus = StreamController<ServerStatusParams>(sync: true);
onServerStatus = _onServerStatus.stream.asBroadcastStream();
_onAnalysisAnalyzedFiles =
StreamController<AnalysisAnalyzedFilesParams>(sync: true);
onAnalysisAnalyzedFiles =
_onAnalysisAnalyzedFiles.stream.asBroadcastStream();
_onAnalysisClosingLabels =
StreamController<AnalysisClosingLabelsParams>(sync: true);
onAnalysisClosingLabels =
_onAnalysisClosingLabels.stream.asBroadcastStream();
_onAnalysisErrors = StreamController<AnalysisErrorsParams>(sync: true);
onAnalysisErrors = _onAnalysisErrors.stream.asBroadcastStream();
_onAnalysisFlushResults =
StreamController<AnalysisFlushResultsParams>(sync: true);
onAnalysisFlushResults = _onAnalysisFlushResults.stream.asBroadcastStream();
_onAnalysisFolding = StreamController<AnalysisFoldingParams>(sync: true);
onAnalysisFolding = _onAnalysisFolding.stream.asBroadcastStream();
_onAnalysisHighlights =
StreamController<AnalysisHighlightsParams>(sync: true);
onAnalysisHighlights = _onAnalysisHighlights.stream.asBroadcastStream();
_onAnalysisImplemented =
StreamController<AnalysisImplementedParams>(sync: true);
onAnalysisImplemented = _onAnalysisImplemented.stream.asBroadcastStream();
_onAnalysisInvalidate =
StreamController<AnalysisInvalidateParams>(sync: true);
onAnalysisInvalidate = _onAnalysisInvalidate.stream.asBroadcastStream();
_onAnalysisNavigation =
StreamController<AnalysisNavigationParams>(sync: true);
onAnalysisNavigation = _onAnalysisNavigation.stream.asBroadcastStream();
_onAnalysisOccurrences =
StreamController<AnalysisOccurrencesParams>(sync: true);
onAnalysisOccurrences = _onAnalysisOccurrences.stream.asBroadcastStream();
_onAnalysisOutline = StreamController<AnalysisOutlineParams>(sync: true);
onAnalysisOutline = _onAnalysisOutline.stream.asBroadcastStream();
_onAnalysisOverrides =
StreamController<AnalysisOverridesParams>(sync: true);
onAnalysisOverrides = _onAnalysisOverrides.stream.asBroadcastStream();
_onCompletionResults =
StreamController<CompletionResultsParams>(sync: true);
onCompletionResults = _onCompletionResults.stream.asBroadcastStream();
_onCompletionAvailableSuggestions =
StreamController<CompletionAvailableSuggestionsParams>(sync: true);
onCompletionAvailableSuggestions =
_onCompletionAvailableSuggestions.stream.asBroadcastStream();
_onCompletionExistingImports =
StreamController<CompletionExistingImportsParams>(sync: true);
onCompletionExistingImports =
_onCompletionExistingImports.stream.asBroadcastStream();
_onSearchResults = StreamController<SearchResultsParams>(sync: true);
onSearchResults = _onSearchResults.stream.asBroadcastStream();
_onExecutionLaunchData =
StreamController<ExecutionLaunchDataParams>(sync: true);
onExecutionLaunchData = _onExecutionLaunchData.stream.asBroadcastStream();
_onFlutterOutline = StreamController<FlutterOutlineParams>(sync: true);
onFlutterOutline = _onFlutterOutline.stream.asBroadcastStream();
}
final _onFlutterOutline = StreamController<FlutterOutlineParams>(sync: true);
/// Dispatch the notification named [event], and containing parameters
/// [params], to the appropriate stream.
@@ -79,8 +79,7 @@ typedef MismatchDescriber = Description Function(
typedef NotificationProcessor = void Function(String event, Map params);
/// Base class for analysis server integration tests.
abstract class AbstractAnalysisServerIntegrationTest
extends IntegrationTestMixin {
abstract class AbstractAnalysisServerIntegrationTest extends IntegrationTest {
/// Amount of time to give the server to respond to a shutdown request before
/// forcibly terminating it.
static const Duration SHUTDOWN_TIMEOUT = Duration(seconds: 60);
@@ -110,10 +109,6 @@ abstract class AbstractAnalysisServerIntegrationTest
String dartSdkPath = path.dirname(path.dirname(Platform.resolvedExecutable));
AbstractAnalysisServerIntegrationTest() {
initializeInttestMixin();
}
/// Return a future which will complete when a 'server.status' notification is
/// received from the server with 'analyzing' set to false.
///
@@ -609,7 +604,7 @@ class Server {
/// Start the server. If [profileServer] is `true`, the server will be started
/// with "--observe" and "--pause-isolates-on-exit", allowing the observatory
/// to be used.
Future start({
Future<void> start({
required String dartSdkPath,
int? diagnosticPort,
String? instrumentationLogFile,
@@ -96,7 +96,7 @@ class TimingResult {
/// The abstract class [TimingTest] defines the behavior of objects that measure
/// the time required to perform some sequence of server operations.
abstract class TimingTest extends IntegrationTestMixin {
abstract class TimingTest extends IntegrationTest {
/// The number of times the test will be performed in order to warm up the VM.
static final int DEFAULT_WARMUP_COUNT = 10;
@@ -125,9 +125,6 @@ abstract class TimingTest extends IntegrationTestMixin {
/// shutdown.
bool skipShutdown = false;
/// Initialize a newly created test.
TimingTest();
/// Return the number of iterations that should be performed in order to
/// compute a time.
int get timingCount => DEFAULT_TIMING_COUNT;
@@ -138,11 +135,10 @@ abstract class TimingTest extends IntegrationTestMixin {
/// Perform any operations that need to be performed once before any
/// iterations.
Future oneTimeSetUp() {
initializeInttestMixin();
Future<void> oneTimeSetUp() {
server = Server();
sourceDirectory = Directory.systemTemp.createTempSync('analysisServer');
var serverConnected = Completer();
var serverConnected = Completer<void>();
onServerConnected.listen((_) {
serverConnected.complete();
});
@@ -159,7 +155,7 @@ abstract class TimingTest extends IntegrationTestMixin {
/// Perform any operations that need to be performed once after all
/// iterations.
Future oneTimeTearDown() {
Future<void> oneTimeTearDown() {
return _shutdownIfNeeded().then((_) {
sourceDirectory.deleteSync(recursive: true);
});
@@ -213,7 +209,7 @@ abstract class TimingTest extends IntegrationTestMixin {
/// Repeatedly execute this test [count] times, adding timing information to
/// the given list of [times] if it is non-`null`.
Future _repeat(int count, List<int>? times) {
Future<void> _repeat(int count, List<int>? times) {
var stopwatch = Stopwatch();
return setUp().then((_) {
stopwatch.start();
@@ -234,7 +230,7 @@ abstract class TimingTest extends IntegrationTestMixin {
}
/// Shut the server down unless [skipShutdown] is `true`.
Future _shutdownIfNeeded() {
Future<void> _shutdownIfNeeded() {
if (skipShutdown) {
return Future.value();
}
@@ -90,32 +90,22 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
writeln("import 'package:$packageName/protocol/protocol_generated.dart';");
writeln(
"import 'package:$packageName/src/protocol/protocol_internal.dart';");
writeln("import 'package:test/test.dart';");
writeln();
writeln("import 'integration_tests.dart';");
writeln("import 'protocol_matchers.dart';");
for (var uri in api.types.importUris) {
write("import '");
write(uri);
writeln("';");
}
writeln("import 'package:test/test.dart';");
writeln();
writeln('/// Convenience methods for running integration tests.');
writeln('abstract class IntegrationTestMixin {');
writeln("import 'integration_tests.dart';");
writeln("import 'protocol_matchers.dart';");
writeln();
writeln('/// Base implementation for running integration tests.');
writeln('abstract class IntegrationTest {');
indent(() {
writeln('Server get server;');
super.visitApi();
writeln();
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.writeln('Initialize the fields in InttestMixin, and');
toHtmlVisitor.writeln('ensure that notifications will be handled.');
}));
writeln('void initializeInttestMixin() {');
indent(() {
write(fieldInitializationCode.join());
});
writeln('}');
writeln();
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.writeln('Dispatch the notification named [event], and');
toHtmlVisitor.writeln('containing parameters [params], to the');
@@ -151,16 +141,13 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
toHtmlVisitor.translateHtml(notification.html);
toHtmlVisitor.describePayload(notification.params, 'Parameters');
}));
writeln('late Stream<$className> $streamName;');
writeln('late final Stream<$className> $streamName = '
'_$streamName.stream.asBroadcastStream();');
writeln();
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.write('Stream controller for [$streamName].');
}));
writeln('late StreamController<$className> _$streamName;');
fieldInitializationCode.add(collectCode(() {
writeln('_$streamName = StreamController<$className>(sync: true);');
writeln('$streamName = _$streamName.stream.asBroadcastStream();');
}));
writeln('final _$streamName = StreamController<$className>(sync: true);');
notificationSwitchContents.add(collectCode(() {
writeln("case '${notification.longEvent}':");
indent(() {
@@ -215,7 +202,7 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
doCapitalize: true);
futureClass = 'Future<$resultClass>';
} else {
futureClass = 'Future';
futureClass = 'Future<void>';
}
writeln('$futureClass $methodName(${args.join(', ')}) async {');
@@ -249,7 +236,6 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
writeln("return $resultClass.fromJson(decoder, 'result', result);");
} else {
writeln('outOfTestExpect(result, isNull);');
writeln('return null;');
}
});
writeln('}');