Giter Club home page Giter Club logo

dependency-analysis-gradle-plugin's People

Contributors

3flex avatar andrzejressel avatar autonomousapps avatar braisgabin avatar cobexer avatar daanschipper avatar gabrielittner avatar ivanalvarado avatar jacksonbailey avatar jjohannes avatar joshfriend avatar js92 avatar martinbonnin avatar mmollaverdi avatar mvegter avatar nsk-mironov avatar pavlospt avatar pforhan avatar sboishtyan avatar seregamorph avatar simonmarquis avatar staktrace avatar stephanenicolas avatar subhrajyotisen avatar tcrawford-figure avatar twisterrob avatar vampire avatar vichy97 avatar vlsi avatar zacsweers 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  avatar  avatar  avatar  avatar

dependency-analysis-gradle-plugin's Issues

False report about unused navigation UI library

Gradle version
6.0.1

Android Gradle Plugin (AGP) version
3.5.3

Describe the bug
Some of our modules are using the navigation component library. It generates code from xml that describes navigation logic.

To Reproduce
Steps to reproduce the behavior:

  1. Add androidx.navigation:navigation-ui-ktx:<latest version>
  2. Create some navigation xml
  3. Run the advice for the project

Expected behavior
Do not report false positive.

Additional context
Add any other context about the problem here.

Detect when databinding or viewbinding are enabled but don't need to be

A user has reported that the dependency androidx.databinding:databinding-common is reported as unused. This dependency is automatically added (I assume) when dataBinding.isEnabled = true is set. I need to learn which dependencies are added, and if it's possible to determine databinding isn't being used, and so therefore we can accurately recommend it be disabled.

Functional tests: stop asserting against output and only look at file output

This would allow us to drop the --rerun-tasks flag from the build invocation, which should make the functional tests much faster.

There may still be some cases where it makes sense to verify console output. For example, the buildHealth task itself is just a default task that always prints to stdout, after executing its dependencies.

Consider using task.withType<...>() and task.register<...>(...)

tasks.withType<PluginUnderTestMetadata>().configureEach {
    pluginClasspath.from(configurations.compileOnly)
}

// and 

