mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Use ToStringTransformer from dart frontend_server (#23915)
This commit is contained in:
parent
eb899383a6
commit
3e17bbc6c4
@ -16,8 +16,8 @@ import 'package:frontend_server/frontend_server.dart' as frontend
|
||||
listenAndCompile,
|
||||
argParser,
|
||||
usage,
|
||||
ProgramTransformer;
|
||||
import 'package:kernel/ast.dart';
|
||||
ProgramTransformer,
|
||||
ToStringTransformer;
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:vm/incremental_compiler.dart';
|
||||
|
||||
@ -150,7 +150,7 @@ Future<int> starter(
|
||||
]);
|
||||
compiler ??= _FlutterFrontendCompiler(
|
||||
output,
|
||||
transformer: ToStringTransformer(null, deleteToStringPackageUris),
|
||||
transformer: frontend.ToStringTransformer(null, deleteToStringPackageUris),
|
||||
);
|
||||
|
||||
await compiler.compile(input, options);
|
||||
@ -170,7 +170,7 @@ Future<int> starter(
|
||||
}
|
||||
|
||||
compiler ??= _FlutterFrontendCompiler(output,
|
||||
transformer: ToStringTransformer(transformer, deleteToStringPackageUris),
|
||||
transformer: frontend.ToStringTransformer(transformer, deleteToStringPackageUris),
|
||||
useDebuggerModuleNames: options['debugger-module-names'] as bool,
|
||||
emitDebugMetadata: options['experimental-emit-debug-metadata'] as bool,
|
||||
unsafePackageSerialization:
|
||||
@ -184,86 +184,3 @@ Future<int> starter(
|
||||
frontend.listenAndCompile(compiler, input ?? stdin, options, completer);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
// Transformer/visitor for toString
|
||||
// If we add any more of these, they really should go into a separate library.
|
||||
|
||||
/// A [RecursiveVisitor] that replaces [Object.toString] overrides with
|
||||
/// `super.toString()`.
|
||||
class ToStringVisitor extends RecursiveVisitor<void> {
|
||||
/// The [packageUris] must not be null.
|
||||
ToStringVisitor(this._packageUris) : assert(_packageUris != null);
|
||||
|
||||
/// A set of package URIs to apply this transformer to, e.g. 'dart:ui' and
|
||||
/// 'package:flutter/foundation.dart'.
|
||||
final Set<String> _packageUris;
|
||||
|
||||
/// Turn 'dart:ui' into 'dart:ui', or
|
||||
/// 'package:flutter/src/semantics_event.dart' into 'package:flutter'.
|
||||
String _importUriToPackage(Uri importUri) => '${importUri.scheme}:${importUri.pathSegments.first}';
|
||||
|
||||
bool _isInTargetPackage(Procedure node) {
|
||||
return _packageUris.contains(_importUriToPackage(node.enclosingLibrary.importUri));
|
||||
}
|
||||
|
||||
bool _hasKeepAnnotation(Procedure node) {
|
||||
for (ConstantExpression expression in node.annotations.whereType<ConstantExpression>()) {
|
||||
if (expression.constant is! InstanceConstant) {
|
||||
continue;
|
||||
}
|
||||
final InstanceConstant constant = expression.constant as InstanceConstant;
|
||||
if (constant.classNode.name == '_KeepToString' && constant.classNode.enclosingLibrary.importUri.toString() == 'dart:ui') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
void visitProcedure(Procedure node) {
|
||||
if (
|
||||
node.name.text == 'toString' &&
|
||||
node.enclosingClass != null &&
|
||||
node.enclosingLibrary != null &&
|
||||
!node.isStatic &&
|
||||
!node.isAbstract &&
|
||||
!node.enclosingClass.isEnum &&
|
||||
_isInTargetPackage(node) &&
|
||||
!_hasKeepAnnotation(node)
|
||||
) {
|
||||
node.function.body.replaceWith(
|
||||
ReturnStatement(
|
||||
SuperMethodInvocation(
|
||||
node.name,
|
||||
Arguments(<Expression>[]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void defaultMember(Member node) {}
|
||||
}
|
||||
|
||||
/// Replaces [Object.toString] overrides with calls to super for the specified
|
||||
/// [packageUris].
|
||||
class ToStringTransformer extends frontend.ProgramTransformer {
|
||||
/// The [packageUris] parameter must not be null, but may be empty.
|
||||
ToStringTransformer(this._child, this._packageUris) : assert(_packageUris != null);
|
||||
|
||||
final frontend.ProgramTransformer _child;
|
||||
|
||||
/// A set of package URIs to apply this transformer to, e.g. 'dart:ui' and
|
||||
/// 'package:flutter/foundation.dart'.
|
||||
final Set<String> _packageUris;
|
||||
|
||||
@override
|
||||
void transform(Component component) {
|
||||
assert(_child is! ToStringTransformer);
|
||||
if (_packageUris.isNotEmpty) {
|
||||
component.visitChildren(ToStringVisitor(_packageUris));
|
||||
}
|
||||
_child?.transform(component);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_frontend_server/server.dart';
|
||||
import 'package:frontend_server/frontend_server.dart' as frontend show ProgramTransformer;
|
||||
import 'package:frontend_server/frontend_server.dart' as frontend
|
||||
show ProgramTransformer, ToStringTransformer, ToStringVisitor;
|
||||
import 'package:kernel/kernel.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
@ -25,7 +25,7 @@ void main(List<String> args) async {
|
||||
};
|
||||
|
||||
test('No packages', () {
|
||||
final ToStringTransformer transformer = ToStringTransformer(null, <String>{});
|
||||
final frontend.ToStringTransformer transformer = frontend.ToStringTransformer(null, <String>{});
|
||||
|
||||
final MockComponent component = MockComponent();
|
||||
transformer.transform(component);
|
||||
@ -33,7 +33,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('dart:ui package', () {
|
||||
final ToStringTransformer transformer = ToStringTransformer(null, uiAndFlutter);
|
||||
final frontend.ToStringTransformer transformer = frontend.ToStringTransformer(null, uiAndFlutter);
|
||||
|
||||
final MockComponent component = MockComponent();
|
||||
transformer.transform(component);
|
||||
@ -42,7 +42,7 @@ void main(List<String> args) async {
|
||||
|
||||
test('Child transformer', () {
|
||||
final MockTransformer childTransformer = MockTransformer();
|
||||
final ToStringTransformer transformer = ToStringTransformer(childTransformer, <String>{});
|
||||
final frontend.ToStringTransformer transformer = frontend.ToStringTransformer(childTransformer, <String>{});
|
||||
|
||||
final MockComponent component = MockComponent();
|
||||
transformer.transform(component);
|
||||
@ -51,7 +51,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor ignores non-toString procedures', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
when(procedure.name).thenReturn(Name('main'));
|
||||
when(procedure.annotations).thenReturn(const <Expression>[]);
|
||||
@ -65,7 +65,7 @@ void main(List<String> args) async {
|
||||
//
|
||||
// void main() {}
|
||||
// String toString() => 'why?';
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -84,7 +84,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor ignores abstract toString', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -103,7 +103,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor ignores static toString', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -122,7 +122,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor ignores enum toString', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -141,7 +141,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor ignores non-specified libraries', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -160,7 +160,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor ignores @keepToString', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -198,7 +198,7 @@ void main(List<String> args) async {
|
||||
}
|
||||
|
||||
test('ToStringVisitor replaces toString in specified libraries (dart:ui)', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
@ -219,7 +219,7 @@ void main(List<String> args) async {
|
||||
});
|
||||
|
||||
test('ToStringVisitor replaces toString in specified libraries (package:flutter)', () {
|
||||
final ToStringVisitor visitor = ToStringVisitor(uiAndFlutter);
|
||||
final frontend.ToStringVisitor visitor = frontend.ToStringVisitor(uiAndFlutter);
|
||||
final MockProcedure procedure = MockProcedure();
|
||||
final MockFunctionNode function = MockFunctionNode();
|
||||
final MockStatement statement = MockStatement();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user