sdk
sdk copied to clipboard
Provide mechanism to mark API as deprecated by a particular Dart SDK version
We'd like to track readiness of code for upcoming API deprecations. E.g, if an API is slated to be removed in Dart 3.0, we'd like to be able to mark that and trigger warnings.
Would adding an optional sdk version named param to Deprecated make sense?
@lrhn @mit-mit @natebosch @leafpetersen
The high-level idea here is that this would enable us to do something like:
- Support annotations like
@Deprecated("Use a list literal, [], or the List.filled constructor instead", 3.0) - Add those annotations to all the Dart 3 API discontinuations now, for our next Dart 2.x release
- Add a flag like
--enable-experiment=error-on-discontinued-dart-3-api-usetodartandfluttertools, and make that fail when they see any use of a@Deprecated("...",3.0)API. - Get our bots to pass with that flag
Later this would also enable things like pub.dev to add "Dart 3 compatible" (combined with a check for no use of legacy null mode).
Does that make sense?
We should not have any deprecated APIs that survive a major version increment, so would it suffice to simply consider all deprecated declarations as errors?
(Would that just be the same as putting deprecated_member_use: error somewhere in analysis_options.yaml?)
We can definitely put an extra (optional) field on Deprecated, with the version by which the deprecated member is intended to be removed.
Since the Deprecated class is used outside of the Dart SDK, the version field should be interpreted as a version of the surrounding thing (SDK version of platform libraries, package version for packages, even SDK-owned packages).
It would not really make sense to have SDK-version dependencies in non-platform libraries.
Another option is to not use a language version as the "tag", but provide a unique tag string instead. We can use "3.0" for that if we want to, but we can also use "DART_SDK_3_0_UPDATE" or whatever we want, and other people's packages can use their own string tags, for their own changes.
Then the analyzer flag could be something like --deprecations-are-errors=tag1,tag2, and that will make any @Deprecated(..., tag: "tag1") or ...tag: "tag2"... be reported as errors instead of warnings. (With a corresponding analysis-options.yaml entry.)
This looks like a more generally applicable feature, and one which can be used by non-SDK developers too.
(The risk of name-clash should be minimal, even just using "SDK3" as our tag should be perfectly safe.)
We still need to allow some uses of the deprecated members, inside the declaring library/package, since it hasn't actually removed it yet. So, we can't just compile as if the code wasn't there.
We should not have any deprecated APIs that survive a major version increment
Historically we've had a gap between "should not" and "won't". I do think customers should still treat deprecations as if they will be removed in the next major version.
I think the filter we want is for the location of the deprecated definition. Something like --sdk-deprecations-are-errors (which could live alongside --deprecations-are-errors=package1,package2 if we needed)
I like the idea of making it per-package. I'd even drop a having a special flag for the SDK, and just treat it as a package named dart, so you can write --deprecations-are-errors=dart,test.
We should not have any deprecated APIs that survive a major version increment
We already know that this is the case.
I think the filter we want is for the location of the deprecated definition.
@natebosch @lrhn can you clarify why you think we need the ability to filter by package? What would we use that for?
If this feature is useful to us, it's probably useful to others as well.
Other people don't make SDKs, so the thing they version are packages.
The corresponding problem would be "what would break if package:foo removed all the deprecated features" or "...deprecated feature that are scheduled to be removed in release 3.0.0".
You'd be able to test that by saying --depreacations-are-errors=foo and maybe --deprecations-are-errors=foo:3.0.0.
For the SDK, we'd do --deprecations-are-errors=dart:3.0.0 (treating the SDK as a package named dart, which is a remarkably good abstraction in many cases).
Closing as we didn't end up needing this