tasks.register<DependencyMisuseAggregateReportTask>("misusedDependenciesReport") {
...

seem to be easier to follow than DependencyMisuseAggregateReportTask::class.java

Reported unused module but super class is needed

Gradle version
6.0.1
Android Gradle Plugin (AGP) version
3.5.3

Describe the bug
I have module A class AA extends module B class BB. And module B class BB extends module C class CC. The module C is reported as non-used in module A but compilation fails:

e: Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class BB, unresolved supertypes: CC

Expected behavior
Module C should not be reported as non-used in module A.

Add a single dependencyHealth task

I'm not sure if dependencies must be analyzed for each "source set", however, I would suggest to have an umbrella task always.
Then people would not have to remember what to execute.

For instance:

$ ./gradlew dependencyHeath

...

Declared as `api`, but could be `implementation` or `runtimeOnly`
-------------------------------

commons-io:commons-io is declared as api, but it is not used in public APIs, so it should be declared as implementaion
...


Declared as `implementation`, but could be `runtimeOnly`
--------------------

commons-codec:commons-codec is declared as implementation, but it is not really used for compilation. Should it be runtimeOnly?
...

Unused dependencies
----------------
com.fasterxml.jackson.core:jackson-databind is declared as implementation, but it is unused.


Used, but undeclared
--------------
org.apache.commons:commons-lang3 is declared in 
"DEF is not explicitly declared in dependencies, but its clases are used. Consider declaring the dependency explicitly as implementation(...)"
"G is declared as api, and it is not used"
...

and so on.

Provide a way to override API status

There might be valid reasons to use implementation (rather than api) even in case a class is present in a signature of a public method.

The method could be visible-for-test only or internal or something like that.

Is it the plugin Android-only?

I tried adding the plugin to https://github.com/apache/calcite, and it does not seem to work very well.

Do you think the plugin could be used for Java (Kotlin) based libraries?

> Configure project :
Building Apache Calcite 1.22.0-SNAPSHOT
Adding JVM tasks to :babel
Adding JVM tasks to :cassandra
Adding JVM tasks to :core
Adding JVM tasks to :druid
Adding JVM tasks to :elasticsearch
Adding JVM tasks to :file
Adding JVM tasks to :geode
Adding JVM tasks to :kafka
Adding JVM tasks to :linq4j
Adding JVM tasks to :mongodb
Adding JVM tasks to :pig
Adding JVM tasks to :piglet
Adding JVM tasks to :plus
Adding JVM tasks to :server
Adding JVM tasks to :spark
Adding JVM tasks to :splunk
Adding JVM tasks to :example:csv
Adding JVM tasks to :example:function

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':core'.
> Could not create task ':core:misusedDependenciesMain'.
   > com/android/build/gradle/internal/publishing/AndroidArtifacts

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 27s
MacBook-Pro-Vladimir-3:calcite vladimirsitnikov$ gw :core:misusedDependenciesMain --stacktrace
Using gradle at '/Users/vladimirsitnikov/Documents/code/calcite/gradlew' to run buildfile '/Users/vladimirsitnikov/Documents/code/calcite/build.gradle.kts':

Starting a Gradle Daemon, 1 incompatible and 3 stopped Daemons could not be reused, use --status for details

> Configure project :
Building Apache Calcite 1.22.0-SNAPSHOT
Adding JVM tasks to :babel
Adding JVM tasks to :cassandra
Adding JVM tasks to :core
Adding JVM tasks to :druid
Adding JVM tasks to :elasticsearch
Adding JVM tasks to :file
Adding JVM tasks to :geode
Adding JVM tasks to :kafka
Adding JVM tasks to :linq4j
Adding JVM tasks to :mongodb
Adding JVM tasks to :pig
Adding JVM tasks to :piglet
Adding JVM tasks to :plus
Adding JVM tasks to :server
Adding JVM tasks to :spark
Adding JVM tasks to :splunk
Adding JVM tasks to :example:csv
Adding JVM tasks to :example:function

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':core'.
> Could not create task ':core:misusedDependenciesMain'.
   > com/android/build/gradle/internal/publishing/AndroidArtifacts

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':core'.
        at org.gradle.execution.TaskNameResolver.getExistingTask(TaskNameResolver.java:116)
        at org.gradle.execution.TaskNameResolver.access$000(TaskNameResolver.java:32)
        at org.gradle.execution.TaskNameResolver$1.collectTasks(TaskNameResolver.java:65)
        at org.gradle.execution.TaskSelector$TaskSelection.getTasks(TaskSelector.java:141)
        at org.gradle.execution.commandline.CommandLineTaskParser.parseTasks(CommandLineTaskParser.java:43)
        at org.gradle.execution.TaskNameResolvingBuildConfigurationAction.configure(TaskNameResolvingBuildConfigurationAction.java:46)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.configure(DefaultBuildConfigurationActionExecuter.java:58)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.access$200(DefaultBuildConfigurationActionExecuter.java:26)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter$2.proceed(DefaultBuildConfigurationActionExecuter.java:66)
        at org.gradle.execution.DefaultTasksBuildExecutionAction.configure(DefaultTasksBuildExecutionAction.java:45)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.configure(DefaultBuildConfigurationActionExecuter.java:58)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.access$200(DefaultBuildConfigurationActionExecuter.java:26)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter$2.proceed(DefaultBuildConfigurationActionExecuter.java:66)
        at org.gradle.execution.ExcludedTaskFilteringBuildConfigurationAction.configure(ExcludedTaskFilteringBuildConfigurationAction.java:48)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.configure(DefaultBuildConfigurationActionExecuter.java:58)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.access$200(DefaultBuildConfigurationActionExecuter.java:26)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter$1.run(DefaultBuildConfigurationActionExecuter.java:44)
        at org.gradle.internal.Factories$1.create(Factories.java:26)
        at org.gradle.api.internal.project.DefaultProjectStateRegistry.withLenientState(DefaultProjectStateRegistry.java:134)
        at org.gradle.api.internal.project.DefaultProjectStateRegistry.withLenientState(DefaultProjectStateRegistry.java:126)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.select(DefaultBuildConfigurationActionExecuter.java:40)
        at org.gradle.initialization.DefaultTaskExecutionPreparer.prepareForTaskExecution(DefaultTaskExecutionPreparer.java:38)
        at org.gradle.initialization.BuildOperatingFiringTaskExecutionPreparer$CalculateTaskGraph.populateTaskGraph(BuildOperatingFiringTaskExecutionPreparer.java:82)
        at org.gradle.initialization.BuildOperatingFiringTaskExecutionPreparer$CalculateTaskGraph.run(BuildOperatingFiringTaskExecutionPreparer.java:57)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.initialization.BuildOperatingFiringTaskExecutionPreparer.prepareForTaskExecution(BuildOperatingFiringTaskExecutionPreparer.java:45)
        at org.gradle.initialization.DefaultGradleLauncher.prepareTaskExecution(DefaultGradleLauncher.java:211)
        at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:146)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:130)
        at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:110)
        at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:60)
        at org.gradle.internal.invocation.GradleBuildController$1.execute(GradleBuildController.java:57)
        at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:85)
        at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:78)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
        at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
        at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:78)
        at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:57)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:63)
        at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
        at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:51)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:45)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
        at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:78)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
        at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:59)
        at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:36)
        at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
        at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:68)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:27)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreationException: Could not create task ':core:misusedDependenciesMain'.
        at org.gradle.api.internal.tasks.DefaultTaskContainer.taskCreationException(DefaultTaskContainer.java:720)
        at org.gradle.api.internal.tasks.DefaultTaskContainer.access$600(DefaultTaskContainer.java:77)
        at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider.domainObjectCreationException(DefaultTaskContainer.java:712)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection$AbstractDomainObjectCreatingProvider.tryCreate(DefaultNamedDomainObjectCollection.java:946)
        at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider.access$1401(DefaultTaskContainer.java:658)
        at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider$1.run(DefaultTaskContainer.java:685)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.DefaultTaskContainer$TaskCreatingProvider.tryCreate(DefaultTaskContainer.java:681)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection$AbstractDomainObjectCreatingProvider.getOrNull(DefaultNamedDomainObjectCollection.java:927)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection.findByName(DefaultNamedDomainObjectCollection.java:294)
        at org.gradle.api.internal.tasks.DefaultTaskContainer.findByName(DefaultTaskContainer.java:562)
        at org.gradle.api.internal.tasks.DefaultTaskContainer.findByName(DefaultTaskContainer.java:76)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection.getByName(DefaultNamedDomainObjectCollection.java:330)
        at org.gradle.api.internal.tasks.DefaultTaskCollection.getByName(DefaultTaskCollection.java:46)
        at org.gradle.execution.TaskNameResolver.getExistingTask(TaskNameResolver.java:114)
        ... 108 more
Caused by: java.lang.NoClassDefFoundError: com/android/build/gradle/internal/publishing/AndroidArtifacts
        at com.autonomousapps.DependencyAnalysisPlugin$analyzeAndroidDependencies$1$1.execute(DependencyAnalysisPlugin.kt:115)
        at com.autonomousapps.DependencyAnalysisPlugin$analyzeAndroidDependencies$1$1.execute(DependencyAnalysisPlugin.kt:27)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationResolvableDependencies.artifactView(DefaultConfiguration.java:1502)
        at com.autonomousapps.DependencyAnalysisPlugin$analyzeAndroidDependencies$1.execute(DependencyAnalysisPlugin.kt:114)
        at com.autonomousapps.DependencyAnalysisPlugin$analyzeAndroidDependencies$1.execute(DependencyAnalysisPlugin.kt:27)
        at org.gradle.api.internal.DefaultMutationGuard$2.execute(DefaultMutationGuard.java:42)
        at org.gradle.api.internal.DefaultMutationGuard$2.execute(DefaultMutationGuard.java:42)
        at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction$1$1.run(DefaultCollectionCallbackActionDecorator.java:100)
        at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.reapply(DefaultUserCodeApplicationContext.java:60)
        at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction$1.run(DefaultCollectionCallbackActionDecorator.java:97)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.api.internal.DefaultCollectionCallbackActionDecorator$BuildOperationEmittingAction.execute(DefaultCollectionCallbackActionDecorator.java:94)
        at org.gradle.internal.ImmutableActionSet$SetWithManyActions.execute(ImmutableActionSet.java:329)
        at org.gradle.api.internal.DefaultDomainObjectCollection.doAdd(DefaultDomainObjectCollection.java:264)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection.doAdd(DefaultNamedDomainObjectCollection.java:112)
        at org.gradle.api.internal.DefaultDomainObjectCollection.add(DefaultDomainObjectCollection.java:258)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection$AbstractDomainObjectCreatingProvider.tryCreate(DefaultNamedDomainObjectCollection.java:942)
        ... 125 more
