Skip to content

Unused Dependency Rule

Jon Schneider edited this page Sep 21, 2016 · 4 revisions

The unused dependency rule is an example of a complex dependency hygiene rule.

To apply the rule, add:

gradleLint.rules += 'unused-dependency'

The rule inspects compiled binaries emanating from your project's source sets looking for class references, and matches those references to the dependencies that you have declared in your dependencies block.

Specifically, the rule makes the following adjustments to dependencies:

  1. Removes unused dependencies
  • Family-style jars like com.amazonaws:aws-java-sdk are removed, as they contain no code
  1. Promotes transitive dependencies that are used directly by your code to explicit first order dependencies
  • This has the side effect of breaking up family style jars like com.amazonaws:aws-java-sdk into the parts that you are actually using, and adding those as first order dependencies
  1. Relocates dependencies to the 'correct' configuration
  • Webjars are moved to the runtime configuration
  • Jars that contain no classes AND content outside of META-INF are moved to runtime
  • 'xerces', 'xercesImpl', 'xml-apis' should always be runtime scoped
  • Service providers (jars containing META-INF/services) like mysql-connector-java are moved to runtime if there is no provable compile-time reference
  • Dependencies are moved to the highest source set configuration possible. For example, 'junit' is relocated to testCompile unless there is an explicit dependency on it in the main source set (rare).

The rule uses a combination of ASM (to look for direct references) and reflection (to look for indirect type hierarchy references) to assess what is in use.

What about reflection?

If your code refers to a dependency only via reflection, the dependency is best placed in the runtime configuration, but the unused dependency rule will not see the reference.

Convenience when dealing with empty family jars

Occasionally, you may find dependencies like com.amazonaws:aws-java-sdk in third party or internal binary repositories that contain a dependency descriptor (POM or Ivy file) that lists a set of dependencies paired with a JAR that is virtually empty (no classes at a minimum). This is a simple technique to allow developers to pick up several libraries at once and provide a weak contract around version alignment for these libraries.

Generally, applications only use a subset of the libraries included in such families. The unnecessary dependencies included with the family both increase the footprint of the application itself. If the 'application' is actually itself a library, these unnecessary dependencies leak downstream to its users, increasing their footprint and potentially introducing breaking version conflict resolution problems.

Using the unused dependency rule, you can get coding quickly by including the family and later run the rule to strike all but the components you actually use (without having to know what each of these components' coordinates are).