Coder Social home page Coder Social logo

apiguardian's People

Contributors

apiguardian avatar hendrikebbers avatar kriegfrj avatar marcono1234 avatar marcphilipp avatar sbrannen avatar sormuras avatar timvdlippe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apiguardian's Issues

Allow @API to be declared at the package level

I am reviewing mockito/mockito#2047 atm, which adds apiguardian statements to various Mockito internal classes that are used by the mockito-junit-jupiter extension. This approach is quite ad-hoc, as we would have to add the annotation when we start using it. An alternative approach would be to add the annotation to every single class we have in org.mockito.internal, but that seems to be quite invasive as well.

Would it be possible to allow the annotation to be added on package statements (e.g. in a package-info.java) for org.mockito.internal? That would then indicate that all classes in its (sub-)packages are marked internal.

I am not sure if OSGi tooling would need to be updated to support the new location, but at least it would allow us to more nicely integrate apiguardian into Mockito.

CC @rotty3000

Javadoc 1.8 cannot link to the published 1.1.0 API documentation

Javadoc 1.8 cannot link to the documentation published at https://apiguardian-team.github.io/apiguardian/docs/1.1.0/api/.

build.gradle

plugins {
  id 'java-library'
}

sourceCompatibility = JavaVersion.VERSION_1_8

repositories.mavenCentral()

ext.apiGuardianVersion = '1.1.0'

dependencies {
  api "org.apiguardian:apiguardian-api:${apiGuardianVersion}"
}

tasks.named('javadoc').configure {
  options.links = [
      'https://docs.oracle.com/javase/8/docs/api/',
      "https://apiguardian-team.github.io/apiguardian/docs/${apiGuardianVersion}/api/"
  ] as String[]
}

src/main/java/Test.java

import org.apiguardian.api.API;

@API(status = API.Status.EXPERIMENTAL)
public class Test {}
$ ./gradlew javadoc

> Task :javadoc
javadoc: warning - Error fetching URL: https://apiguardian-team.github.io/apiguardian/docs/1.1.0/api/
1 warning

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

$ ./gradlew --version

------------------------------------------------------------
Gradle 5.2.1
------------------------------------------------------------

Build time:   2019-02-08 19:00:10 UTC
Revision:     f02764e074c32ee8851a4e1877dd1fea8ffb7183

Kotlin DSL:   1.1.3
Kotlin:       1.3.20
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM:          1.8.0_242 (AdoptOpenJDK 25.242-b08)
OS:           Mac OS X 10.15.3 x86_64

Whereas

  • https://apiguardian-team.github.io/apiguardian/docs/current/api/
  • https://apiguardian-team.github.io/apiguardian/docs/1.0.0/api/

work.

Using Gradle 6.2.1 produces the same warning message.

Clarify wildcard usage for API.consumers

API.consumers allows according to the documentation the usage of wildcards:

The supplied packages can be fully qualified package names or patterns containing asterisks that will be used as wildcards.

However, it is not very specific regarding the following:

  1. What is a wildcard? Only *?
  2. Do wildcards apply only to one package nesting depth or to this depth and all "sub packages". E.g. does a.* match a.b and a.b.c?
    Note that Java does not have a concept of "sub packages" so for example a package-private type in a cannot be seen by a type in a.b.
  3. Do wildcards match if that nesting depth is not present (related to point 1 above)? E.g. a.b.* matching a.b
  4. Can wildcards only appear at the end, or may they also appear in the middle or the front of the package name (if so how does points 2 and 3 above apply)? E.g. *.a.*.b
  5. May wildcards only appear as replacement for a complete "sub package name" or may they also be used within "sub package" names (and if so, how would they match)? E.g. a.tes* matching a.test and a.testing

Note that I do not suggest that the behavior described above is the desired one, it only lists what one might expect from wildcards.

Could you please clarify this in the documentation and possibly include some examples?

Introduce SPI status to indicate the extension points

The current set of Status values looks consistent for most of projects. However, in a framework or library — which are intended to be used as building blocks — there is also often an additional need to indicate the designed extension points.

SPI status solves such a task by taking "it is safe to use" semantic (i.e. STABLE) and appending it with "you are welcome to extend this element" — as per SPI definition.

Some libraries dedicate a package to this purpose. However, package-based approach isn't always possible and it's way less convenient for tasks such as code inspection/post-processing.

In a way, this issue is similar to #9, but instead of restricting the API extension, I'd propose to mark the elements that are designed for it.

Introduce tools for @API annotation processing

Ideas

  • Extract all public APIs and generate a report
  • Compare two versions of an artifact for release notes
  • Check correct usage of APIs (internally and externally)
    • The tool should check that @API is only declared on public types/methods.
  • Implement a reporting tool that warns about usage of experimental and deprecated APIs.

Related Issues

Deliverables

  • ?

Introduce annotations to further restrict API usage

Overview

For Frameworks and libraries it is quite common to provide interfaces and classes. But not all interfaces are intended to be implemented by clients, or classes may not be intended to be instantiated. If you write plugins for Eclipse you can use the Eclipse API Annotations to express such restrictions (and the IDE supports them by generating violation errors).

It would be nice to have a common-lib/apiguardian that provides these so they may become standard.

Example

Copied directly from Eclipse API Annotations:

Annotation Type Description
NoExtend Classes and interfaces tagged with this annotation are declaring they are not to be extended by clients.
NoImplement Interfaces tagged with this annotation are declaring they are not to be implemented by clients.
NoInstantiate Classes tagged with this annotation are declaring they are not to be instantiated by clients.
NoOverride Methods tagged with this annotation are declaring they are not to be overridden by clients.
NoReference Classes, interfaces, annotations, enums, methods and fields tagged with this annotation are declaring they are not to be referenced at all by clients.