Caused by: java.lang.ClassNotFoundException: com.android.build.gradle.internal.publishing.AndroidArtifacts
        ... 147 more

Don't suggest changing viewbinding dependencies

When viewbinding is enabled, AGP adds a number of dependencies to the project, and this is entirely outside of the user's control. This plugin should not suggest removing or changing these libraries.

AGP 3.6.1

Viewbinding disabled

With AGP 3.6.1 and viewbinding not enabled, a build scan for ./gradlew app:assembleDebug shows the following debugCompileClasspath:

  • androidx.activity:activity:{strictly 1.0.0}
  • androidx.annotation:annotation:{strictly 1.1.0}
  • androidx.appcompat:appcompat:1.1.0
  • androidx.appcompat:appcompat:{strictly 1.1.0}
  • androidx.appcompat:appcompat-resources:{strictly 1.1.0}
  • androidx.arch.core:core-common:{strictly 2.1.0}
  • androidx.arch.core:core-runtime:{strictly 2.0.0}
  • androidx.collection:collection:{strictly 1.1.0}
  • androidx.constraintlayout:constraintlayout:1.1.3
  • androidx.constraintlayout:constraintlayout:{strictly 1.1.3}
  • androidx.constraintlayout:constraintlayout-solver:{strictly 1.1.3}
  • androidx.core:core:{strictly 1.1.0}
  • androidx.cursoradapter:cursoradapter:{strictly 1.0.0}
  • androidx.customview:customview:{strictly 1.0.0}
  • androidx.drawerlayout:drawerlayout:{strictly 1.0.0}
  • androidx.fragment:fragment:{strictly 1.1.0}
  • androidx.interpolator:interpolator:{strictly 1.0.0}
  • androidx.lifecycle:lifecycle-common:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-livedata:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-livedata-core:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-runtime:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-viewmodel:{strictly 2.1.0}
  • androidx.loader:loader:{strictly 1.0.0}
  • androidx.savedstate:savedstate:{strictly 1.0.0}
  • androidx.vectordrawable:vectordrawable:{strictly 1.1.0}
  • androidx.vectordrawable:vectordrawable-animated:{strictly 1.1.0}
  • androidx.versionedparcelable:versionedparcelable:{strictly 1.1.0}
  • androidx.viewpager:viewpager:{strictly 1.0.0}

and the following debugRuntimeClasspath:

  • androidx.appcompat:appcompat:1.1.0
  • androidx.constraintlayout:constraintlayout:1.1.3

debugAnnotationProcessorClasspath:
empty

Viewbinding enabled

build scan
debugCompileClasspath:

  • androidx.activity:activity:{strictly 1.0.0}
  • androidx.annotation:annotation:{strictly 1.1.0}
  • androidx.appcompat:appcompat:1.1.0
  • androidx.appcompat:appcompat:{strictly 1.1.0}
  • androidx.appcompat:appcompat-resources:{strictly 1.1.0}
  • androidx.arch.core:core-common:{strictly 2.1.0}
  • androidx.arch.core:core-runtime:{strictly 2.0.0}
  • androidx.collection:collection:{strictly 1.1.0}
  • androidx.constraintlayout:constraintlayout:1.1.3
  • androidx.constraintlayout:constraintlayout:{strictly 1.1.3}
  • androidx.constraintlayout:constraintlayout-solver:{strictly 1.1.3}
  • androidx.core:core:{strictly 1.1.0}
  • androidx.cursoradapter:cursoradapter:{strictly 1.0.0}
  • androidx.customview:customview:{strictly 1.0.0}
  • androidx.databinding:viewbinding:3.6.1
  • androidx.databinding:viewbinding:{strictly 3.6.1}
  • androidx.drawerlayout:drawerlayout:{strictly 1.0.0}
  • androidx.fragment:fragment:{strictly 1.1.0}
  • androidx.interpolator:interpolator:{strictly 1.0.0}
  • androidx.lifecycle:lifecycle-common:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-livedata:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-livedata-core:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-runtime:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-viewmodel:{strictly 2.1.0}
  • androidx.loader:loader:{strictly 1.0.0}
  • androidx.savedstate:savedstate:{strictly 1.0.0}
  • androidx.vectordrawable:vectordrawable:{strictly 1.1.0}
  • androidx.vectordrawable:vectordrawable-animated:{strictly 1.1.0}
  • androidx.versionedparcelable:versionedparcelable:{strictly 1.1.0}
  • androidx.viewpager:viewpager:{strictly 1.0.0}

debugRuntimeClasspath:

  • androidx.appcompat:appcompat:1.1.0
  • androidx.constraintlayout:constraintlayout:1.1.3
  • androidx.databinding:viewbinding:3.6.1

debugAnnotationProcessorClasspath:
empty

So, viewbinding adds the following

debugCompileClasspath:

  • androidx.databinding:viewbinding:3.6.1
  • androidx.databinding:viewbinding:{strictly 3.6.1}

debugRuntimeClasspath:

  • androidx.databinding:viewbinding:3.6.1

debugAnnotationProcessorClasspath:
empty

Report when a dependency isn't required by prod code, but rather test code

The possibility for doing this has opened up with the new variants work currently in PR at #177.

Some notes about some test-related tasks:
Android libraries and apps use these two tasks:

  • compileDebugUnitTestKotlin of type org.jetbrains.kotlin.gradle.tasks.KotlinCompile
  • compileDebugUnitTestJavaWithJavac of type org.gradle.api.tasks.compile.JavaCompile

Java and Kotlin libraries use these two tasks:

  • compileTestKotlin of type org.jetbrains.kotlin.gradle.tasks.KotlinCompile
  • compileTestJava of type org.gradle.api.tasks.compile.JavaCompile

Yay, looks like there are only two types, albeit four separate names.

Add configurable failure states

I'm imagining the following configurable failure states right now:

  1. Any unused declared components
  2. Any used transitive components
  3. Any components on the wrong configuration (api vs implementation)
  4. Used external resources
    ...others?

The first three will be based on the output from the Advice report, while the fourth will come from the android-res analysis task.

In addition, it must be possible for users to tell the plugin, at a fine-grain, which dependencies to ignore when looking at failure states, possibly even on a per-failure-state basis.

java.lang.NoSuchMethodError: com.squareup.moshi.Moshi.adapter

Plugin version: 0.25.0 and 0.24.0

Gradle version: 6.2.2

Android Gradle Plugin (AGP) version : 3.6.1

