mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 07:19:58 +00:00
[pkg/vm_service] use package:lints/recommended.yaml
Change-Id: Icf2b33ed47c5006c72bb4809fca230845cf51908 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/282383 Reviewed-by: Ben Konyi <bkonyi@google.com> Commit-Queue: Devon Carew <devoncarew@google.com>
This commit is contained in:
parent
f0362507f0
commit
5a53de5b14
|
@ -1,4 +1,4 @@
|
|||
include: package:lints/core.yaml
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
|
|
|
@ -38,7 +38,7 @@ void main(List<String> args) {
|
|||
}
|
||||
|
||||
void foo(int val) {
|
||||
print('val: ${val}');
|
||||
print('val: $val');
|
||||
}
|
||||
|
||||
class Bar extends FooBar {
|
||||
|
|
|
@ -29,19 +29,19 @@ void main() {
|
|||
test('integration', () async {
|
||||
String sdk = path.dirname(path.dirname(Platform.resolvedExecutable));
|
||||
|
||||
print('Using sdk at ${sdk}.');
|
||||
print('Using sdk at $sdk.');
|
||||
|
||||
// pause_isolates_on_start, pause_isolates_on_exit
|
||||
process = await Process.start('${sdk}/bin/dart', [
|
||||
process = await Process.start('$sdk/bin/dart', [
|
||||
'--pause_isolates_on_start',
|
||||
'--enable-vm-service=${port}',
|
||||
'--enable-vm-service=$port',
|
||||
'--disable-service-auth-codes',
|
||||
'example/sample_main.dart'
|
||||
]);
|
||||
|
||||
print('dart process started');
|
||||
|
||||
process!.exitCode.then((code) => print('vm exited: ${code}'));
|
||||
process!.exitCode.then((code) => print('vm exited: $code'));
|
||||
process!.stdout.transform(utf8.decoder).listen(print);
|
||||
process!.stderr.transform(utf8.decoder).listen(print);
|
||||
|
||||
|
@ -52,13 +52,13 @@ void main() {
|
|||
|
||||
print('socket connected');
|
||||
|
||||
serviceClient.onSend.listen((str) => print('--> ${str}'));
|
||||
serviceClient.onSend.listen((str) => print('--> $str'));
|
||||
|
||||
// The next listener will bail out if you toggle this to false, which we need
|
||||
// to do for some things like the custom service registration tests.
|
||||
var checkResponseJsonCompatibility = true;
|
||||
serviceClient.onReceive.listen((str) {
|
||||
print('<-- ${str}');
|
||||
print('<-- $str');
|
||||
|
||||
if (!checkResponseJsonCompatibility) return;
|
||||
|
||||
|
@ -94,11 +94,11 @@ void main() {
|
|||
expect(reserializedJson, equals(originalJson));
|
||||
});
|
||||
|
||||
serviceClient.onIsolateEvent.listen((e) => print('onIsolateEvent: ${e}'));
|
||||
serviceClient.onDebugEvent.listen((e) => print('onDebugEvent: ${e}'));
|
||||
serviceClient.onGCEvent.listen((e) => print('onGCEvent: ${e}'));
|
||||
serviceClient.onStdoutEvent.listen((e) => print('onStdoutEvent: ${e}'));
|
||||
serviceClient.onStderrEvent.listen((e) => print('onStderrEvent: ${e}'));
|
||||
serviceClient.onIsolateEvent.listen((e) => print('onIsolateEvent: $e'));
|
||||
serviceClient.onDebugEvent.listen((e) => print('onDebugEvent: $e'));
|
||||
serviceClient.onGCEvent.listen((e) => print('onGCEvent: $e'));
|
||||
serviceClient.onStdoutEvent.listen((e) => print('onStdoutEvent: $e'));
|
||||
serviceClient.onStderrEvent.listen((e) => print('onStderrEvent: $e'));
|
||||
|
||||
unawaited(serviceClient.streamListen(EventStreams.kIsolate));
|
||||
unawaited(serviceClient.streamListen(EventStreams.kDebug));
|
||||
|
@ -217,7 +217,9 @@ Future testSourceReport(IsolateRef isolateRef) async {
|
|||
}
|
||||
|
||||
class StdoutLog extends Log {
|
||||
@override
|
||||
void warning(String message) => print(message);
|
||||
|
||||
@override
|
||||
void severe(String message) => print(message);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ void main(List<String> args) {
|
|||
}
|
||||
|
||||
void foo(int val) {
|
||||
print('val: ${val}');
|
||||
print('val: $val');
|
||||
}
|
||||
|
||||
class Bar extends FooBar {
|
||||
|
|
|
@ -34,7 +34,7 @@ void main(List<String> args) {
|
|||
}
|
||||
|
||||
void foo(int val) {
|
||||
print('val: ${val}');
|
||||
print('val: $val');
|
||||
}
|
||||
|
||||
class Bar extends FooBar {
|
||||
|
|
|
@ -11,7 +11,7 @@ import 'vm_service.dart' hide Error;
|
|||
|
||||
extension DartIOExtension on VmService {
|
||||
static bool _factoriesRegistered = false;
|
||||
static Map<String, Version> _isolateVersion = {};
|
||||
static final Map<String, Version> _isolateVersion = {};
|
||||
|
||||
Future<Version> _version(String isolateId) async {
|
||||
Version? version = _isolateVersion[isolateId];
|
||||
|
@ -798,9 +798,11 @@ class SpawnedProcess extends Response implements SpawnedProcessRef {
|
|||
String get type => 'SpawnedProcess';
|
||||
|
||||
/// The unique ID associated with this process.
|
||||
@override
|
||||
final int id;
|
||||
|
||||
/// The name of the executable.
|
||||
@override
|
||||
final String name;
|
||||
|
||||
/// The process ID associated with the process.
|
||||
|
@ -902,9 +904,11 @@ class OpenFile extends Response implements OpenFileRef {
|
|||
String get type => 'OpenFile';
|
||||
|
||||
/// The unique ID associated with this file.
|
||||
@override
|
||||
final int id;
|
||||
|
||||
/// The path of the file.
|
||||
@override
|
||||
final String name;
|
||||
|
||||
/// The total number of bytes read from this file.
|
||||
|
@ -939,6 +943,7 @@ class OpenFileList extends Response {
|
|||
_files = List<OpenFileRef>.from(
|
||||
createServiceObject(json['files'], const ['OpenFileRef']) as List);
|
||||
|
||||
@override
|
||||
String get type => 'OpenFileList';
|
||||
|
||||
/// A list of all files opened through dart:io on a given isolate.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,6 +21,7 @@ class Token {
|
|||
|
||||
bool get isComment => text != null && text!.startsWith('//');
|
||||
|
||||
@override
|
||||
String toString() => text == null ? 'EOF' : text!;
|
||||
}
|
||||
|
||||
|
@ -70,7 +71,7 @@ class Tokenizer {
|
|||
|
||||
void _emit(String? value) {
|
||||
Token token = Token(value);
|
||||
if (_head == null) _head = token;
|
||||
_head ??= token;
|
||||
if (_last != null) _last!.next = token;
|
||||
_last = token;
|
||||
}
|
||||
|
@ -80,16 +81,17 @@ class Tokenizer {
|
|||
return i < text.length ? text[i] : String.fromCharCodes([0]);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
StringBuffer buf = StringBuffer();
|
||||
|
||||
Token t = _head!;
|
||||
|
||||
buf.write('[${t}]\n');
|
||||
buf.write('[$t]\n');
|
||||
|
||||
while (!t.eof) {
|
||||
t = t.next!;
|
||||
buf.write('[${t}]\n');
|
||||
buf.write('[$t]\n');
|
||||
}
|
||||
|
||||
return buf.toString().trim();
|
||||
|
@ -105,7 +107,7 @@ abstract class Parser {
|
|||
|
||||
Token expect(String text) {
|
||||
Token t = advance()!;
|
||||
if (text != t.text) fail('expected ${text}, got ${t}');
|
||||
if (text != t.text) fail('expected $text, got $t');
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -126,7 +128,7 @@ abstract class Parser {
|
|||
|
||||
Token expectName() {
|
||||
Token t = advance()!;
|
||||
if (!t.isName) fail('expected name token, got ${t}');
|
||||
if (!t.isName) fail('expected name token, got $t');
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -154,7 +156,7 @@ abstract class Parser {
|
|||
} else if (str.isEmpty) {
|
||||
buf.write('\n\n');
|
||||
} else {
|
||||
buf.write('${str} ');
|
||||
buf.write('$str ');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +187,7 @@ abstract class Parser {
|
|||
}
|
||||
|
||||
void validate(bool result, String message) {
|
||||
if (!result) throw 'expected ${message}';
|
||||
if (!result) throw 'expected $message';
|
||||
}
|
||||
|
||||
void fail(String message) => throw message;
|
||||
|
|
|
@ -6,10 +6,10 @@ library src_gen_common;
|
|||
|
||||
import 'package:markdown/markdown.dart';
|
||||
|
||||
const int RUNE_SPACE = 32;
|
||||
const int RUNE_EOL = 10;
|
||||
const int RUNE_LEFT_CURLY = 123;
|
||||
const int RUNE_RIGHT_CURLY = 125;
|
||||
const int $space = 32;
|
||||
const int $eol = 10;
|
||||
const int $leftCurly = 123;
|
||||
const int $rightCurly = 125;
|
||||
|
||||
final RegExp _wsRegexp = RegExp(r'\s+');
|
||||
|
||||
|
@ -82,7 +82,7 @@ String _simpleWrap(String str, [int col = 80]) {
|
|||
while (str.length > col) {
|
||||
int index = col;
|
||||
|
||||
while (index > 0 && str.codeUnitAt(index) != RUNE_SPACE) {
|
||||
while (index > 0 && str.codeUnitAt(index) != $space) {
|
||||
index--;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ String? _coerceRefType(String? typeName) {
|
|||
if (typeName == 'Function') typeName = 'Func';
|
||||
if (typeName == '@Function') typeName = 'FuncRef';
|
||||
|
||||
if (typeName!.startsWith('@')) typeName = typeName.substring(1) + 'Ref';
|
||||
if (typeName!.startsWith('@')) typeName = '${typeName.substring(1)}Ref';
|
||||
|
||||
if (typeName == 'string') typeName = 'String';
|
||||
if (typeName == 'map') typeName = 'Map';
|
||||
|
@ -32,7 +32,7 @@ String? _coerceRefType(String? typeName) {
|
|||
}
|
||||
|
||||
String _typeRefListToString(List<TypeRef> types) =>
|
||||
'const [' + types.map((e) => "'" + e.name! + "'").join(',') + ']';
|
||||
'const [${types.map((e) => "'${e.name!}'").join(',')}]';
|
||||
|
||||
final String _headerCode = r'''
|
||||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||
|
@ -45,6 +45,8 @@ final String _headerCode = r'''
|
|||
///
|
||||
/// The main entry-point for this library is the [VmService] class.
|
||||
|
||||
// ignore_for_file: overridden_fields
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show base64, jsonDecode, jsonEncode, utf8;
|
||||
import 'dart:typed_data';
|
||||
|
@ -128,7 +130,7 @@ final String _implCode = r'''
|
|||
/// Register a service for invocation.
|
||||
void registerServiceCallback(String service, ServiceCallback cb) {
|
||||
if (_services.containsKey(service)) {
|
||||
throw Exception('Service \'${service}\' already registered');
|
||||
throw Exception('Service \'$service\' already registered');
|
||||
}
|
||||
_services[service] = cb;
|
||||
}
|
||||
|
@ -173,7 +175,7 @@ final String _implCode = r'''
|
|||
_onReceive.add(message);
|
||||
json = jsonDecode(message)!;
|
||||
} catch (e, s) {
|
||||
_log.severe('unable to decode message: ${message}, ${e}\n${s}');
|
||||
_log.severe('unable to decode message: $message, $e\n$s');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -188,7 +190,7 @@ final String _implCode = r'''
|
|||
_processResponse(json);
|
||||
}
|
||||
else {
|
||||
_log.severe('unknown message type: ${message}');
|
||||
_log.severe('unknown message type: $message');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,6 +307,7 @@ class RPCError implements Exception {
|
|||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (details == null) {
|
||||
return '$callingMethod: ($code) $message';
|
||||
|
@ -322,7 +325,8 @@ class SentinelException implements Exception {
|
|||
SentinelException.parse(this.callingMethod, Map<String, dynamic> data) :
|
||||
sentinel = Sentinel.parse(data)!;
|
||||
|
||||
String toString() => '$sentinel from ${callingMethod}()';
|
||||
@override
|
||||
String toString() => '$sentinel from $callingMethod()';
|
||||
}
|
||||
|
||||
/// An `ExtensionData` is an arbitrary map that can have any contents.
|
||||
|
@ -336,7 +340,8 @@ class ExtensionData {
|
|||
|
||||
ExtensionData._fromJson(this.data);
|
||||
|
||||
String toString() => '[ExtensionData ${data}]';
|
||||
@override
|
||||
String toString() => '[ExtensionData $data]';
|
||||
}
|
||||
|
||||
/// A logging handler you can pass to a [VmService] instance in order to get
|
||||
|
@ -350,7 +355,9 @@ abstract class Log {
|
|||
}
|
||||
|
||||
class _NullLog implements Log {
|
||||
@override
|
||||
void warning(String message) {}
|
||||
@override
|
||||
void severe(String message) {}
|
||||
}
|
||||
''';
|
||||
|
@ -404,6 +411,7 @@ abstract class Member {
|
|||
|
||||
bool get hasDocs => docs != null;
|
||||
|
||||
@override
|
||||
String toString() => name!;
|
||||
}
|
||||
|
||||
|
@ -440,7 +448,7 @@ class Api extends Member with ApiParseUtil {
|
|||
!str.startsWith('- ')) {
|
||||
str = collapseWhitespace(str);
|
||||
}
|
||||
docs = '${docs}\n\n${str}';
|
||||
docs = '$docs\n\n$str';
|
||||
}
|
||||
|
||||
docs = docs!.trim();
|
||||
|
@ -463,8 +471,10 @@ class Api extends Member with ApiParseUtil {
|
|||
_parseStreamListenDocs(streamListenMethod.docs!);
|
||||
}
|
||||
|
||||
@override
|
||||
String get name => 'api';
|
||||
|
||||
@override
|
||||
String? get docs => null;
|
||||
|
||||
void _parse(String name, String definition, [String? docs]) {
|
||||
|
@ -479,7 +489,7 @@ class Api extends Member with ApiParseUtil {
|
|||
} else if (definition.startsWith('enum ')) {
|
||||
enums.add(Enum(name, definition, docs));
|
||||
} else {
|
||||
throw 'unexpected entity: ${name}, ${definition}';
|
||||
throw 'unexpected entity: $name, $definition';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,13 +500,14 @@ class Api extends Member with ApiParseUtil {
|
|||
if (n.tag != 'h3') return n.tag;
|
||||
return '${n.tag}:[${n.children!.map((c) => printNode(c)).join(', ')}]';
|
||||
} else {
|
||||
return '${n}';
|
||||
return '$n';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
gen.out(_headerCode);
|
||||
gen.writeln("const String vmServiceVersion = '${serviceVersion}';");
|
||||
gen.writeln("const String vmServiceVersion = '$serviceVersion';");
|
||||
gen.writeln();
|
||||
gen.writeln('''
|
||||
/// @optional
|
||||
|
@ -543,7 +554,8 @@ Object? createServiceObject(dynamic json, List<String> expectedTypes) {
|
|||
}
|
||||
}
|
||||
|
||||
dynamic _createSpecificObject(dynamic json, dynamic creator(Map<String, dynamic> map)) {
|
||||
dynamic _createSpecificObject(
|
||||
dynamic json, dynamic Function(Map<String, dynamic> map) creator) {
|
||||
if (json == null) return null;
|
||||
|
||||
if (json is List) {
|
||||
|
@ -581,17 +593,17 @@ void addTypeFactory(String name, Function factory) {
|
|||
''');
|
||||
gen.writeln();
|
||||
gen.writeln('Map<String, Function> _typeFactories = {');
|
||||
types.forEach((Type? type) {
|
||||
for (var type in types) {
|
||||
gen.writeln("'${type!.rawName}': ${type.name}.parse,");
|
||||
});
|
||||
}
|
||||
gen.writeln('};');
|
||||
gen.writeln();
|
||||
|
||||
gen.writeln('Map<String, List<String>> _methodReturnTypes = {');
|
||||
methods.forEach((Method method) {
|
||||
for (var method in methods) {
|
||||
String returnTypes = _typeRefListToString(method.returnType.types);
|
||||
gen.writeln("'${method.name}' : $returnTypes,");
|
||||
});
|
||||
}
|
||||
gen.writeln('};');
|
||||
gen.writeln();
|
||||
|
||||
|
@ -610,104 +622,106 @@ abstract class VmServiceInterface {
|
|||
/// Handler for calling extra service extensions.
|
||||
Future<Response> callServiceExtension(String method, {String? isolateId, Map<String, dynamic>? args});
|
||||
''');
|
||||
methods.forEach((m) {
|
||||
for (var m in methods) {
|
||||
m.generateDefinition(gen);
|
||||
gen.write(';');
|
||||
});
|
||||
}
|
||||
gen.write('}');
|
||||
gen.writeln();
|
||||
|
||||
// The server class, takes a VmServiceInterface and delegates to it
|
||||
// automatically.
|
||||
gen.write('''
|
||||
class _PendingServiceRequest {
|
||||
Future<Map<String, Object?>> get future => _completer.future;
|
||||
final _completer = Completer<Map<String, Object?>>();
|
||||
class _PendingServiceRequest {
|
||||
Future<Map<String, Object?>> get future => _completer.future;
|
||||
final _completer = Completer<Map<String, Object?>>();
|
||||
|
||||
final dynamic originalId;
|
||||
final dynamic originalId;
|
||||
|
||||
_PendingServiceRequest(this.originalId);
|
||||
_PendingServiceRequest(this.originalId);
|
||||
|
||||
void complete(Map<String, Object?> response) {
|
||||
response['id'] = originalId;
|
||||
_completer.complete(response);
|
||||
}
|
||||
void complete(Map<String, Object?> response) {
|
||||
response['id'] = originalId;
|
||||
_completer.complete(response);
|
||||
}
|
||||
}
|
||||
|
||||
/// A Dart VM Service Protocol connection that delegates requests to a
|
||||
/// [VmServiceInterface] implementation.
|
||||
///
|
||||
/// One of these should be created for each client, but they should generally
|
||||
/// share the same [VmServiceInterface] and [ServiceExtensionRegistry]
|
||||
/// instances.
|
||||
class VmServerConnection {
|
||||
final Stream<Map<String, Object>> _requestStream;
|
||||
final StreamSink<Map<String, Object?>> _responseSink;
|
||||
final ServiceExtensionRegistry _serviceExtensionRegistry;
|
||||
final VmServiceInterface _serviceImplementation;
|
||||
/// Used to create unique ids when acting as a proxy between clients.
|
||||
int _nextServiceRequestId = 0;
|
||||
|
||||
/// Manages streams for `streamListen` and `streamCancel` requests.
|
||||
final _streamSubscriptions = <String, StreamSubscription>{};
|
||||
|
||||
/// Completes when [_requestStream] is done.
|
||||
Future<void> get done => _doneCompleter.future;
|
||||
final _doneCompleter = Completer<void>();
|
||||
|
||||
/// Pending service extension requests to this client by id.
|
||||
final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
|
||||
|
||||
VmServerConnection(this._requestStream, this._responseSink,
|
||||
this._serviceExtensionRegistry, this._serviceImplementation) {
|
||||
_requestStream.listen(_delegateRequest, onDone: _doneCompleter.complete);
|
||||
done.then((_) {
|
||||
for (var sub in _streamSubscriptions.values) {
|
||||
sub.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// A Dart VM Service Protocol connection that delegates requests to a
|
||||
/// [VmServiceInterface] implementation.
|
||||
/// Invoked when the current client has registered some extension, and
|
||||
/// another client sends an RPC request for that extension.
|
||||
///
|
||||
/// One of these should be created for each client, but they should generally
|
||||
/// share the same [VmServiceInterface] and [ServiceExtensionRegistry]
|
||||
/// instances.
|
||||
class VmServerConnection {
|
||||
final Stream<Map<String, Object>> _requestStream;
|
||||
final StreamSink<Map<String, Object?>> _responseSink;
|
||||
final ServiceExtensionRegistry _serviceExtensionRegistry;
|
||||
final VmServiceInterface _serviceImplementation;
|
||||
/// Used to create unique ids when acting as a proxy between clients.
|
||||
int _nextServiceRequestId = 0;
|
||||
/// We don't attempt to do any serialization or deserialization of the
|
||||
/// request or response in this case
|
||||
Future<Map<String, Object?>> _forwardServiceExtensionRequest(
|
||||
Map<String, Object?> request) {
|
||||
final originalId = request['id'];
|
||||
request = Map<String, Object?>.of(request);
|
||||
// Modify the request ID to ensure we don't have conflicts between
|
||||
// multiple clients ids.
|
||||
final newId = '\${_nextServiceRequestId++}:\$originalId';
|
||||
request['id'] = newId;
|
||||
var pendingRequest = _PendingServiceRequest(originalId);
|
||||
_pendingServiceExtensionRequests[newId] = pendingRequest;
|
||||
_responseSink.add(request);
|
||||
return pendingRequest.future;
|
||||
}
|
||||
|
||||
/// Manages streams for `streamListen` and `streamCancel` requests.
|
||||
final _streamSubscriptions = <String, StreamSubscription>{};
|
||||
void _delegateRequest(Map<String, Object?> request) async {
|
||||
try {
|
||||
var id = request['id'];
|
||||
// Check if this is actually a response to a pending request.
|
||||
if (_pendingServiceExtensionRequests.containsKey(id)) {
|
||||
final pending = _pendingServiceExtensionRequests[id]!;
|
||||
pending.complete(Map<String, Object?>.of(request));
|
||||
return;
|
||||
}
|
||||
final method = request['method'] as String?;
|
||||
if (method == null) {
|
||||
throw RPCError(
|
||||
null, RPCError.kInvalidRequest, 'Invalid Request', request);
|
||||
}
|
||||
final params = request['params'] as Map<String, dynamic>?;
|
||||
late Response response;
|
||||
|
||||
/// Completes when [_requestStream] is done.
|
||||
Future<void> get done => _doneCompleter.future;
|
||||
final _doneCompleter = Completer<void>();
|
||||
|
||||
/// Pending service extension requests to this client by id.
|
||||
final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
|
||||
|
||||
VmServerConnection(
|
||||
this._requestStream, this._responseSink, this._serviceExtensionRegistry,
|
||||
this._serviceImplementation) {
|
||||
_requestStream.listen(_delegateRequest, onDone: _doneCompleter.complete);
|
||||
done.then(
|
||||
(_) => _streamSubscriptions.values.forEach((sub) => sub.cancel()));
|
||||
}
|
||||
|
||||
/// Invoked when the current client has registered some extension, and
|
||||
/// another client sends an RPC request for that extension.
|
||||
///
|
||||
/// We don't attempt to do any serialization or deserialization of the
|
||||
/// request or response in this case
|
||||
Future<Map<String, Object?>> _forwardServiceExtensionRequest(
|
||||
Map<String, Object?> request) {
|
||||
final originalId = request['id'];
|
||||
request = Map<String, Object?>.of(request);
|
||||
// Modify the request ID to ensure we don't have conflicts between
|
||||
// multiple clients ids.
|
||||
final newId = '\${_nextServiceRequestId++}:\$originalId';
|
||||
request['id'] = newId;
|
||||
var pendingRequest = _PendingServiceRequest(originalId);
|
||||
_pendingServiceExtensionRequests[newId] = pendingRequest;
|
||||
_responseSink.add(request);
|
||||
return pendingRequest.future;
|
||||
}
|
||||
|
||||
void _delegateRequest(Map<String, Object?> request) async {
|
||||
try {
|
||||
var id = request['id'];
|
||||
// Check if this is actually a response to a pending request.
|
||||
if (_pendingServiceExtensionRequests.containsKey(id)) {
|
||||
final pending = _pendingServiceExtensionRequests[id]!;
|
||||
pending.complete(Map<String, Object?>.of(request));
|
||||
return;
|
||||
}
|
||||
final method = request['method'] as String?;
|
||||
if (method == null) {
|
||||
throw RPCError(
|
||||
null, RPCError.kInvalidRequest, 'Invalid Request', request);
|
||||
}
|
||||
final params = request['params'] as Map<String, dynamic>?;
|
||||
late Response response;
|
||||
|
||||
switch(method) {
|
||||
case 'registerService':
|
||||
$_registerServiceImpl
|
||||
break;
|
||||
''');
|
||||
methods.forEach((m) {
|
||||
switch(method) {
|
||||
case 'registerService':
|
||||
$_registerServiceImpl
|
||||
break;
|
||||
''');
|
||||
for (var m in methods) {
|
||||
if (m.name != 'registerService') {
|
||||
gen.writeln("case '${m.name}':");
|
||||
if (m.name == 'streamListen') {
|
||||
|
@ -716,13 +730,14 @@ abstract class VmServiceInterface {
|
|||
gen.writeln(_streamCancelCaseImpl);
|
||||
} else {
|
||||
bool firstParam = true;
|
||||
final nullCheck = () {
|
||||
String nullCheck() {
|
||||
final result = firstParam ? '!' : '';
|
||||
if (firstParam) {
|
||||
firstParam = false;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
if (m.deprecated) {
|
||||
gen.writeln('// ignore: deprecated_member_use_from_same_package');
|
||||
}
|
||||
|
@ -739,7 +754,7 @@ abstract class VmServiceInterface {
|
|||
// Optional named args
|
||||
var namedArgs = m.args.where((arg) => arg.optional);
|
||||
if (namedArgs.isNotEmpty) {
|
||||
namedArgs.forEach((arg) {
|
||||
for (var arg in namedArgs) {
|
||||
if (arg.name == 'scope') {
|
||||
gen.writeln(
|
||||
"${arg.name}: params${nullCheck()}['${arg.name}']?.cast<String, String>(), ");
|
||||
|
@ -747,13 +762,13 @@ abstract class VmServiceInterface {
|
|||
gen.writeln(
|
||||
"${arg.name}: params${nullCheck()}['${arg.name}'], ");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
gen.writeln(');');
|
||||
}
|
||||
gen.writeln('break;');
|
||||
}
|
||||
});
|
||||
}
|
||||
// Handle service extensions
|
||||
gen.writeln('default:');
|
||||
gen.writeln('''
|
||||
|
@ -836,64 +851,71 @@ class _OutstandingRequest<T> {
|
|||
gen.writeStatement('late final Function _writeMessage;');
|
||||
gen.writeStatement(
|
||||
'final Map<String, _OutstandingRequest> _outstandingRequests = {};');
|
||||
gen.writeStatement('Map<String, ServiceCallback> _services = {};');
|
||||
gen.writeStatement('final Map<String, ServiceCallback> _services = {};');
|
||||
gen.writeStatement('late final Log _log;');
|
||||
gen.write('''
|
||||
|
||||
StreamController<String> _onSend = StreamController.broadcast(sync: true);
|
||||
StreamController<String> _onReceive = StreamController.broadcast(sync: true);
|
||||
final StreamController<String> _onSend = StreamController.broadcast(sync: true);
|
||||
final StreamController<String> _onReceive = StreamController.broadcast(sync: true);
|
||||
|
||||
final Completer _onDoneCompleter = Completer();
|
||||
final Completer _onDoneCompleter = Completer();
|
||||
|
||||
Map<String, StreamController<Event>> _eventControllers = {};
|
||||
final Map<String, StreamController<Event>> _eventControllers = {};
|
||||
|
||||
StreamController<Event> _getEventController(String eventName) {
|
||||
StreamController<Event>? controller = _eventControllers[eventName];
|
||||
if (controller == null) {
|
||||
controller = StreamController.broadcast();
|
||||
_eventControllers[eventName] = controller;
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
late final DisposeHandler? _disposeHandler;
|
||||
|
||||
VmService(Stream<dynamic> /*String|List<int>*/ inStream, void writeMessage(String message), {
|
||||
Log? log,
|
||||
DisposeHandler? disposeHandler,
|
||||
Future? streamClosed,
|
||||
}) {
|
||||
_streamSub = inStream.listen(_processMessage, onDone: ()=> _onDoneCompleter.complete());
|
||||
_writeMessage = writeMessage;
|
||||
_log = log == null ? _NullLog() : log;
|
||||
_disposeHandler = disposeHandler;
|
||||
streamClosed?.then((_) {
|
||||
if (!_onDoneCompleter.isCompleted) {
|
||||
_onDoneCompleter.complete();
|
||||
StreamController<Event> _getEventController(String eventName) {
|
||||
StreamController<Event>? controller = _eventControllers[eventName];
|
||||
if (controller == null) {
|
||||
controller = StreamController.broadcast();
|
||||
_eventControllers[eventName] = controller;
|
||||
}
|
||||
});
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<Event> onEvent(String streamId) => _getEventController(streamId).stream;
|
||||
late final DisposeHandler? _disposeHandler;
|
||||
|
||||
VmService(
|
||||
Stream<dynamic> /*String|List<int>*/ inStream,
|
||||
void Function(String message) writeMessage, {
|
||||
Log? log,
|
||||
DisposeHandler? disposeHandler,
|
||||
Future? streamClosed,
|
||||
}) {
|
||||
_streamSub = inStream.listen(_processMessage,
|
||||
onDone: () => _onDoneCompleter.complete());
|
||||
_writeMessage = writeMessage;
|
||||
_log = log ?? _NullLog();
|
||||
_disposeHandler = disposeHandler;
|
||||
streamClosed?.then((_) {
|
||||
if (!_onDoneCompleter.isCompleted) {
|
||||
_onDoneCompleter.complete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<Event> onEvent(String streamId) => _getEventController(streamId).stream;
|
||||
''');
|
||||
|
||||
// streamCategories
|
||||
streamCategories.forEach((s) => s.generate(gen));
|
||||
for (var s in streamCategories) {
|
||||
s.generate(gen);
|
||||
}
|
||||
|
||||
gen.writeln();
|
||||
methods.forEach((m) => m.generate(gen));
|
||||
for (var m in methods) {
|
||||
m.generate(gen);
|
||||
}
|
||||
gen.out(_implCode);
|
||||
gen.writeStatement('}');
|
||||
gen.writeln();
|
||||
gen.out(_rpcError);
|
||||
gen.writeln('// enums');
|
||||
enums.forEach((e) {
|
||||
for (var e in enums) {
|
||||
if (e.name == 'EventKind') {
|
||||
_generateEventStream(gen);
|
||||
}
|
||||
e.generate(gen);
|
||||
});
|
||||
}
|
||||
gen.writeln();
|
||||
gen.writeln('// types');
|
||||
types.where((t) => !t!.skip).forEach((t) => t!.generate(gen));
|
||||
|
@ -940,9 +962,9 @@ Stream<Event> onEvent(String streamId) => _getEventController(streamId).stream;
|
|||
gen.writeln('EventStreams._();');
|
||||
gen.writeln();
|
||||
|
||||
streamCategories.forEach((c) {
|
||||
for (var c in streamCategories) {
|
||||
gen.writeln("static const String k${c.name} = '${c.name}';");
|
||||
});
|
||||
}
|
||||
|
||||
gen.writeln('}');
|
||||
}
|
||||
|
@ -971,11 +993,14 @@ class StreamCategory {
|
|||
"Stream<Event> get on${name}Event => _getEventController('$name').stream;");
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => '$name: $events';
|
||||
}
|
||||
|
||||
class Method extends Member {
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
final String? docs;
|
||||
|
||||
MemberType returnType = MemberType();
|
||||
|
@ -991,10 +1016,11 @@ class Method extends Member {
|
|||
|
||||
bool get hasOptionalArgs => args.any((MethodArg arg) => arg.optional);
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
generateDefinition(gen, withDocs: false, withOverrides: true);
|
||||
if (!hasArgs) {
|
||||
gen.writeStatement("=> _call('${name}');");
|
||||
gen.writeStatement("=> _call('$name');");
|
||||
} else if (hasOptionalArgs) {
|
||||
gen.writeStatement("=> _call('$name', {");
|
||||
gen.write(args
|
||||
|
@ -1016,7 +1042,7 @@ class Method extends Member {
|
|||
|
||||
gen.writeln('});');
|
||||
} else {
|
||||
gen.write("=> _call('${name}', {");
|
||||
gen.write("=> _call('$name', {");
|
||||
gen.write(args.map((MethodArg arg) {
|
||||
return "'${arg.name}': ${arg.name}";
|
||||
}).join(', '));
|
||||
|
@ -1034,24 +1060,24 @@ class Method extends Member {
|
|||
{bool withDocs = true, bool withOverrides = false}) {
|
||||
gen.writeln();
|
||||
if (withDocs && docs != null) {
|
||||
String _docs = docs == null ? '' : docs!;
|
||||
String methodDocs = docs!;
|
||||
if (returnType.isMultipleReturns) {
|
||||
_docs += '\n\nThe return value can be one of '
|
||||
'${joinLast(returnType.types.map((t) => '[${t}]'), ', ', ' or ')}.';
|
||||
_docs = _docs.trim();
|
||||
methodDocs += '\n\nThe return value can be one of '
|
||||
'${joinLast(returnType.types.map((t) => '[$t]'), ', ', ' or ')}.';
|
||||
methodDocs = methodDocs.trim();
|
||||
}
|
||||
if (returnType.canReturnSentinel) {
|
||||
_docs +=
|
||||
methodDocs +=
|
||||
'\n\nThis method will throw a [SentinelException] in the case a [Sentinel] is returned.';
|
||||
_docs = _docs.trim();
|
||||
methodDocs = methodDocs.trim();
|
||||
}
|
||||
if (_docs.isNotEmpty) gen.writeDocs(_docs);
|
||||
if (methodDocs.isNotEmpty) gen.writeDocs(methodDocs);
|
||||
}
|
||||
if (deprecated) {
|
||||
gen.writeln("@Deprecated('$deprecationMessage')");
|
||||
}
|
||||
if (withOverrides) gen.writeln('@override');
|
||||
gen.write('Future<${returnType.name}> ${name}(');
|
||||
gen.write('Future<${returnType.name}> $name(');
|
||||
bool startedOptional = false;
|
||||
gen.write(args.map((MethodArg arg) {
|
||||
String typeName;
|
||||
|
@ -1067,9 +1093,9 @@ class Method extends Member {
|
|||
final nullable = arg.optional ? '?' : '';
|
||||
if (arg.optional && !startedOptional) {
|
||||
startedOptional = true;
|
||||
return '{${typeName}$nullable ${arg.name}';
|
||||
return '{$typeName$nullable ${arg.name}';
|
||||
} else {
|
||||
return '${typeName}$nullable ${arg.name}';
|
||||
return '$typeName$nullable ${arg.name}';
|
||||
}
|
||||
}).join(', '));
|
||||
if (args.length >= 4) gen.write(',');
|
||||
|
@ -1136,6 +1162,7 @@ class MemberType extends Member {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String get name {
|
||||
if (types.isEmpty) return '';
|
||||
if (types.length == 1) return types.first.ref;
|
||||
|
@ -1164,6 +1191,7 @@ class MemberType extends Member {
|
|||
|
||||
bool get isArray => types.length == 1 && types.first.isArray;
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) => gen.write(name);
|
||||
}
|
||||
|
||||
|
@ -1177,9 +1205,9 @@ class TypeRef {
|
|||
|
||||
String get ref {
|
||||
if (arrayDepth == 2) {
|
||||
return 'List<List<${name}${nullable ? "?" : ""}>>';
|
||||
return 'List<List<$name${nullable ? "?" : ""}>>';
|
||||
} else if (arrayDepth == 1) {
|
||||
return 'List<${name}${nullable ? "?" : ""}>';
|
||||
return 'List<$name${nullable ? "?" : ""}>';
|
||||
} else if (genericTypes != null) {
|
||||
return '$name<${genericTypes!.join(', ')}>';
|
||||
} else {
|
||||
|
@ -1221,29 +1249,35 @@ class TypeRef {
|
|||
name == 'double' ||
|
||||
name == 'ByteData');
|
||||
|
||||
@override
|
||||
String toString() => ref;
|
||||
}
|
||||
|
||||
class MethodArg extends Member {
|
||||
final Method parent;
|
||||
TypeRef type;
|
||||
@override
|
||||
String? name;
|
||||
bool optional = false;
|
||||
|
||||
MethodArg(this.parent, this.type, this.name);
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
gen.write('${type.ref} ${name}');
|
||||
gen.write('${type.ref} $name');
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => '$type $name';
|
||||
}
|
||||
|
||||
class Type extends Member {
|
||||
final Api parent;
|
||||
String? rawName;
|
||||
@override
|
||||
String? name;
|
||||
String? superName;
|
||||
@override
|
||||
final String? docs;
|
||||
List<TypeField> fields = [];
|
||||
|
||||
|
@ -1305,21 +1339,22 @@ class Type extends Member {
|
|||
|
||||
bool get skip => name == 'ExtensionData';
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
gen.writeln();
|
||||
if (docs != null) gen.writeDocs(docs);
|
||||
gen.write('class ${name} ');
|
||||
gen.write('class $name ');
|
||||
Type? superType;
|
||||
if (superName != null) {
|
||||
superType = parent.getType(superName);
|
||||
gen.write('extends ${superName} ');
|
||||
gen.write('extends $superName ');
|
||||
}
|
||||
if (parent.getType('${name}Ref') != null) {
|
||||
gen.write('implements ${name}Ref ');
|
||||
}
|
||||
gen.writeln('{');
|
||||
gen.writeln('static ${name}? parse(Map<String, dynamic>? json) => '
|
||||
'json == null ? null : ${name}._fromJson(json);');
|
||||
gen.writeln('static $name? parse(Map<String, dynamic>? json) => '
|
||||
'json == null ? null : $name._fromJson(json);');
|
||||
gen.writeln();
|
||||
|
||||
if (name == 'Response' || name == 'TimelineEvent') {
|
||||
|
@ -1331,7 +1366,9 @@ class Type extends Member {
|
|||
}
|
||||
|
||||
// fields
|
||||
fields.forEach((TypeField field) => field.generate(gen));
|
||||
for (var field in fields) {
|
||||
field.generate(gen);
|
||||
}
|
||||
gen.writeln();
|
||||
|
||||
// ctors
|
||||
|
@ -1339,7 +1376,7 @@ class Type extends Member {
|
|||
bool hasRequiredParentFields = superType != null &&
|
||||
(superType.name == 'ObjRef' || superType.name == 'Obj');
|
||||
// Default
|
||||
gen.write('${name}(');
|
||||
gen.write('$name(');
|
||||
if (fields.isNotEmpty) {
|
||||
gen.write('{');
|
||||
fields.where((field) => !field.optional).forEach((field) {
|
||||
|
@ -1384,9 +1421,9 @@ class Type extends Member {
|
|||
gen.writeln();
|
||||
String superCall = superName == null ? '' : ': super._fromJson(json) ';
|
||||
if (name == 'Response' || name == 'TimelineEvent') {
|
||||
gen.write('${name}._fromJson(this.json)');
|
||||
gen.write('$name._fromJson(this.json)');
|
||||
} else {
|
||||
gen.write('${name}._fromJson(Map<String, dynamic> json) ${superCall}');
|
||||
gen.write('$name._fromJson(Map<String, dynamic> json) $superCall');
|
||||
}
|
||||
|
||||
if (fields.isEmpty) {
|
||||
|
@ -1395,7 +1432,7 @@ class Type extends Member {
|
|||
gen.writeln('{');
|
||||
}
|
||||
|
||||
fields.forEach((TypeField field) {
|
||||
for (var field in fields) {
|
||||
if (field.type.isSimple || field.type.isEnum) {
|
||||
// Special case `AllocationProfile`.
|
||||
if (name == 'AllocationProfile' && field.type.name == 'int') {
|
||||
|
@ -1500,7 +1537,7 @@ class Type extends Member {
|
|||
'$typesList) as ${field.type.name}$nullable;',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (fields.isNotEmpty) {
|
||||
gen.writeln('}');
|
||||
}
|
||||
|
@ -1559,20 +1596,20 @@ Map<String, dynamic> toJson() {
|
|||
var requiredFields = fields.where((f) => !f.optional);
|
||||
if (requiredFields.isNotEmpty) {
|
||||
gen.writeln('json.addAll({');
|
||||
requiredFields.forEach((TypeField field) {
|
||||
for (var field in requiredFields) {
|
||||
gen.write("'${field.name}': ");
|
||||
generateSerializedFieldAccess(field, gen);
|
||||
gen.writeln(',');
|
||||
});
|
||||
}
|
||||
gen.writeln('});');
|
||||
}
|
||||
|
||||
var optionalFields = fields.where((f) => f.optional);
|
||||
optionalFields.forEach((TypeField field) {
|
||||
for (var field in optionalFields) {
|
||||
gen.write("_setIfNotNull(json, '${field.name}', ");
|
||||
generateSerializedFieldAccess(field, gen);
|
||||
gen.writeln(');');
|
||||
});
|
||||
}
|
||||
gen.writeln('return json;');
|
||||
gen.writeln('}');
|
||||
gen.writeln();
|
||||
|
@ -1580,11 +1617,13 @@ Map<String, dynamic> toJson() {
|
|||
|
||||
// equals and hashCode
|
||||
if (supportsIdentity) {
|
||||
gen.writeln('@override');
|
||||
gen.writeStatement('int get hashCode => id.hashCode;');
|
||||
gen.writeln();
|
||||
|
||||
gen.writeln('@override');
|
||||
gen.writeStatement(
|
||||
'bool operator ==(Object other) => other is ${name} && id == other.id;');
|
||||
'bool operator ==(Object other) => other is $name && id == other.id;');
|
||||
gen.writeln();
|
||||
}
|
||||
|
||||
|
@ -1592,25 +1631,24 @@ Map<String, dynamic> toJson() {
|
|||
Iterable<TypeField> toStringFields =
|
||||
getAllFields().where((f) => !f.optional);
|
||||
const maxFieldsShownInToString = 8;
|
||||
gen.writeln('@override');
|
||||
if (toStringFields.length <= maxFieldsShownInToString) {
|
||||
String properties = toStringFields
|
||||
.map(
|
||||
(TypeField f) => '${f.generatableName}: \${${f.generatableName}}')
|
||||
.map((TypeField f) => '${f.generatableName}: \$${f.generatableName}')
|
||||
.join(', ');
|
||||
if (properties.length > 60) {
|
||||
int index = properties.indexOf(', ', 55);
|
||||
if (index != -1) {
|
||||
properties = properties.substring(0, index + 2) +
|
||||
"' //\n'" +
|
||||
properties.substring(index + 2);
|
||||
properties =
|
||||
"${properties.substring(0, index + 2)}' //\n'${properties.substring(index + 2)}";
|
||||
}
|
||||
gen.writeln("String toString() => '[${name} ' //\n'${properties}]';");
|
||||
gen.writeln("String toString() => '[$name ' //\n'$properties]';");
|
||||
} else {
|
||||
final formattedProperties = (properties.isEmpty) ? '' : ' $properties';
|
||||
gen.writeln("String toString() => '[$name$formattedProperties]';");
|
||||
}
|
||||
} else {
|
||||
gen.writeln("String toString() => '[${name}]';");
|
||||
gen.writeln("String toString() => '[$name]';");
|
||||
}
|
||||
|
||||
gen.writeln('}');
|
||||
|
@ -1689,7 +1727,7 @@ void _parseTokenPosTable() {
|
|||
}
|
||||
|
||||
void generateAssert(DartGenerator gen) {
|
||||
gen.writeln('vms.${name} assert${name}(vms.${name} obj) {');
|
||||
gen.writeln('vms.$name assert$name(vms.$name obj) {');
|
||||
gen.writeln('assertNotNull(obj);');
|
||||
for (TypeField field in getAllFields()) {
|
||||
if (!field.optional) {
|
||||
|
@ -1697,9 +1735,8 @@ void _parseTokenPosTable() {
|
|||
if (type.isArray) {
|
||||
TypeRef arrayType = type.types.first;
|
||||
if (arrayType.arrayDepth == 1) {
|
||||
String assertMethodName = 'assertListOf' +
|
||||
arrayType.name!.substring(0, 1).toUpperCase() +
|
||||
arrayType.name!.substring(1);
|
||||
String assertMethodName =
|
||||
'assertListOf${arrayType.name!.substring(0, 1).toUpperCase()}${arrayType.name!.substring(1)}';
|
||||
gen.writeln('$assertMethodName(obj.${field.generatableName}!);');
|
||||
} else {
|
||||
gen.writeln(
|
||||
|
@ -1712,9 +1749,8 @@ void _parseTokenPosTable() {
|
|||
first = false;
|
||||
gen.writeln(
|
||||
'if (obj.${field.generatableName} is vms.${typeRef.name}) {');
|
||||
String assertMethodName = 'assert' +
|
||||
typeRef.name!.substring(0, 1).toUpperCase() +
|
||||
typeRef.name!.substring(1);
|
||||
String assertMethodName =
|
||||
'assert${typeRef.name!.substring(0, 1).toUpperCase()}${typeRef.name!.substring(1)}';
|
||||
gen.writeln('$assertMethodName(obj.${field.generatableName}!);');
|
||||
}
|
||||
gen.writeln('} else {');
|
||||
|
@ -1722,9 +1758,8 @@ void _parseTokenPosTable() {
|
|||
'throw "Unexpected value: \${obj.${field.generatableName}}";');
|
||||
gen.writeln('}');
|
||||
} else {
|
||||
String assertMethodName = 'assert' +
|
||||
type.name.substring(0, 1).toUpperCase() +
|
||||
type.name.substring(1);
|
||||
String assertMethodName =
|
||||
'assert${type.name.substring(0, 1).toUpperCase()}${type.name.substring(1)}';
|
||||
gen.writeln('$assertMethodName(obj.${field.generatableName}!);');
|
||||
}
|
||||
}
|
||||
|
@ -1735,10 +1770,10 @@ void _parseTokenPosTable() {
|
|||
}
|
||||
|
||||
void generateListAssert(DartGenerator gen) {
|
||||
gen.writeln('List<vms.${name}> '
|
||||
'assertListOf${name}(List<vms.${name}> list) {');
|
||||
gen.writeln('for (vms.${name} elem in list) {');
|
||||
gen.writeln('assert${name}(elem);');
|
||||
gen.writeln('List<vms.$name> '
|
||||
'assertListOf$name(List<vms.$name> list) {');
|
||||
gen.writeln('for (vms.$name elem in list) {');
|
||||
gen.writeln('assert$name(elem);');
|
||||
gen.writeln('}');
|
||||
gen.writeln('return list;');
|
||||
gen.writeln('}');
|
||||
|
@ -1777,6 +1812,7 @@ class TypeField extends Member {
|
|||
final Type parent;
|
||||
final String? _docs;
|
||||
MemberType type = MemberType();
|
||||
@override
|
||||
String? name;
|
||||
bool optional = false;
|
||||
String? _defaultValue;
|
||||
|
@ -1786,18 +1822,19 @@ class TypeField extends Member {
|
|||
|
||||
void setOverrides() => overrides = true;
|
||||
|
||||
@override
|
||||
String? get docs {
|
||||
String str = _docs == null ? '' : _docs!;
|
||||
if (type.isMultipleReturns) {
|
||||
str += '\n\n[${generatableName}] can be one of '
|
||||
'${joinLast(type.types.map((t) => '[${t}]'), ', ', ' or ')}.';
|
||||
str += '\n\n[$generatableName] can be one of '
|
||||
'${joinLast(type.types.map((t) => '[$t]'), ', ', ' or ')}.';
|
||||
str = str.trim();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
String? get generatableName {
|
||||
return _nameRemap[name] != null ? _nameRemap[name] : name;
|
||||
return _nameRemap[name] ?? name;
|
||||
}
|
||||
|
||||
set defaultValue(String? value) {
|
||||
|
@ -1834,10 +1871,14 @@ class TypeField extends Member {
|
|||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
Type? refType = parent.parent.getType('${parent.name}Ref');
|
||||
var interfaceOverride = refType?.hasField(name) ?? false;
|
||||
|
||||
if (docs!.isNotEmpty) gen.writeDocs(docs);
|
||||
if (optional) gen.write('@optional ');
|
||||
if (overrides) gen.write('@override ');
|
||||
if (overrides || interfaceOverride) gen.write('@override ');
|
||||
// Special case where Instance extends Obj, but 'classRef' is not optional
|
||||
// for Instance although it is for Obj.
|
||||
/*if (parent.name == 'Instance' && generatableName == 'classRef') {
|
||||
|
@ -1852,7 +1893,7 @@ class TypeField extends Member {
|
|||
if (typeName != 'dynamic') {
|
||||
typeName = '$typeName?';
|
||||
}
|
||||
gen.writeStatement('${typeName} ${generatableName};');
|
||||
gen.writeStatement('$typeName $generatableName;');
|
||||
if (parent.fields.any((field) => field.hasDocs)) gen.writeln();
|
||||
}
|
||||
}
|
||||
|
@ -1861,15 +1902,17 @@ class TypeField extends Member {
|
|||
if (fromParent) {
|
||||
String? typeName =
|
||||
api.isEnumName(type.name) ? '/*${type.name}*/ String' : type.name;
|
||||
gen.writeStatement('required $typeName ${generatableName},');
|
||||
gen.writeStatement('required $typeName $generatableName,');
|
||||
} else {
|
||||
gen.writeStatement('this.${generatableName},');
|
||||
gen.writeStatement('this.$generatableName,');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Enum extends Member {
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
final String? docs;
|
||||
|
||||
List<EnumValue> enums = [];
|
||||
|
@ -1900,24 +1943,27 @@ class Enum extends Member {
|
|||
String get prefix =>
|
||||
name.endsWith('Kind') ? name.substring(0, name.length - 4) : name;
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
gen.writeln();
|
||||
if (docs != null) gen.writeDocs(docs);
|
||||
gen.writeStatement('class ${name} {');
|
||||
gen.writeStatement('${name}._();');
|
||||
gen.writeStatement('class $name {');
|
||||
gen.writeStatement('$name._();');
|
||||
gen.writeln();
|
||||
enums.forEach((e) => e.generate(gen));
|
||||
for (var e in enums) {
|
||||
e.generate(gen);
|
||||
}
|
||||
gen.writeStatement('}');
|
||||
}
|
||||
|
||||
void generateAssert(DartGenerator gen) {
|
||||
gen.writeln('String assert${name}(String obj) {');
|
||||
gen.writeln('String assert$name(String obj) {');
|
||||
List<EnumValue> sorted = enums.toList()
|
||||
..sort((EnumValue e1, EnumValue e2) => e1.name!.compareTo(e2.name!));
|
||||
for (EnumValue value in sorted) {
|
||||
gen.writeln(' if (obj == "${value.name}") return obj;');
|
||||
}
|
||||
gen.writeln(' throw "invalid ${name}: \$obj";');
|
||||
gen.writeln(' throw "invalid $name: \$obj";');
|
||||
gen.writeln('}');
|
||||
gen.writeln('');
|
||||
}
|
||||
|
@ -1927,16 +1973,19 @@ class Enum extends Member {
|
|||
|
||||
class EnumValue extends Member {
|
||||
final Enum parent;
|
||||
@override
|
||||
final String? name;
|
||||
@override
|
||||
final String? docs;
|
||||
|
||||
EnumValue(this.parent, this.name, [this.docs]);
|
||||
|
||||
bool get isLast => parent.enums.last == this;
|
||||
|
||||
@override
|
||||
void generate(DartGenerator gen) {
|
||||
if (docs != null) gen.writeDocs(docs);
|
||||
gen.writeStatement("static const String k${name} = '${name}';");
|
||||
gen.writeStatement("static const String k$name = '$name';");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1954,6 +2003,7 @@ class TextOutputVisitor implements NodeVisitor {
|
|||
|
||||
TextOutputVisitor();
|
||||
|
||||
@override
|
||||
bool visitElementBefore(Element element) {
|
||||
if (element.tag == 'em' || element.tag == 'code') {
|
||||
buf.write('`');
|
||||
|
@ -1978,6 +2028,7 @@ class TextOutputVisitor implements NodeVisitor {
|
|||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
void visitText(Text text) {
|
||||
String? t = text.text;
|
||||
if (_em) {
|
||||
|
@ -1987,12 +2038,13 @@ class TextOutputVisitor implements NodeVisitor {
|
|||
}
|
||||
|
||||
if (_blockquote) {
|
||||
buf.write('${t}\n```');
|
||||
buf.write('$t\n```');
|
||||
} else {
|
||||
buf.write(t);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitElementAfter(Element element) {
|
||||
if (element.tag == 'em' || element.tag == 'code') {
|
||||
buf.write('`');
|
||||
|
@ -2014,6 +2066,7 @@ class TextOutputVisitor implements NodeVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => buf.toString().trim();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import '../common/src_gen_common.dart';
|
|||
/// dartdoc comments, automatically manages indent by counting curly braces, and
|
||||
/// automatically wraps doc comments on 80 char column boundaries.
|
||||
class DartGenerator {
|
||||
static const DEFAULT_COLUMN_BOUNDARY = 80;
|
||||
static const defaultColumnBoundary = 80;
|
||||
|
||||
final int colBoundary;
|
||||
|
||||
|
@ -20,7 +20,7 @@ class DartGenerator {
|
|||
|
||||
bool _previousWasEol = false;
|
||||
|
||||
DartGenerator({this.colBoundary = DEFAULT_COLUMN_BOUNDARY});
|
||||
DartGenerator({this.colBoundary = defaultColumnBoundary});
|
||||
|
||||
/// Write out the given dartdoc text, wrapping lines as necessary to flow
|
||||
/// along the column boundary. If [preferSingle] is true, and the docs would
|
||||
|
@ -32,7 +32,7 @@ class DartGenerator {
|
|||
// docs = docs.replaceAll('*/', '/');
|
||||
// docs = docs.replaceAll('/*', r'/\*');
|
||||
|
||||
docs.split('\n').forEach((line) => _writeln('/// ${line}'.trimRight()));
|
||||
docs.split('\n').forEach((line) => _writeln('/// $line'.trimRight()));
|
||||
|
||||
// if (!docs.contains('\n') && preferSingle) {
|
||||
// _writeln("/// ${docs}", true);
|
||||
|
@ -63,34 +63,35 @@ class DartGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
void writeln([String str = '']) => _write('${str}\n');
|
||||
void writeln([String str = '']) => _write('$str\n');
|
||||
|
||||
void write(String str) => _write(str);
|
||||
|
||||
void out(String str) => _buf.write(str);
|
||||
|
||||
void _writeln([String str = '', bool ignoreCurlies = false]) =>
|
||||
_write('${str}\n', ignoreCurlies);
|
||||
_write('$str\n', ignoreCurlies);
|
||||
|
||||
void _write(String str, [bool ignoreCurlies = false]) {
|
||||
for (final int rune in str.runes) {
|
||||
if (!ignoreCurlies) {
|
||||
if (rune == RUNE_LEFT_CURLY) {
|
||||
_indent = '${_indent} ';
|
||||
} else if (rune == RUNE_RIGHT_CURLY && _indent.length >= 2) {
|
||||
if (rune == $leftCurly) {
|
||||
_indent = '$_indent ';
|
||||
} else if (rune == $rightCurly && _indent.length >= 2) {
|
||||
_indent = _indent.substring(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (_previousWasEol && rune != RUNE_EOL) {
|
||||
if (_previousWasEol && rune != $eol) {
|
||||
_buf.write(_indent);
|
||||
}
|
||||
|
||||
_buf.write(String.fromCharCode(rune));
|
||||
|
||||
_previousWasEol = rune == RUNE_EOL;
|
||||
_previousWasEol = rune == $eol;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => _buf.toString();
|
||||
}
|
||||
|
|
|
@ -113,13 +113,13 @@ void _stampPubspec(Version version) {
|
|||
String? build = v.build.isEmpty ? null : v.build.join('+');
|
||||
v = Version(version.major, version.minor, v.patch,
|
||||
pre: pre, build: build);
|
||||
return '${pattern}${v.toString()}';
|
||||
return '$pattern${v.toString()}';
|
||||
} else {
|
||||
return line;
|
||||
}
|
||||
}).join('\n');
|
||||
|
||||
if (!found) throw '`${pattern}` not found';
|
||||
if (!found) throw '`$pattern` not found';
|
||||
|
||||
file.writeAsStringSync(text);
|
||||
}
|
||||
|
@ -133,6 +133,6 @@ void _checkUpdateChangelog(Version version) {
|
|||
bool containsReleaseNotes =
|
||||
text.split('\n').any((line) => line.startsWith(check));
|
||||
if (!containsReleaseNotes) {
|
||||
throw '`${check}` not found in the CHANGELOG.md file';
|
||||
throw '`$check` not found in the CHANGELOG.md file';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ String? _coerceRefType(String? typeName) {
|
|||
if (typeName == '@Object') typeName = 'ObjRef';
|
||||
if (typeName == 'Function') typeName = 'Func';
|
||||
if (typeName == '@Function') typeName = 'FuncRef';
|
||||
if (typeName!.startsWith('@')) typeName = typeName.substring(1) + 'Ref';
|
||||
if (typeName!.startsWith('@')) typeName = '${typeName.substring(1)}Ref';
|
||||
if (typeName == 'string') typeName = 'String';
|
||||
if (typeName == 'bool') typeName = 'boolean';
|
||||
if (typeName == 'num') typeName = 'BigDecimal';
|
||||
|
@ -103,8 +103,10 @@ class Api extends Member with ApiParseUtil {
|
|||
Map<String, List<String>> streamIdMap = {};
|
||||
final String scriptLocation;
|
||||
|
||||
@override
|
||||
String? get docs => null;
|
||||
|
||||
@override
|
||||
String get name => 'api';
|
||||
|
||||
Api(this.scriptLocation);
|
||||
|
@ -194,7 +196,7 @@ class Api extends Member with ApiParseUtil {
|
|||
JavaMethodArg('responseType', 'String'),
|
||||
JavaMethodArg('json', 'JsonObject')
|
||||
], (StatementWriter writer) {
|
||||
var generatedForwards = Set<String>();
|
||||
var generatedForwards = <String>{};
|
||||
|
||||
var sorted = methods.toList()
|
||||
..sort((m1, m2) {
|
||||
|
@ -319,7 +321,7 @@ class Api extends Member with ApiParseUtil {
|
|||
} else if (definition.startsWith('enum ')) {
|
||||
enums.add(Enum(name, scriptLocation, definition, docs));
|
||||
} else {
|
||||
throw 'unexpected entity: ${name}, ${definition}';
|
||||
throw 'unexpected entity: $name, $definition';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,14 +362,16 @@ class Api extends Member with ApiParseUtil {
|
|||
if (n.tag != 'h3') return n.tag;
|
||||
return '${n.tag}:[${n.children!.map((c) => printNode(c)).join(', ')}]';
|
||||
} else {
|
||||
return '${n}';
|
||||
return '$n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Enum extends Member {
|
||||
@override
|
||||
final String name;
|
||||
final String scriptLocation;
|
||||
@override
|
||||
final String? docs;
|
||||
|
||||
List<EnumValue> enums = [];
|
||||
|
@ -423,7 +427,9 @@ class EnumParser extends Parser {
|
|||
|
||||
class EnumValue extends Member {
|
||||
final Enum parent;
|
||||
@override
|
||||
final String? name;
|
||||
@override
|
||||
final String? docs;
|
||||
|
||||
EnumValue(this.parent, this.name, [this.docs]);
|
||||
|
@ -438,6 +444,7 @@ abstract class Member {
|
|||
|
||||
String? get name;
|
||||
|
||||
@override
|
||||
String toString() => name!;
|
||||
}
|
||||
|
||||
|
@ -456,6 +463,7 @@ class MemberType extends Member {
|
|||
|
||||
bool get isValueAndSentinel => types.length == 2 && hasSentinel;
|
||||
|
||||
@override
|
||||
String? get name {
|
||||
if (types.isEmpty) return '';
|
||||
if (types.length == 1) return types.first.ref;
|
||||
|
@ -486,7 +494,9 @@ class MemberType extends Member {
|
|||
while (parser.consume('[')) {
|
||||
parser.expect(']');
|
||||
if (isMulti) {
|
||||
types.forEach((t) => t.arrayDepth++);
|
||||
for (var t in types) {
|
||||
t.arrayDepth++;
|
||||
}
|
||||
} else {
|
||||
ref.arrayDepth++;
|
||||
}
|
||||
|
@ -498,8 +508,10 @@ class MemberType extends Member {
|
|||
}
|
||||
|
||||
class Method extends Member {
|
||||
@override
|
||||
final String name;
|
||||
final String scriptLocation;
|
||||
@override
|
||||
final String? docs;
|
||||
|
||||
MemberType returnType = MemberType();
|
||||
|
@ -595,7 +607,7 @@ class Method extends Member {
|
|||
for (MethodArg arg in args) {
|
||||
if (!includeOptional && arg.optional) continue;
|
||||
var argName = arg.name;
|
||||
String op = arg.optional ? 'if (${argName} != null) ' : '';
|
||||
String op = arg.optional ? 'if ($argName != null) ' : '';
|
||||
if (arg.isEnumType) {
|
||||
writer
|
||||
.addLine('${op}params.addProperty("$argName", $argName.name());');
|
||||
|
@ -625,7 +637,9 @@ class Method extends Member {
|
|||
class MethodArg extends Member {
|
||||
final Method parent;
|
||||
final TypeRef type;
|
||||
@override
|
||||
String? name;
|
||||
@override
|
||||
String? docs;
|
||||
bool optional = false;
|
||||
|
||||
|
@ -712,8 +726,10 @@ class TextOutputVisitor implements NodeVisitor {
|
|||
|
||||
TextOutputVisitor();
|
||||
|
||||
@override
|
||||
String toString() => buf.toString().trim();
|
||||
|
||||
@override
|
||||
bool visitElementBefore(Element element) {
|
||||
if (element.tag == 'em') {
|
||||
buf.write('[');
|
||||
|
@ -732,12 +748,14 @@ class TextOutputVisitor implements NodeVisitor {
|
|||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
void visitText(Text text) {
|
||||
String? t = text.text;
|
||||
if (_inRef) t = _coerceRefType(t);
|
||||
buf.write(t);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitElementAfter(Element element) {
|
||||
if (element.tag == 'em') {
|
||||
buf.write(']');
|
||||
|
@ -758,8 +776,10 @@ class Type extends Member {
|
|||
final Api parent;
|
||||
final String scriptLocation;
|
||||
String? rawName;
|
||||
@override
|
||||
String? name;
|
||||
String? superName;
|
||||
@override
|
||||
final String? docs;
|
||||
List<TypeField> fields = [];
|
||||
|
||||
|
@ -879,6 +899,7 @@ class TypeField extends Member {
|
|||
final Type parent;
|
||||
final String? _docs;
|
||||
MemberType type = MemberType();
|
||||
@override
|
||||
String? name;
|
||||
bool optional = false;
|
||||
String? defaultValue;
|
||||
|
@ -900,11 +921,12 @@ class TypeField extends Member {
|
|||
return 'get${titleCase(remappedName!)}';
|
||||
}
|
||||
|
||||
@override
|
||||
String? get docs {
|
||||
String str = _docs == null ? '' : _docs!;
|
||||
if (type.isMultipleReturns) {
|
||||
str += '\n\n@return one of '
|
||||
'${joinLast(type.types.map((t) => '<code>${t}</code>'), ', ', ' or ')}';
|
||||
'${joinLast(type.types.map((t) => '<code>$t</code>'), ', ', ' or ')}';
|
||||
str = str.trim();
|
||||
}
|
||||
if (optional) {
|
||||
|
@ -923,9 +945,9 @@ class TypeField extends Member {
|
|||
for (TypeRef t in type.types) {
|
||||
String refName = t.name!;
|
||||
if (refName.endsWith('Ref')) {
|
||||
refName = '@' + refName.substring(0, refName.length - 3);
|
||||
refName = '@${refName.substring(0, refName.length - 3)}';
|
||||
}
|
||||
w.addLine('if (elem.get("type").getAsString().equals("${refName}")) '
|
||||
w.addLine('if (elem.get("type").getAsString().equals("$refName")) '
|
||||
'return new ${t.name}(elem);');
|
||||
}
|
||||
w.addLine('return null;');
|
||||
|
@ -1023,11 +1045,11 @@ class TypeRef {
|
|||
if (genericTypes != null) {
|
||||
return '$name<${genericTypes!.join(', ')}>';
|
||||
} else if (isSimple) {
|
||||
if (arrayDepth == 2) return 'List<List<${javaBoxedName}>>';
|
||||
if (arrayDepth == 1) return 'List<${javaBoxedName}>';
|
||||
if (arrayDepth == 2) return 'List<List<$javaBoxedName>>';
|
||||
if (arrayDepth == 1) return 'List<$javaBoxedName>';
|
||||
} else {
|
||||
if (arrayDepth == 2) return 'ElementList<ElementList<${javaBoxedName}>>';
|
||||
if (arrayDepth == 1) return 'ElementList<${javaBoxedName}>';
|
||||
if (arrayDepth == 2) return 'ElementList<ElementList<$javaBoxedName>>';
|
||||
if (arrayDepth == 1) return 'ElementList<$javaBoxedName>';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
@ -1161,5 +1183,6 @@ class TypeRef {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => ref!;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ class JavaGenerator {
|
|||
/// The java source directory into which files are generated.
|
||||
final String srcDirPath;
|
||||
|
||||
Set<String> _generatedPaths = Set();
|
||||
final Set<String> _generatedPaths = {};
|
||||
|
||||
JavaGenerator(this.srcDirPath);
|
||||
|
||||
|
@ -117,12 +117,12 @@ class TypeWriter {
|
|||
bool isEnum = false;
|
||||
String? javadoc;
|
||||
String modifiers = 'public';
|
||||
final Set<String> _imports = Set<String>();
|
||||
final Set<String> _imports = <String>{};
|
||||
String? superclassName;
|
||||
List<String> interfaceNames = <String>[];
|
||||
final StringBuffer _content = StringBuffer();
|
||||
final List<String> _fields = <String>[];
|
||||
final Map<String, String> _methods = Map<String, String>();
|
||||
final Map<String, String> _methods = <String, String>{};
|
||||
final String scriptLocation;
|
||||
|
||||
TypeWriter(String typeName, this.scriptLocation)
|
||||
|
@ -265,10 +265,12 @@ class TypeWriter {
|
|||
buffer.writeln('package $pkgName;');
|
||||
buffer.writeln();
|
||||
buffer.writeln(
|
||||
'// This file is generated by the script: ${scriptLocation} in dart-lang/sdk.');
|
||||
'// This file is generated by the script: $scriptLocation in dart-lang/sdk.');
|
||||
buffer.writeln();
|
||||
addImport(superclassName);
|
||||
interfaceNames.forEach((t) => addImport(t));
|
||||
for (var t in interfaceNames) {
|
||||
addImport(t);
|
||||
}
|
||||
if (_imports.isNotEmpty) {
|
||||
var sorted = _imports.toList()..sort();
|
||||
for (String typeName in sorted) {
|
||||
|
@ -297,10 +299,10 @@ class TypeWriter {
|
|||
}
|
||||
buffer.writeln(' {');
|
||||
buffer.write(_content.toString());
|
||||
_fields.forEach((f) {
|
||||
for (var f in _fields) {
|
||||
buffer.writeln();
|
||||
buffer.write(f);
|
||||
});
|
||||
}
|
||||
_methods.keys.toList()
|
||||
..sort()
|
||||
..forEach((String methodName) {
|
||||
|
|
Loading…
Reference in a new issue