Open matanlurey opened 2 years ago
I'm guessing that the second (abstract) class was intended to be AllowOtherwise
.
I might suggest that we define AllowOtherwise
to be concrete with a field whose value is the name of the annotation for which the instance is the value. In other words:
class AllowOtherwise {
final String annotationName;
const AllowOtherwise(this.annotationName);
}
That would allow for better messages, such as "The method 'exampleUnsafeMethod' should not be invoked except in methods annotated with 'allowSynchronousLayout'."
I'm not sure how useful these annotations would be for Flutter developers, so I might propose that we prototype them internally first.
to be concrete with a field whose value is the name of the annotation
I would prefer not to use stringly-typed annotations :)
I'm not sure how useful these annotations would be for Flutter developers
This is a general use annotation, the example I gave was specific to web (though, still impacts Flutter web).
@goderbauer For visibility.
One potential use-case I can see for this in Flutter land is making sure certain blocking IO methods are not called from build/layout methods, since that can stall rendering - while still allowing them in other cases, since using blocking io is safe to do from an isolate/compute:
example:
bad:
class FooWidget extends StatelessWidget {
Widget build(BuildContext context) {
return Image.memory(File('data.png').readAsBytesSync()); // BAD!
}
}
ok:
class FooWidgetState extends State<FooWidget> {
Uint8List? data;
Uint8List _loadData(_) {
return File('data.png').readAsBytesSync(); // OK
}
initState() {
super.initState();
compute(_loadData, null).then((bytes) {
setState(() => data = bytes);
});
}
Widget build(BuildContext context) {
...
}
}
not including stuff like existsSync(), which is generally always OK
There are methods that are generally unsafe to use, and you'd want to avoid using unintentionally.
For example, on the web, some methods and getters/setters cause forced synchronous layout.
Now, once option would be creating two custom annotations (
@avoidSynchronousLayout
,@allowSynchronousLayout
), and go and update libraries and add the former annotation on some library APIs, and the latter annotation on other APIs:However, that seems pretty specialized for something that actually could be used by different libraries/frameworks (similar to
@useResult
).What if we instead created two classes:
(There might be a cuter way to design the classes, but really I'm just interested in the end result, which is the ability to define unsafe APIs and opt-ins for using those unsafe APIs)
/cc @srawlins