Describe the bug
app:adviceDebug task fails with the following exception

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:artifactsReportDebug'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:205)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:203)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:184)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: java.lang.NoSuchMethodError: com.squareup.moshi.Moshi.adapter(Ljava/lang/reflect/Type;Ljava/util/Set;Ljava/lang/String;)Lcom/squareup/moshi/JsonAdapter;
        at com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory.create(KotlinJsonAdapter.kt:241)
        at com.squareup.moshi.Moshi.adapter(Moshi.java:100)
        at com.squareup.moshi.StandardJsonAdapters$ObjectJsonAdapter.toJson(StandardJsonAdapters.java:285)
        at com.squareup.moshi.JsonAdapter$2.toJson(JsonAdapter.java:135)
        at com.squareup.moshi.CollectionJsonAdapter.toJson(CollectionJsonAdapter.java:85)
        at com.squareup.moshi.CollectionJsonAdapter$2.toJson(CollectionJsonAdapter.java:53)
        at com.squareup.moshi.JsonAdapter$2.toJson(JsonAdapter.java:135)
        at com.squareup.moshi.JsonAdapter.toJson(JsonAdapter.java:46)
        at com.squareup.moshi.JsonAdapter.toJson(JsonAdapter.java:52)
        at com.autonomousapps.tasks.ArtifactsAnalysisTask.action(ArtifactsAnalysisTask.kt:96)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:49)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:42)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:727)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:694)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.run(ExecuteActionsTaskExecuter.java:568)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:553)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:536)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:109)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:276)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:265)
        at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:67)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:36)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
        at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
        at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:153)
        at org.gradle.internal.execution.steps.CacheStep.executeAndStoreInCache(CacheStep.java:129)
        at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache$2(CacheStep.java:107)
        at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache$3(CacheStep.java:107)
        at org.gradle.internal.Try$Success.map(Try.java:162)
        at org.gradle.internal.execution.steps.CacheStep.executeWithCache(CacheStep.java:76)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:66)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:41)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53)
        at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39)
        at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40)
        at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:192)
        ... 30 more

Expected behavior
task should finish and produce the report

private_to_this not considered in ABI analysis

Plugin version
0.26.1

Gradle version
6.3

Android Gradle Plugin (AGP) version
Irrelevant

Describe the bug
Kotlin visibility has a notion of "private to this", which is present in metadata. I don't think this is currently accounted for.

To Reproduce
Steps to reproduce the behavior:

private class Foo

class Bar {
  private val foo = Foo()
}

Expected behavior
A clear and concise description of what you expected to happen.

Additional context
Add any other context about the problem here.

Example of reading the flag from metadata: https://github.com/square/kotlinpoet/blob/master/kotlinpoet-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/Flags.kt#L46

Cannot apply along with org.gradle.java-gradle-plugin

Gradle version
6.1.1

Describe the bug
If you apply both this plugin and org.gradle.java-gradle-plugin, the following error occurs if you run gradle:

An exception occurred applying plugin request [id: 'org.gradle.java-gradle-plugin']
> Failed to apply plugin [class 'org.gradle.api.plugins.JavaLibraryPlugin']
   > Cannot add a configuration with name 'dependencyReport' as a configuration with that name already exists.

FR - add version in transitive dependencies

Right now transitive dependencies don't include versions, which potentially prevents pulling them up into the consuming app

{
  "identifier": ":jobqueue",
  "usedTransitiveDependencies": [
    "com.birbit:android-priority-jobqueue",
    "org.jetbrains:annotations",
    "androidx.core:core",
    "androidx.annotation:annotation",
    "androidx.lifecycle:lifecycle-common",
    "androidx.arch.core:core-common",
    "androidx.collection:collection",
    "androidx.loader:loader",
    "androidx.viewpager:viewpager",
    "androidx.coordinatorlayout:coordinatorlayout",
    "androidx.interpolator:interpolator",
    "androidx.swiperefreshlayout:swiperefreshlayout",
    "androidx.fragment:fragment"
  ]
}

Don't suggest changing databinding dependencies

When databinding is enabled, AGP adds a number of dependencies to the project, and this is entirely outside of the user's control. This plugin should not suggest removing or changing these libraries.

AGP 3.6.1

Databinding disabled

With AGP 3.6.1 and databinding not enabled, a build scan for ./gradlew app:assembleDebug shows the following debugCompileClasspath:

  • androidx.activity:activity:{strictly 1.0.0}
  • androidx.annotation:annotation:{strictly 1.1.0}
  • androidx.appcompat:appcompat:1.1.0
  • androidx.appcompat:appcompat:{strictly 1.1.0}
  • androidx.appcompat:appcompat-resources:{strictly 1.1.0}
  • androidx.arch.core:core-common:{strictly 2.1.0}
  • androidx.arch.core:core-runtime:{strictly 2.0.0}
  • androidx.collection:collection:{strictly 1.1.0}
  • androidx.constraintlayout:constraintlayout:1.1.3
  • androidx.constraintlayout:constraintlayout:{strictly 1.1.3}
  • androidx.constraintlayout:constraintlayout-solver:{strictly 1.1.3}
  • androidx.core:core:{strictly 1.1.0}
  • androidx.cursoradapter:cursoradapter:{strictly 1.0.0}
  • androidx.customview:customview:{strictly 1.0.0}
  • androidx.drawerlayout:drawerlayout:{strictly 1.0.0}
  • androidx.fragment:fragment:{strictly 1.1.0}
  • androidx.interpolator:interpolator:{strictly 1.0.0}
  • androidx.lifecycle:lifecycle-common:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-livedata:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-livedata-core:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-runtime:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-viewmodel:{strictly 2.1.0}
  • androidx.loader:loader:{strictly 1.0.0}
  • androidx.savedstate:savedstate:{strictly 1.0.0}
  • androidx.vectordrawable:vectordrawable:{strictly 1.1.0}
  • androidx.vectordrawable:vectordrawable-animated:{strictly 1.1.0}
  • androidx.versionedparcelable:versionedparcelable:{strictly 1.1.0}
  • androidx.viewpager:viewpager:{strictly 1.0.0}

and the following debugRuntimeClasspath:

  • androidx.appcompat:appcompat:1.1.0
  • androidx.constraintlayout:constraintlayout:1.1.3

debugAnnotationProcessorClasspath:
empty

Databinding enabled

