[RFC] Experimental APIs
sfPlayer1 opened this issue Β· 39 comments
In order to support API features that are likely to change (1.16 nether biome selection) or difficult to get right from the start, I am proposing to offer experimental APIs in Fabric API. Those APIs are marked via @Deprecated
and can both extend existing modules or form new ones.
The @Deprecated
annotation use is in line with how Java annotates its preview features, which serve a similar purpose. Additionally the associated Javadoc has to include @deprecated Experimental feature, may be removed or changed without further notice <optional explanation why it is experimental>
.
Addition of and incompatible changes to experimental features will incur a minor version bump, the major version and module version (v0/v1/...) remain the same.
Modules such as fabric-transfer-api-v1
now use a combination of a module lifecycle field, annotations, and Javadoc to indicate their experimental status:
fabric/fabric-transfer-api-v1/src/main/resources/fabric.mod.json
Lines 27 to 29 in 58bef3f
This is now encoded in the contribution guidelines, which should be a sufficient reference.
We may add another annotation targetting classes, fields, and methods to accompany @Deprecated
(for easy lookup, added to api base most likely, or use guava @Beta
as well)
Quick vote:
π for guava @Beta
annotation etc. in addition to @Deprecated
on snapshot hooks
π for just @Deprecated
on snapshot hooks
Quick reasoning:
@Beta
alone cannot warn users efficiently. @Deprecated
alone cannot distinguish from apis scheduled for release-stage removal or in no-source distributions. Combined would be the most informative.
Another quick note: We talked about jetbrain annotations has annotations like @ApiStatus.Experimental
, which may serve notification purposes with ide integration.
Jetbrains Annotations are useful for stuff like ScheduledForRemoval and Experimental, but do IDEs support them?
Here are all of the annotation APIs I know of:
- JetBrains Annotations - Maven
- Supported by JetBrains IDEs by default
- Includes several annotations for APIs (
Experimental
,Internal
,ScheduledForRemoval
,AvailableSince
,NonExtendable
, andOverrideOnly
) - Includes several other annotations related to compile-time checks, safety, and method contracts
- @API Guardian - Maven
- Supported by JetBrains IDEs by default
- Includes one annotation with an enum for levels of support (
INTERNAL
,DEPRECATED
,EXPERIMENTAL
,MAINTAINED
, andSTABLE
)
- Guava Annotations - Maven
- Supported by JetBrains IDEs by default
- Includes one annotation for APIs (
Beta
) - Includes three other annotations related to GWT and testing
I can't speak on Eclipse support as I haven't used it in like six years.
I personally prefer JetBrains Annotations because they allow showing detailed API info and additional optional info.
Here are the cons of each:
- JetBrains Annotations
- Maybe not interpreted by other IDEs? An annotation processor is preferable.
- API Guardian
- Too few associated tools available from official site (e.g. no annotation processor)
- Guava Annotations
- No standalone distribution, shipped with guava
- May conflict with the version of guava vanilla uses
All in favor of Jetbrains annotations voteπ
All in favor of literally anything else vote π
I prefer JetBrains, because JetBrains IDEs will give a warning, and everything else can be configured to do so easily (or does so by default). Whereas anything else, will not be supported by literally anything.
We need to decide on one annotation standard for ALL projects. This includes yarn, loom, api and loader.
The choice we make imo should be able to support type annotations such as
Foo<@Nullable Bar>
and Foo.@Nullable Bar
I think you should talk about the different options and the pros and cons before starting a poll like that.
#499 (comment)
#499 (comment)
also most the other comments in this issue are that
This isnβt the right issue for the null checking annotations either. Iβd create a new issue about it.
I mean JetBrains annotations "just work", while other annotations will be more descriptive. @Deprecated
doesn't make that much sense, but will show a warning, while @Experimental
makes sense, but no warning in the IDE. I prefer having IDE warnings.
Deprecated was chosen as it works in all IDEs not just idea. Java itβs self was using it (I believe the latest version does something else now) for its own experimental APIs so it seemed a great fit.
We're taking a lot of the experimental API stuff over to FabLabs. It'll be drafted and worked on there before it's PR'd into Fabric API.
Imo fablabs will be large experimental apis that are applicable to previous versions (generally applicable).
Snapshot-bound smaller essential apis like nether biomes or living entity attributes may go through fabric directly, I'd suggest, due to a high necessity.
I wonder how feasable it would be to add an @Experimental
annotation, should be able to add warnings to that. IDEA does so for Unsafe and similar things.
Well we could obviously add an annotation in 2s. The issue is IDE support for these annotations so the user can see something.
The user visibility imo can be done with an annotation processor that maybe produces a warning if an annotated class/method/field is used in the abstract syntax tree?
I don't think IntelliJ at least shows warnings from the Annotation Processor in the editing view, I know this because I have gotten Mixin warning that wait to show up until compiling, and then only in the build screen.
@sfPlayer1 Now that we are on java 16, a notable new feature is that @Deprecated
now has a forRemoval
boolean field. Should we start using those in fabric api now?
I think so, see https://openjdk.java.net/jeps/277 - "the API is experimental and is subject to incompatible changes"
See #1459 where I add forRemoval
for apis that are definitely getting removed in the future.
Meanwhile, for actual experimental apis, I suggest a new review mechanism:
We do not need as throughout review for new-generation apis. We would instead add them with @ApiStatus.Experimental
and @Deprecated
, and have the review for normalization of new api in another pr (we can object or change an api to be forRemoval=true
there).
Yeah, forRemoval=true
is one of the possible outcomes for an experimental api in a pull request that determines the fate of the exp api; or it may just be nuked in a minecraft update in the worst case.
Imo this two step model would allow us to draft a temporary api with less delay in case there is a minecraft update that break existing apis, such as a biome update; the maintainers can just add an api with no-last-call period or minimal review (or even commited to the api directly), which will be an exp api; the community later can open a pr to remove those temp api or elevate them to be permanent.
The three states:
State | Annotations | Destiny |
---|---|---|
Experimental API | @ApiStatus.Experimental @Deprecated Note: forRemoval is false by default |
to be reviewed in a later pr, may either go mature or go dying, triaged through extensive use over time and the review pr |
Dying API | @Deprecated(forRemoval = true) |
to be removed in a version update, exact schedule to be determined in another issue as we don't have one yet |
Mature API | None | the regular API endpoints that we recommend people to use; may go dying as API evolves |
I'd state false explicitly, this is all about communication, otherwise the above scheme is fine. The "in a version update" would be a bump in the minor version only as per the OP.
The "in a version update" would be a bump in the minor version only as per the OP.
Hmm, removing dying api that grew from mature apis in minor updates would be too breaking imo. So an updated table:
State | Annotations | Destiny |
---|---|---|
Experimental API | @ApiStatus.Experimental @Deprecated(forRemoval = false) |
to be reviewed in a later pr, may either go mature or go dying, triaged through extensive use over time and the review pr |
Dying Experimental API | @ApiStatus.Experimental @Deprecated(forRemoval = true) |
to be removed in a minor version update |
Mature API | None | the regular API endpoints that we recommend people to use; may go dying as API evolves |
Dying Mature API | @Deprecated(forRemoval = true) |
to be removed in a major version update |
That table does not reflect the status quo I think: Dying Mature API should probably be @Deprecated
alone, as we will somewhat try not to remove it.
@liach Ok so Player meant that the table is correct for Dying Mature APIs
, so that would be for an API that we know we will have to remove in a subsequent version. However most deprecated APIs are not dying, so they should be marked as @Deprecated
alone imo.
forRemoval = false
would suggest we will keep it, which is not necessarily the case.
forRemoval = true
means we intend to remove the API, which is not necessarily the case, or at least we will try to postpone it as long as it's reasonable.