Skip to content

Commit b36d861

Browse files
author
Dart CI
committed
Version 2.17.0-11.0.dev
Merge commit '0e5a539315e690eb1bfac9ecf8a676822fcbf714' into 'dev'
2 parents f1c98a5 + 0e5a539 commit b36d861

File tree

8 files changed

+135
-5
lines changed

8 files changed

+135
-5
lines changed

pkg/vm/lib/transformations/to_string_transformer.dart

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class ToStringVisitor extends RecursiveVisitor {
1919
/// 'package:flutter/foundation.dart'.
2020
final Set<String> _packageUris;
2121

22+
final Map<Class, bool> _inheritedKeepAnnotations = {};
23+
2224
/// Turn 'dart:ui' into 'dart:ui', or
2325
/// 'package:flutter/src/semantics_event.dart' into 'package:flutter'.
2426
String _importUriToPackage(Uri importUri) =>
@@ -29,7 +31,18 @@ class ToStringVisitor extends RecursiveVisitor {
2931
.contains(_importUriToPackage(node.enclosingLibrary.importUri));
3032
}
3133

32-
bool _hasKeepAnnotation(Procedure node) {
34+
bool _hasKeepAnnotation(Procedure node) =>
35+
_hasPragma(node, 'flutter:keep-to-string');
36+
37+
bool _hasKeepAnnotationOnClass(Class node) =>
38+
_hasPragma(node, 'flutter:keep-to-string-in-subtypes');
39+
40+
bool _hasInheritedKeepAnnotation(Class node) =>
41+
_inheritedKeepAnnotations[node] ??= (_hasKeepAnnotationOnClass(node) ||
42+
node.supers
43+
.any((Supertype t) => _hasInheritedKeepAnnotation(t.classNode)));
44+
45+
bool _hasPragma(Annotatable node, String pragma) {
3346
for (ConstantExpression expression
3447
in node.annotations.whereType<ConstantExpression>()) {
3548
if (expression.constant is! InstanceConstant) {
@@ -43,8 +56,7 @@ class ToStringVisitor extends RecursiveVisitor {
4356
for (var fieldRef in constant.fieldValues.keys) {
4457
if (fieldRef.asField.name.text == 'name') {
4558
Constant? name = constant.fieldValues[fieldRef];
46-
return name is StringConstant &&
47-
name.value == 'flutter:keep-to-string';
59+
return name is StringConstant && name.value == pragma;
4860
}
4961
}
5062
return false;
@@ -61,7 +73,8 @@ class ToStringVisitor extends RecursiveVisitor {
6173
!node.isAbstract &&
6274
!node.enclosingClass!.isEnum &&
6375
_isInTargetPackage(node) &&
64-
!_hasKeepAnnotation(node)) {
76+
!_hasKeepAnnotation(node) &&
77+
!_hasInheritedKeepAnnotation(node.enclosingClass!)) {
6578
node.function.body!.replaceWith(
6679
ReturnStatement(
6780
SuperMethodInvocation(

pkg/vm/testcases/transformations/to_string_transformer/lib/main.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'dart:convert';
66

77
const keepToString = pragma('flutter:keep-to-string');
8+
const keepToStringInSubtypes = pragma('flutter:keep-to-string-in-subtypes');
89

910
String toString() => 'I am static';
1011

@@ -26,9 +27,28 @@ class Keep {
2627
String toString() => 'I am a Keep';
2728
}
2829

30+
@keepToStringInSubtypes
31+
class Base1 {}
32+
33+
class Base2 extends Base1 {}
34+
35+
class Base3 extends Object with Base2 {}
36+
37+
class KeepInherited implements Base3 {
38+
@override
39+
String toString() => 'Heir';
40+
}
41+
42+
class MyException implements Exception {
43+
@override
44+
String toString() => 'A very detailed message';
45+
}
46+
2947
void main() {
3048
final IFoo foo = Foo();
3149
print(foo.toString());
3250
print(Keep().toString());
3351
print(FooEnum.B.toString());
52+
print(KeepInherited().toString());
53+
print(MyException().toString());
3454
}

pkg/vm/testcases/transformations/to_string_transformer/not_transformed.expect

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,54 @@ class Keep extends core::Object {
3939
method toString() → core::String
4040
return "I am a Keep";
4141
}
42+
@#C16
43+
class Base1 extends core::Object {
44+
synthetic constructor •() → self::Base1
45+
: super core::Object::•()
46+
;
47+
}
48+
class Base2 extends self::Base1 {
49+
synthetic constructor •() → self::Base2
50+
: super self::Base1::•()
51+
;
52+
}
53+
abstract class _Base3&Object&Base2 extends core::Object implements self::Base2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
54+
const synthetic constructor •() → self::_Base3&Object&Base2
55+
: super core::Object::•()
56+
;
57+
}
58+
class Base3 extends self::_Base3&Object&Base2 {
59+
synthetic constructor •() → self::Base3
60+
: super self::_Base3&Object&Base2::•()
61+
;
62+
}
63+
class KeepInherited extends core::Object implements self::Base3 {
64+
synthetic constructor •() → self::KeepInherited
65+
: super core::Object::•()
66+
;
67+
@#C1
68+
method toString() → core::String
69+
return "Heir";
70+
}
71+
class MyException extends core::Object implements core::Exception {
72+
synthetic constructor •() → self::MyException
73+
: super core::Object::•()
74+
;
75+
@#C1
76+
method toString() → core::String
77+
return "A very detailed message";
78+
}
4279
static const field core::pragma keepToString = #C14;
80+
static const field core::pragma keepToStringInSubtypes = #C16;
4381
static method toString() → core::String
4482
return "I am static";
4583
static method main() → void {
4684
final self::IFoo foo = new self::Foo::•();
4785
core::print(foo.{self::IFoo::toString}(){() → core::String});
4886
core::print(new self::Keep::•().{self::Keep::toString}(){() → core::String});
4987
core::print(#C7.{self::FooEnum::toString}(){() → core::String});
88+
core::print(new self::KeepInherited::•().{self::KeepInherited::toString}(){() → core::String});
89+
core::print(new self::MyException::•().{self::MyException::toString}(){() → core::String});
5090
}
5191
constants {
5292
#C1 = core::_Override {}
@@ -63,4 +103,6 @@ constants {
63103
#C12 = "flutter:keep-to-string"
64104
#C13 = null
65105
#C14 = core::pragma {name:#C12, options:#C13}
106+
#C15 = "flutter:keep-to-string-in-subtypes"
107+
#C16 = core::pragma {name:#C15, options:#C13}
66108
}

pkg/vm/testcases/transformations/to_string_transformer/transformed.expect

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,54 @@ class Keep extends core::Object {
3939
method toString() → core::String
4040
return "I am a Keep";
4141
}
42+
@#C16
43+
class Base1 extends core::Object {
44+
synthetic constructor •() → self::Base1
45+
: super core::Object::•()
46+
;
47+
}
48+
class Base2 extends self::Base1 {
49+
synthetic constructor •() → self::Base2
50+
: super self::Base1::•()
51+
;
52+
}
53+
abstract class _Base3&Object&Base2 extends core::Object implements self::Base2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
54+
const synthetic constructor •() → self::_Base3&Object&Base2
55+
: super core::Object::•()
56+
;
57+
}
58+
class Base3 extends self::_Base3&Object&Base2 {
59+
synthetic constructor •() → self::Base3
60+
: super self::_Base3&Object&Base2::•()
61+
;
62+
}
63+
class KeepInherited extends core::Object implements self::Base3 {
64+
synthetic constructor •() → self::KeepInherited
65+
: super core::Object::•()
66+
;
67+
@#C1
68+
method toString() → core::String
69+
return "Heir";
70+
}
71+
class MyException extends core::Object implements core::Exception {
72+
synthetic constructor •() → self::MyException
73+
: super core::Object::•()
74+
;
75+
@#C1
76+
method toString() → core::String
77+
return "A very detailed message";
78+
}
4279
static const field core::pragma keepToString = #C14;
80+
static const field core::pragma keepToStringInSubtypes = #C16;
4381
static method toString() → core::String
4482
return "I am static";
4583
static method main() → void {
4684
final self::IFoo foo = new self::Foo::•();
4785
core::print(foo.{self::IFoo::toString}(){() → core::String});
4886
core::print(new self::Keep::•().{self::Keep::toString}(){() → core::String});
4987
core::print(#C7.{self::FooEnum::toString}(){() → core::String});
88+
core::print(new self::KeepInherited::•().{self::KeepInherited::toString}(){() → core::String});
89+
core::print(new self::MyException::•().{self::MyException::toString}(){() → core::String});
5090
}
5191
constants {
5292
#C1 = core::_Override {}
@@ -63,4 +103,6 @@ constants {
63103
#C12 = "flutter:keep-to-string"
64104
#C13 = null
65105
#C14 = core::pragma {name:#C12, options:#C13}
106+
#C15 = "flutter:keep-to-string-in-subtypes"
107+
#C16 = core::pragma {name:#C15, options:#C13}
66108
}

runtime/docs/pragmas.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,14 @@ Additionally, they are categorized into "safe" and "unsafe" forms: "safe" pragma
4141
| Pragma | Meaning |
4242
| --- | --- |
4343
| `vm:testing.unsafe.trace-entrypoints-fn` | [Observing which flow-graph-level entry-point was used when a function was called](compiler/frontend/testing_trace_entrypoints_pragma.md) |
44+
45+
## Flutter toString transformer pragmas
46+
47+
These pragmas are useful to exclude certain toString methods from toString transformation,
48+
which is enabled with `--delete-tostring-package-uri` option in kernel compilers and
49+
used by Flutter to remove certain toString methods in release mode to reduce size.
50+
51+
| Pragma | Meaning |
52+
| --- | --- |
53+
| `flutter:keep-to-string` | Avoid transforming the annotated toString method. |
54+
| `flutter:keep-to-string-in-subtypes` | Avoid transforming toString methods in all subtypes of the annotated class. |

sdk/lib/core/errors.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ part of dart.core;
6464
/// For example, the [String.contains] method will use a [RangeError]
6565
/// if its `startIndex` isn't in the range `0..length`,
6666
/// which is easily created by `RangeError.range(startIndex, 0, length)`.
67+
@pragma('flutter:keep-to-string-in-subtypes')
6768
class Error {
6869
Error(); // Prevent use as mixin.
6970

sdk/lib/core/exceptions.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ part of dart.core;
1616
/// is discouraged in library code since it doesn't give users a precise
1717
/// type they can catch. It may be reasonable to use instances of this
1818
/// class in tests or during development.
19+
@pragma('flutter:keep-to-string-in-subtypes')
1920
abstract class Exception {
2021
factory Exception([var message]) => _Exception(message);
2122
}

tools/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ CHANNEL dev
2727
MAJOR 2
2828
MINOR 17
2929
PATCH 0
30-
PRERELEASE 10
30+
PRERELEASE 11
3131
PRERELEASE_PATCH 0

0 commit comments

Comments
 (0)