autonomousapps / dependency-analysis-gradle-plugin

Gradle plugin for JVM projects written in Java, Kotlin, Groovy, or Scala; and Android projects written in Java or Kotlin. Provides advice for managing dependencies and other applied plugins
Apache License 2.0
1.81k stars 120 forks source link

Dependencies from constants marked as unused when using Eclipse Compiler for Java #735

Open loetifuss opened 2 years ago

loetifuss commented 2 years ago

Plugin version 1.10.0 Gradle version 7.4.2

Describe the bug Plugin reports dependency on project "a" as unused although a String constant from "a" is referenced by project "b". This happens only when using Eclipse Compiler for Java. In our project we need to rely on this compiler type switching to javac is not an option because of tons of legacy code.

Advice for :b Unused dependencies which should be removed: implementation project(':a')

To Reproduce

constants.zip

Steps to reproduce the behavior:

  1. Expand attached example project
  2. run gradlew buildHealth

Expected behavior Plugin should not report any dependencies as unused in this example.

Additional context Project "b" references a constant from project "a" without specifying an import statement since the constant is from the same package. When using Eclipse Compiler for Java (by using "ecj"-plugin in "b/build.gradle") the dependency on "a" is reported as unused. When using "javac" no dependencies are reported. I suspect this is due to the different behaviour of ECJ and javac regarding constant pool. Apart from the constant pool is there any way to detect constants from the same package or fully qualified constants?

loetifuss commented 2 years ago

some more detail on the differences in constant pool between javac and ecj: https://bugs.eclipse.org/bugs/show_bug.cgi?id=549455

autonomousapps commented 2 years ago

Thanks for the report.

autonomousapps commented 2 years ago

@loetifuss the problem is that the code in both of your projects are in the same package. To work around issues with detecting constants when there is no constant pool (see also kotlinc, not just ecj), this plugin does limited source parsing. It specifically looks at import statements and correlates those to constants detected in the bytecode of dependencies (which are always detectable). So the fact that your project :b has no import statements is what is causing the analysis to fail to detect the dependency usage.

It would be possible to lift this limitation with more intensive source parsing, but I have no plans to do that at this time, particularly given that split packages are somewhat uncommon.