Well defined API status graph

Status quo is that the statuses (huh, accidental wordplay, nice) are only described with javadocs. Missing part is some formal definition of state graph.

This API is only documentational unless there will be some tools provided that would check whether annotated elements behave as expected between versions. It can be quite easy to misinterpret the javadoc in some minor detail and that would result with different tools behaving differently (one could consider some API change as valid, another one could raise a warning in the same case). There should be strict definiton of rules that would be later shared by these tools.

The graph

See the picture for proposed graph, suited for 1.0.0 of apiguardian API.

An issue to be discussed: can STABLE go to MAINTAINED?

I'd say that it shouldn't. IMO STABLE should mean that API element in that state will stay for the end of major version lifecycle.

Another one: are there any restrictions on what happens when major version changes?

Again, I'd say that there shouldn't be. Change of major version defines basically a new API that may or may not look similiar to the previous one.

The module

There is a pull request #3 that splits the repo to several modules. I would propose adding yet another module apiguardian-contract that would contain some simple graph model (that would have domain names, so e.g. ApiElementState instead of Node and StateTransitionRule instead of Edge) and an utility class with static content that would provide set of rules describing the graph that was agreed upon and some ways to inspect it (methods like isValidStateChange(...) and validStatesFrom(...)).

There is WIP pull request #8 for my implementation draft.

Providing such module would make it easier for creators of tools to keep their behaviour consistent with different tools.

Copyright

Please clearly indicate the names of the authors and the copyright date.

One of the nice things about Maven's pom.xml file is that it defines a machine-readable format for listing the project title (name), license, main authors, contributors, inception year, project homepage, and other useful metadata. Such data can be fed into ORT, which helps to automatically generate a software bill of materials. IMO, it was a bit of an oversight by the Gradle team to not require such items as part of the build scripts (e.g., as standard property file entries).

Add OSGi metadata

From discussion in junit-team/junit5#2547, it was noted that the @API annotation of API guardian has RUNTIME retention policy - which means that some code might reasonably expect it to be available at runtime. (This is in contrast to a comment made earlier here stating that it was a compile-only dependency.)

Given that runtime retention implies that runtime usage is anticipated, API Guardian should probably at some stage get its own OSGi metadata to make it available at runtime in an OSGi context.

Class/method stability for fluent APIs

Some fluent APIs use multiple intermediate types to restrict the available methods depending on what methods were called earlier in the call chain.

As an illustration, imagine a fictitious library that models SQL as Java method call chains:

// Compiles fine
Result result = db.select().from(table).where(criterion1).and(criterion2).execute();

// COMPILER ERROR: cannot find symbol and() on type Select1
Result result = db.select().from(table).and(criterion2).execute();

Adding new features to such APIs often causes changes in the state machine and thus re-numbering of intermediate types. Therefore, the library explicitly discourages users from defining variables such as Select2 select = db.select().from(table).where(criterion1);.

Consequently, in its SemVer documentation the library excludes the names of these intermediate types from the public API. However, it promises that any method chain that worked in one release will still work in a subsequent minor release (albeit with possibly different intermediate type names).

Could such a library use API Guardian? If so, how? To me, the closest match would be documenting the entry point (the one with select() with STABLE and the intermediate types (Select0, Select1 etc) with INTERNAL - but the methods on those intermediate types would be STABLE. I interpret this to mean "don't rely on this type name, but rest assured the method will stay available".

With this interpretation, I could (and intent to) use API Guardian for fluent APIs in puretemplate. However, that usage may be counterintuitive to users and even frowned upon by the API Guardian team because the Javadocs for @API say the following (emphasis mine):

If @API is present on a type, it is considered to hold for all public members of the type as well. However, a member of such an annotated type is allowed to declare a API.Status of lower stability.

My "INTERNAL class with STABLE methods" trick is the exact reverse of this.

So, what do you think of this? Please note that I'm fine with any answer; I just wanted to bring this to your attention.

Here are some alternatives I can imagine:

  1. We have no idea what you're talking about.
  2. We get it, but can't endorse this weird stuff.
  3. We will mention "INTERNAL class with STABLE methods" as an exception to the rule.
  4. We will change the "declare a API.Status of lower stability" wording to "declare a different API.Status", followed by two examples: one is the "with lower stability" case, the other is "INTERNAL class with STABLE methods, e.g. for fluent APIs".
  5. This is important, but INTERNAL on the class is wrong. We will introduce a special status called ANONYMOUS for this. (No, I'm not seriously suggesting that.)

When to use API.Status.DEPRECATED?

When should API.Status.DEPRECATED be used? Normally you would use @java.lang.Deprecated which has since Java 9 the elements since and forRemoval and is likely supported by every IDE.

So what are cases where one would (only) use API.Status.DEPRECATED? Is it intended for situations where the public API will be removed, but the annotated element will still be available internally afterwards (though wouldn't @Deprecated then be better as well)?

Introduce INCUBATING status

I'm missing API status that would mean "this is completely new feature and it will almost definitely change - expect SOME solution to problem solved by this, but don't get too attached to current form".

That way EXPERIMENTAL would mean something like "this API may morph, but gradually", while INCUBATING would mean "we have no clue how to describe this domain/context, but here's an approach".

I wouldn't provide any contract on what happens to such features in future versions, but I'd say that INCUBATING features shouldn't be promoted directly to MAINTAINED or STABLE and should go through EXPERIMENTAL stage first.

In the end, EXPERIMENTAL would mean "we're polishing this", while INCUBATING would mean "we're coming up with this".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.