CodeTools proposal: apidiff

Proposal

apidiff, a new tool in the OpenJDK CodeTools project.

Summary

A utility to compare two or more versions of an API, using a combination of the information in class files, source files and/or API documentation files (cf. original post).

Rationale

An important task when evolving APIs is to be able to compare different versions of an API, such as before and after a proposed change. However, comparing versions of an API is not an easy task:

  • Comparing just source files is hard because of additional content related to the implementation of the API.

  • Comparing just class files is hard because class files do not include any narrative specification from the documentation comments.

  • Comparing just API documentation files is hard because the underlying model of the API can be difficult to discern, and is subject to the presentation by the javadoc tool. However, this is the form most commonly used by developers wanting to read the specification of an API.

In addition, the Java language is evolving, with new features like records and sealed classes, and it is desirable for comparison tools to be able to handle such features when they show up in an API.

It would also be good to be able to classify changes with respect to whether or not they are compatible changes, and if so, what “kind” of compatible. However, this generally requires detailed and accurate models of the APIs being compared: more so than can reasonably be obtained from API documentation files.

Description

apidiff is a tool that leverages the javac front end and other code in the JDK java.compiler and jdk.compiler modules in order to read source and/or class files, and to find the declarations to be compared. When source files are provided, the tool can also compare the “raw” documentation comments for those declarations, and if the corresponding API documentation is provided, the tool can also extract and compare the parts of the documentation for those declarations. Third-party libraries (java-diff-utils, daisydiff) are used to compare the plain text of documentation comments and the relevant parts of the generated API documentation.

The tool can compare two or three versions of an API. It can compare classes on the class path, or in modules. It can also compare the often-overlooked specifications of the serialized forms of classes. It can compare classes in different versions of JDK, although there are currently limitations if preview features are involved. The tool requires JDK 11 or newer to run: because it uses JDK modules internally, the tool must be run with a version of JDK at least as new as the newest API being compared.

When comparing more than two versions of an API, the “structural” parts of each declaration are compared and reported as a group; the “narrative” parts of the specification of each declaration are compared pair-wise against the latest version.

Internally, the tool comprises a front end, which can set up and access different concurrent instances of the javac front end and which reports differences via an interface to a back end, which can generate an HTML report. An internal component provides the ability to extract the parts of an API documentation file containing the specifications of the declarations in that file, ignoring the “window dressing” of the header, footer, and summary tables; this component can handle the output generated by most recent versions of thejavadoc tool.