build scan
debugCompileClasspath:

  • androidx.activity:activity:{strictly 1.0.0}
  • androidx.annotation:annotation:{strictly 1.1.0}
  • androidx.appcompat:appcompat:1.1.0
  • androidx.appcompat:appcompat:{strictly 1.1.0}
  • androidx.appcompat:appcompat-resources:{strictly 1.1.0}
  • androidx.arch.core:core-common:{strictly 2.1.0}
  • androidx.arch.core:core-runtime:{strictly 2.0.0}
  • androidx.collection:collection:{strictly 1.1.0}
  • androidx.constraintlayout:constraintlayout:1.1.3
  • androidx.constraintlayout:constraintlayout:{strictly 1.1.3}
  • androidx.constraintlayout:constraintlayout-solver:{strictly 1.1.3}
  • androidx.core:core:{strictly 1.1.0}
  • androidx.cursoradapter:cursoradapter:{strictly 1.0.0}
  • androidx.customview:customview:{strictly 1.0.0}
  • androidx.databinding:databinding-adapters:3.6.1
  • androidx.databinding:databinding-adapters:{strictly 3.6.1}
  • androidx.databinding:databinding-common:3.6.1
  • androidx.databinding:databinding-common:{strictly 3.6.1}
  • androidx.databinding:databinding-runtime:3.6.1
  • androidx.databinding:databinding-runtime:{strictly 3.6.1}
  • androidx.databinding:viewbinding:{strictly 3.6.1}
  • androidx.drawerlayout:drawerlayout:{strictly 1.0.0}
  • androidx.fragment:fragment:{strictly 1.1.0}
  • androidx.interpolator:interpolator:{strictly 1.0.0}
  • androidx.lifecycle:lifecycle-common:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-livedata:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-livedata-core:{strictly 2.0.0}
  • androidx.lifecycle:lifecycle-runtime:{strictly 2.1.0}
  • androidx.lifecycle:lifecycle-viewmodel:{strictly 2.1.0}
  • androidx.loader:loader:{strictly 1.0.0}
  • androidx.savedstate:savedstate:{strictly 1.0.0}
  • androidx.vectordrawable:vectordrawable:{strictly 1.1.0}
  • androidx.vectordrawable:vectordrawable-animated:{strictly 1.1.0}
  • androidx.versionedparcelable:versionedparcelable:{strictly 1.1.0}
  • androidx.viewpager:viewpager:{strictly 1.0.0}

debugRuntimeClasspath:

  • androidx.appcompat:appcompat:1.1.0
  • androidx.constraintlayout:constraintlayout:1.1.3
  • androidx.databinding:databinding-adapters:3.6.1
  • androidx.databinding:databinding-common:3.6.1
  • androidx.databinding:databinding-runtime:3.6.1

debugAnnotationProcessorClasspath:

  • androidx.databinding:databinding-compiler:3.6.1

So, databinding adds the following

debugCompileClasspath:
androidx.databinding:databinding-adapters:3.6.1
androidx.databinding:databinding-adapters:{strictly 3.6.1}
androidx.databinding:databinding-common:3.6.1
androidx.databinding:databinding-common:{strictly 3.6.1}
androidx.databinding:databinding-runtime:3.6.1
androidx.databinding:databinding-runtime:{strictly 3.6.1}
androidx.databinding:viewbinding:{strictly 3.6.1}

debugRuntimeClasspath:

  • androidx.databinding:databinding-adapters:3.6.1
  • androidx.databinding:databinding-common:3.6.1
  • androidx.databinding:databinding-runtime:3.6.1

debugAnnotationProcessorClasspath:

  • androidx.databinding:databinding-compiler:3.6.1

Dependency Analysis fails for pure java android app modules (no kotlin).

Gradle: 6.2.1
AGP: 3.5.3 / 3.6.1
Dependency Analysis plugin : 0.22.0

Describe the bug
the ./gradlew buildHealth command fails to configure a pure java (no kkotlin) android app.

A problem occurred configuring project ':app.
> Task with name 'compileDebugKotlin' not found in project ':app'.

To Reproduce

Steps to reproduce the behavior:

  1. create an android app with no kotlin code
  2. use the plugin

Expected behavior
It would work fine ;)

Additional context
Here is the full stack trace:

