Class/Package Filtering

Given Java’s lacking modularity (prior to Java9), authors are often forced to make classes that are essentially an implementation detail of a library public. Such classes are often included in packages like impl or internal to hint at their non-public nature.

While Revapi offers the basic filtering capabilities using the basic filter, it is often simpler to exclude classes or packages using this class / package filters specifically made for this purpose (if for nothing else then for the simpler configuration).

By default, all classes are included. If the include filter is specified, only the classes matching the include filter are included in the API check. The exclude filter can take out classes that would otherwise be included.

It is not possible include class that matches a class exclude filter (i.e. if include and exclude filter match the same class, the class is not included) but it is possible to include an inner classes while its parent class is excluded.

It is not possible include classes in package that matches a package exclude filter (i.e. if include and exclude filter match the same package, the classes are not included).

Sample Configuration

[
  {
    "extension": "revapi.java",
    "configuration": {
      "missing-classes": {
        "behavior": "report",
        "ignoreMissingAnnotations": false
      },
      "reportUsesFor": ["java.missing.newClass", "java.class.nonPublicPartOfAPI"],
      "filter": {
        "classes": {
          "regex": true,
          "include": ["com\\.acme\\.api\\..*"]
          "exclude": ["com\\.acme\\.api\\.WeRegretWePlacedThisInApi"]
        },
        "packages": {
          "regex": true,
          "include": ["com\\.acme\\.api\\..*"]
          "exclude": ["com\\.acme\\.internal"]
        }
      }
    }
  }
]

Properties

missing-classes.behavior

This tells the checker what to do when a class is found in the API that is not found in any of the provided jars. The possible values are: error, ignore or report (the default). If report is chosen then the missing class is reported as a problem with either java.missing.oldClass code or java.missing.newClass depending on whether the class was found missing in the old or new version of the API.

missing-classes.ignoreMissingAnnotations

If true (the default is false) the usage chain of annotation classes will not be tracked. The end result of this is that annotation classes will not be considered part of the API and thus missing annotation classes will not be reported.

reportUsesFor

Revapi is able to track usage chains of the classes it finds in the API. For some (or all) problems you may want to know how and where a certain class is used to be able to determine if that’s something wrong or not. This configuration property can either be a string all-differences, signifying that an example use chain will be reported for every found difference or a list of difference codes for which the example use chain should be produced. By default the usage chains are reported for the following problem codes: java.missing.newClass, java.missing.oldClass, java.class.nonPublicPartOfAPI, java.class.externalClassNoLongerExposedInAPI, java.class.externalClassExposedInAPI.

filter.classes.regex

Specifies whether to consider the strings in exclude and include lists as regular expressions or not. The default value is false, meaning the strings are not considered as regular expressions.

filter.classes.exclude

List of strings representing FQCNs or regular expressions matching FQCNs. Classes with the matching fully qualified names (and the members of those classes) will be excluded from the API check.

filter.classes.include

List of strings representing FQCNs or regular expressions matching FQCNs. Only classes with the matching fully qualified names (and their members) will be included in the API check.

filter.packages.regex

Specifies whether to consider the strings in exclude and include lists as regular expressions or not. The default value is false, meaning the strings are not considered as regular expressions.

filter.packages.exclude

List of strings representing full package names or regular expressions matching them. Classes with the matching package names (and the members of those classes) will be excluded from the API check.

filter.packages.include

List of strings representing full package names or regular expressions matching them. Classes with the matching package names (and the members of those classes) will be included in the API check.

Notes

Contrary to intuition, java packages are not hierarchical, even though they have hierarchical names. In Java parlance, package com.acme.foo is a sub-package of com.acme but that does not mean that it’s enclosing element is com.acme. No, each package is a top level element that does not have any parent elements and which only contains classes, not other packages.

Therefore if you want to exclude a package and all its sub-packages, you need to use a regular expression "com\\.acme(\\..+)?" which will match the com.acme package and any of its sub-packages.