* Exception is:
org.gradle.api.ProjectConfigurationException: A problem occurred configuring project ':app.
        at org.gradle.configuration.project.LifecycleProjectEvaluator.wrapException(LifecycleProjectEvaluator.java:80)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.addConfigurationFailure(LifecycleProjectEvaluator.java:73)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.access$600(LifecycleProjectEvaluator.java:53)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate.run(LifecycleProjectEvaluator.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject$1.run(LifecycleProjectEvaluator.java:112)
        at org.gradle.internal.Factories$1.create(Factories.java:26)
        at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:237)
        at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:226)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:96)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:68)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:700)
        at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:142)
        at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:36)
        at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:64)
        at org.gradle.execution.TaskSelector.getSelection(TaskSelector.java:101)
        at org.gradle.execution.TaskSelector.getSelection(TaskSelector.java:82)
        at org.gradle.execution.commandline.CommandLineTaskParser.parseTasks(CommandLineTaskParser.java:42)
        at org.gradle.execution.TaskNameResolvingBuildConfigurationAction.configure(TaskNameResolvingBuildConfigurationAction.java:46)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.configure(DefaultBuildConfigurationActionExecuter.java:58)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.access$200(DefaultBuildConfigurationActionExecuter.java:26)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter$2.proceed(DefaultBuildConfigurationActionExecuter.java:66)
        at org.gradle.execution.DefaultTasksBuildExecutionAction.configure(DefaultTasksBuildExecutionAction.java:45)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.configure(DefaultBuildConfigurationActionExecuter.java:58)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.access$200(DefaultBuildConfigurationActionExecuter.java:26)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter$2.proceed(DefaultBuildConfigurationActionExecuter.java:66)
        at org.gradle.execution.ExcludedTaskFilteringBuildConfigurationAction.configure(ExcludedTaskFilteringBuildConfigurationAction.java:48)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.configure(DefaultBuildConfigurationActionExecuter.java:58)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.access$200(DefaultBuildConfigurationActionExecuter.java:26)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter$1.run(DefaultBuildConfigurationActionExecuter.java:44)
        at org.gradle.internal.Factories$1.create(Factories.java:26)
        at org.gradle.api.internal.project.DefaultProjectStateRegistry.withLenientState(DefaultProjectStateRegistry.java:134)
        at org.gradle.api.internal.project.DefaultProjectStateRegistry.withLenientState(DefaultProjectStateRegistry.java:126)
        at org.gradle.execution.DefaultBuildConfigurationActionExecuter.select(DefaultBuildConfigurationActionExecuter.java:40)
        at org.gradle.initialization.DefaultTaskExecutionPreparer.prepareForTaskExecution(DefaultTaskExecutionPreparer.java:38)
        at org.gradle.initialization.BuildOperatingFiringTaskExecutionPreparer$CalculateTaskGraph.populateTaskGraph(BuildOperatingFiringTaskExecutionPreparer.java:123)
        at org.gradle.initialization.BuildOperatingFiringTaskExecutionPreparer$CalculateTaskGraph.run(BuildOperatingFiringTaskExecutionPreparer.java:64)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.initialization.BuildOperatingFiringTaskExecutionPreparer.prepareForTaskExecution(BuildOperatingFiringTaskExecutionPreparer.java:52)
        at org.gradle.initialization.DefaultGradleLauncher.prepareTaskExecution(DefaultGradleLauncher.java:225)
        at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:159)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:140)
        at org.gradle.initialization.DefaultGradleLauncher.executeTasks(DefaultGradleLauncher.java:120)
        at org.gradle.internal.invocation.GradleBuildController$1.create(GradleBuildController.java:74)
        at org.gradle.internal.invocation.GradleBuildController$1.create(GradleBuildController.java:67)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
        at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
        at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:67)
        at org.gradle.internal.invocation.GradleBuildController.run(GradleBuildController.java:56)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:31)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:63)
        at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
        at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:51)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:45)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
        at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:80)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
        at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
        at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
        at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:60)
        at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:38)
        at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
        at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
        at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
        at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
        at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
        at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
        at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
        at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:68)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:29)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
        at org.gradle.util.Swapper.swap(Swapper.java:38)
        at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
        at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
        at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
        at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
        at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.api.UnknownTaskException: Task with name 'compileDebugKotlin' not found in project ':app'.
        at org.gradle.api.internal.tasks.DefaultTaskCollection.createNotFoundException(DefaultTaskCollection.java:102)
        at org.gradle.api.internal.tasks.DefaultTaskCollection.createNotFoundException(DefaultTaskCollection.java:46)
        at org.gradle.api.internal.DefaultNamedDomainObjectCollection.named(DefaultNamedDomainObjectCollection.java:359)
        at org.gradle.api.internal.tasks.DefaultTaskCollection.named(DefaultTaskCollection.java:112)
        at com.autonomousapps.internal.AndroidAppAnalyzer.registerClassAnalysisTask(dependencyAnalysis.kt:148)
        at com.autonomousapps.DependencyAnalysisPlugin.analyzeDependencies(DependencyAnalysisPlugin.kt:265)
        at com.autonomousapps.DependencyAnalysisPlugin.access$analyzeDependencies(DependencyAnalysisPlugin.kt:38)
        at com.autonomousapps.DependencyAnalysisPlugin$configureAndroidAppProject$1$1.execute(DependencyAnalysisPlugin.kt:84)
        at com.autonomousapps.DependencyAnalysisPlugin$configureAndroidAppProject$1$1.execute(DependencyAnalysisPlugin.kt:38)
        at org.gradle.api.internal.DefaultDomainObjectCollection.all(DefaultDomainObjectCollection.java:163)
        at com.autonomousapps.DependencyAnalysisPlugin$configureAndroidAppProject$1.execute(DependencyAnalysisPlugin.kt:78)
        at com.autonomousapps.DependencyAnalysisPlugin$configureAndroidAppProject$1.execute(DependencyAnalysisPlugin.kt:38)
        at org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator$BuildOperationEmittingAction$1.lambda$run$0(DefaultListenerBuildOperationDecorator.java:152)
        at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.reapply(DefaultUserCodeApplicationContext.java:60)
        at org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator$BuildOperationEmittingAction$1.run(DefaultListenerBuildOperationDecorator.java:152)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator$BuildOperationEmittingAction.execute(DefaultListenerBuildOperationDecorator.java:149)
        at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:92)
        at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:80)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:231)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:150)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:325)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:235)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:141)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at com.sun.proxy.$Proxy37.afterEvaluate(Unknown Source)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate$1.execute(LifecycleProjectEvaluator.java:191)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate$1.execute(LifecycleProjectEvaluator.java:188)
        at org.gradle.api.internal.project.DefaultProject.stepEvaluationListener(DefaultProject.java:1438)
        at org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate.run(LifecycleProjectEvaluator.java:197)
        ... 129 more

Improved configuration DSL

Current state

The current state of the dependencyAnalysis extension leaves a bit to be desired. Consider:

// root build.gradle
dependencyAnalysis {
  issues {
    onAny {
      fail("some:dep", "some-other:dep")
    }
  }
}

What does that mean? In fact, what it means is that, on detection of "any" issue (and there are three types that are distinguished; see below), the plugin will fail the build. Oh, and if it encounters either of "some:dep" or "some-other:dep", it will pretend those don't exist; they simply won't show up in any report, because they're being ignored (if you look at the source code for the fail() method, you'll see that its optional argument is named "ignore").

This is not very intuitive.

Three types of issue:

  1. Unused dependencies (which should be removed!) -> onUnusedDependencies {}
  2. Used transitive dependencies (which should be declared directly!) -> onUsedTransitiveDependencies {}
  3. Incorrect configuration for a dependency (is api but should be implementation, and vice-versa). -> onIncorrectConfiguration {}

And in addition, as one can see above, there is an onAny {} block which configures all three types simultaneously and equally.

There are currently three options for each of these three types:

  1. warn(). This is the default behavior. The plugin will print its advice to console and the build will not fail due to any dependency issue detected.
  2. fail(). This will tell the plugin to fail the build upon detection of the configured issue type.
  3. ignore(). This tells the plugin to ignore any dependencies issues of the associated type. Perhaps you don't care if you're using transitive dependencies, for example.

Consider this more complex example:

// root build.gradle
dependencyAnalysis {
  issues {
    onUnusedDependencies {
      fail("some:dep")
    }
    onUsedTransitiveDependencies {
      ignore()
    }
    onIncorrectConfiguration {
      warn("some-other:dep")
    }
  }
}

and the result of this is that:

  1. The plugin will fail if it discovers any unused (but declared) dependencies, unless that dependency is "some:dep", which it ignores.
  2. The plugin will ignore all issues relating to used transitive dependencies.
  3. The plugin will emit a warning and not fail the build if it detects a plugin on the wrong configuration, unless that dependency is "some-other:dep", which it ignores.

So, that's the current state.

Goals for an improved API

Readable

The first goal is readability. A DSL with a block like onUnusedDependencies { fail("some:dep") } isn't very readable, as it is natural to think we're telling the plugin to fail if "some:dep" is unused, which is roughly the opposite of the actual behavior.

Flexible

There is already some degree of flexibility, but more is desirable. For example, it might be useful to be able to ignore certain dependencies only for a particular project (or set of projects). Currently we can only ignore a dependency for all projects.

What about configuring this behavior via a file, instead of or addition to the DSL? Consider lint for example, which can be configured with an XML file. We could do the same, with XML or JSON or whatever.

Unambiguous

Currently there's a degree of ambiguity. If one configures both the onAny {} block and one of the others, what is the result? Does onAny supersede the more specific rule? Does the specific rule supersede the general? Are the rules combined in some way? In point of fact it's the last option (the rules are unioned together), but this is not obvious.

Proposed API

I'm currently considering something like the following:

issues {
  assumeIsolated = false // one of [true, false]
  
  // configure ':proj-a'
  project(':proj-a') {
    behavior = 'warn' // one of ['warn', 'fail', 'ignore']

    // The following are assumed to be correct. I.e., the plugin will not
    // suggest removing these if theyโ€™re found on the given configuration,
    // or variant thereof.
    convention {
      implementation = ['androidx.core:core-ktx', '*-ktx']
      api = ['androidx.multidex:multidex']
      // note that, by default, the plugin will not suggest changing a 
      // compileOnly dependency. It assumes users know what theyโ€™re
      // doing when they do that.
    }
  }

  // configure all projects
  all {
    ...
  }
}

Overlapping rules

When rulesets overlap (for example, you've configured all {} and specific projects, the system will layer these, with the more general at bottom and the more specific at top. So you might set all { behavior = 'warn' }, but project(':proj-a') { behavior = 'fail' }. Any issue detected in proj-a will lead to build failure, but issues in other projects would merely result in a warning.

Non-holistic / isolated changes

assumeIsolated: when unset or set to false (the default), the plugin follows default (current) behavior. When set to true, it will assume changes to the project will be made piecemeal (not holistically). As such, it will not suggest removing an "unused" dependency that is part of the ABI of a parent project unless that ABI dependency is on the api configuration; nor will it suggest reducing the visibility of any dependencies that are currently on api (even if they "should" be implementation). The idea is to minimize the potential to break a given subproject that is undergoing incremental (non-holistic) change. Correct implementation of such an algorithm would likely be very complex, and so would likely come last, if at all. Such a need may be highly specialized, and of uncertain general benefit.

Config file

One additional change I would like to make to the DSL is to provide an option to write it out to disk as a json config file. The dependencyAnalysis {} extension could then take a single config parameter that points to such a file, and then the file is the source of truth. Sort of like how lint can be configured in the Android world.

FR: ABI exclusion configuration

There are certain types of annotations or package name structures that are conventionally used as "public-but-private" cases

  • @Generated-annotated code is usually implementation detail for the code it originates from and is usually exposed (if at all) via something else.
  • @RestrictedApi (error prone) or @RestrictTo (androidx) annotations
  • package names with .internal in them
  • public kotlin code annotated with @PublishedApi, as they're only public for use with inline functions

All of these cases could be candidates to be treated as internal visibility to a module and not part of ABI consideration.

A proposal API for configuring this:

issues {
  abi {
    ignoreGeneratedCode() // Implicitly ignores `@Generated`
    ignoreAnnotations("androidx.annotation.RestrictTo", ...)
    ignorePattern("**.internal.**")
  }
}

Advice should include more explanations about dependency changes.

In 0.24.0 and below, the plugin is working well, but there is a gap between developers workflow and the plugin advises:

  • devs are working in one module, they will do changes one module at a time.
  • the plugin has a more holistic view of the changes.

This difference makes it so that changes in a single module are breaking because they suppose that other changes are applied in other modules. Devs cannot fix a module in isolation, test to see if this module compiles and move on. Applying the advises will create situations where compilation or annotation processing fails and the errors and stack traces they provide are very hard to make sense of.

Here is an example:

A impl -> C impl
A impl -> B impl -> C.

The plugin can say that C is not used by A and should be removed, it takes into account that B should be modified to : B api -> C.
But devs, just by looking at the advises for A will have no understanding of the changes required in B before they proceed to cleaning A.

If they apply the advises to A only and try to compile it, they can have dramatic errors that are completely unclear, and the issues are very hard to solve with the provided information.

Very often the problems they will face will be inside the class loading mechanisms of kapt/apt/javac/kotlinc and these tools don't provide fine grained info in these cases.

Ideally the plugin should be able to explain something like

dependency to C should be removed in A as it should be provided by B which requires B should have a dependency on C in the api configuration.

A workaround would be to explain devs that they should clean up modules in the topological order of modules which is not an easy notion to get, it would require assistance to do so as well.

FR - consider androidx ktx libraries to be the same dependency common androidx

Gradle version
6.1.1

Android Gradle Plugin (AGP) version
3.5.5

Describe the bug

As we are using kotlin in our project - we define only -ktx variants of androidx dependencies, even if code does not use any ktx extensions. Running adviceDebug task proposes to replace -ktx dependecny with the same dependency but without -ktx.

Expected behavior
Androidx -ktx dependencies are not reported as unused, when only code from non-ktx dependency is used.

Module that provides constant marked as unused

Gradle version - 6.1.1
Android Gradle Plugin (AGP) version - 3.5.3

Describe the bug

I am running adviceDebug task on a submodule ":one" that has a dependency on one a constant defined in submodule ":two" object class. Submodule ":two" is reported as unused, though it is needed.

Expected behavior
Submodule dependency ":two" is not reported as unused.

Print task outcomes even in case the task is cached

$ gw misusedDependenciesMain
..
BUILD SUCCESSFUL in 1s
14 actionable tasks: 14 up-to-date

I can't really see task output. It is sad.

I suggest that the task that prints output to the screen should be never up to date. Then the user could run the task again and again and see the current output.

FR - Post-processing hook

Alternative to #14. This could be a generic hook to handle parsed data and allow the consumer to perform custom operations in reaction to it. This could be used for verification, patching, or other stuff.

Some custom ones could be available as batteries-included options for generic build.gradle file modifications.

buildHealth task fails with NoSuchMethodError: org.gradle.workers.WorkerExecutor.noIsolation()Lorg/gradle/workers/WorkQueue

Running ./gradlew buildHealth --stacktrace gives the following failure:

...

> Task :common:abiAnalysisMain FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':common:abiAnalysisMain'.
> org.gradle.workers.WorkerExecutor.noIsolation()Lorg/gradle/workers/WorkQueue;

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':common:abiAnalysisMain'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.accept(ExecuteActionsTaskExecuter.java:151)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.accept(ExecuteActionsTaskExecuter.java:148)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:191)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:141)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionStateTaskExecuter.execute(ResolveBeforeExecutionStateTaskExecuter.java:75)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:108)
        at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExecuter.java:67)
        at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionStateTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:94)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:95)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:73)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:49)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: java.lang.NoSuchMethodError: org.gradle.workers.WorkerExecutor.noIsolation()Lorg/gradle/workers/WorkQueue;
        at com.autonomousapps.tasks.AbiAnalysisTask.action(AbiAnalysisTask.kt:43)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:103)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:48)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:702)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:669)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$5.run(ExecuteActionsTaskExecuter.java:404)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:393)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:376)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:213)
        at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:58)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:35)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:48)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:33)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:39)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
        at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:35)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:51)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:45)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:31)
        at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:201)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:70)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:45)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
        at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:43)
        at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:32)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:89)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:54)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:77)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:90)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:48)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:120)
        ... 35 more


* Get more help at https://help.gradle.org

BUILD FAILED in 0s
8 actionable tasks: 1 executed, 7 up-to-date
./gradlew --version

------------------------------------------------------------
Gradle 5.4.1
------------------------------------------------------------

Build time:   2019-04-26 08:14:42 UTC
Revision:     261d171646b36a6a28d5a19a69676cd098a4c19d

Kotlin:       1.3.21
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM:          1.8.0_202 (Oracle Corporation 25.202-b08)
OS:           Mac OS X 10.14.6 x86_64

I'd add more information but I don't know what would be useful here.

(Oh and the title of the issue could probably be improved with the actual cause :) )

Reported unused module but dimension resource is used from it

Gradle version
6.0.1

Android Gradle Plugin (AGP) version
3.5.3

Describe the bug
I have a module A that defines enum with dimension from module B:

enum class IconSize(@DimenRes val res: Int) {
    SMALL(R.dimen.icon_size_small),
    NORMAL(R.dimen.icon_size);
}

Unfortunately, in this case module B reported as a non-used in module A.

To Reproduce
Steps to reproduce the behavior:

  1. Use dimension in kotlin enum

Expected behavior
The module should not be reported as unused.

`buildHealth` fails with `java.lang.StringIndexOutOfBoundsException: String index out of range: -1`

Plugin version
0.25.0
Gradle version
6.2.2
Android Gradle Plugin (AGP) version
3.6.1
Describe the bug
buildHealth fails with StringIndexOutOfBoundsException: String index out of range: -1

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':around_you_implementation:inlineMemberExtractorDebug'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:205)
        at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:203)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:184)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing com.autonomousapps.tasks.InlineMemberExtractionWorkAction
        at org.gradle.workers.internal.DefaultWorkerExecutor$WorkItemExecution.waitForCompletion(DefaultWorkerExecutor.java:334)
        at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForItemsAndGatherFailures(DefaultAsyncWorkTracker.java:142)
        at org.gradle.internal.work.DefaultAsyncWorkTracker.access$000(DefaultAsyncWorkTracker.java:34)
        at org.gradle.internal.work.DefaultAsyncWorkTracker$1.run(DefaultAsyncWorkTracker.java:106)
        at org.gradle.internal.Factories$1.create(Factories.java:26)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withoutLocks(DefaultWorkerLeaseService.java:260)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withoutProjectLock(DefaultWorkerLeaseService.java:171)
        at org.gradle.internal.work.DefaultWorkerLeaseService.withoutProjectLock(DefaultWorkerLeaseService.java:165)
        at org.gradle.internal.work.StopShieldingWorkerLeaseService.withoutProjectLock(StopShieldingWorkerLeaseService.java:95)
        at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForItemsAndGatherFailures(DefaultAsyncWorkTracker.java:102)
        at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForAll(DefaultAsyncWorkTracker.java:80)
        at org.gradle.internal.work.DefaultAsyncWorkTracker.waitForCompletion(DefaultAsyncWorkTracker.java:68)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.run(ExecuteActionsTaskExecuter.java:576)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:553)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:536)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:109)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:276)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:265)
        at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:67)
        at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:36)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
        at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54)
        at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38)
        at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
        at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:153)
        at org.gradle.internal.execution.steps.CacheStep.executeAndStoreInCache(CacheStep.java:129)
        at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache$2(CacheStep.java:107)
        at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache$3(CacheStep.java:107)
        at org.gradle.internal.Try$Success.map(Try.java:162)
        at org.gradle.internal.execution.steps.CacheStep.executeWithCache(CacheStep.java:76)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:66)
        at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:41)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53)
        at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39)
        at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40)
        at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:192)
        ... 30 more
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
        at com.autonomousapps.tasks.InlineMemberFinder.find(InlineMemberExtractionTask.kt:223)
        at com.autonomousapps.tasks.InlineDependenciesFinder.findInlineImportCandidates(InlineMemberExtractionTask.kt:130)
        at com.autonomousapps.tasks.InlineDependenciesFinder.find(InlineMemberExtractionTask.kt:120)
        at com.autonomousapps.tasks.InlineMemberExtractionWorkAction.execute(InlineMemberExtractionTask.kt:96)
        at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
        at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
        at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
        at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:98)
        at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
        at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
        at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
        at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
        at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$2(DefaultWorkerExecutor.java:198)
        at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:215)
        at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:164)
        at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:131)
        ... 3 more

To Reproduce
thanks to #72 I was able to add additional logging to InlineMemberExtractionTask, build plugin locally and identify the
problem.

Crash happens because in my project there is Extensions.kt file without the package. As result, lastIndexOf("/) from InlineMemberExtractionTask returns "-1" for ExtensionsKt.kt and entry.name.substring(0, -1) crashes.

Expected behavior I have two proposals.
Option 1. Crash with a better message
Replace

val pn = entry.name.substring(0, entry.name.lastIndexOf("/")).replace("/", ".")

with

val pn = if (entry.name.contains("/")) {
    entry.name.substring(0, entry.name.lastIndexOf("/")).replace("/", ".")
} else {
    throw IllegalArgumentException("${entry.name} doesn't have a package.")
}

Option 2. Keep working, but notify about the problem.
Replace the same line with

val pn = if (entry.name.contains("/")) {
    entry.name.substring(0, entry.name.lastIndexOf("/")).replace("/", ".")
} else {
    logger.warn("${entry.name} doesn't have a package.")
    entry.name
}

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.