arunkumar9t2 / scabbard

🗡 A tool to visualize Dagger 2 dependency graphs
https://arunkumar9t2.github.io/scabbard
Apache License 2.0
851 stars 34 forks source link

No gutter icons present nor generated dot/png files in build #17

Closed ZacSweers closed 4 years ago

ZacSweers commented 4 years ago

Unfortuantely I can't share the project as it's our internal one, but happy to hop in the debugger locally and breakpoint if I could be pointed to some likely code blocks to check.

arunkumar9t2 commented 4 years ago

Oh, that's unfortunate. As a first step, could you please try enabling the failOnError flag which will fail the build on exception in scabbard so we know the cause? It could be enabled like this

scabbard {
   failOnError true
}

Additionally, below are important parts in processing step.

If you are willing to run locally, scabbard also ships with IDE run configurations to make debugging easier - you could replace scabbard-sample with your project and see if that helps. alt text

debugScabbardProcessor would start a gradle build in debug mode and wait for debugger. Then Attach Scabbard Debugger will attach and you should be able to step through. I'll document all this in Contributing.MD.

Ofcourse, I will also look into this, could you share if it is a pure java project?

jgindin commented 4 years ago

Also failing for me, and I'm also unable to share the project.

I did, as suggested above, add the failOnError true. Now when doing a Build -> Rebuild Project from IntelliJ, I get:

> Task :compileJava FAILED
14 actionable tasks: 3 executed, 11 up-to-date

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> java.lang.RuntimeException: Scabbard processor failed

IntelliJ then shows me this error: Attempt to reopen a file for path /home/<user>/src/<path/to/code>/build/classes/java/main/<package/path>FooApplicationComponent/<package.name>.FooApplicationComponent.png

(As a side note, this is a surprising place to locate the artifacts; I would have expected them to be in something like, e.g., build/generated/scabbard or something that is off on its own.)

arunkumar9t2 commented 4 years ago

@ZacSweers , by any chance do you use allprojects {} or subprojects {} to apply the plugin in a multi-module app?

@jgindin that error (FilerException) is intentionally ignored but the good news is it seems the processor is running. Could you flip the failOnError flag to false, run a build and let us know if images are there in the above folder even if gutter icon is not present?

surprising place to locate the artifacts

The reason is scabbard can only use standard annotation processing output directories. Work needs to be done in the gradle plugin to possibly copy the images into build/scabbard/.

ZacSweers commented 4 years ago

Yep using subprojects

digitalbuddha commented 4 years ago

this works for me in dropbox paper which is a 50ish module project. Not sure if overkill

subprojects { Project project ->

    project.plugins.withId('kapt') {
        project.apply plugin: 'scabbard.gradle'

        project.scabbard {
            enabled(true)
        }
    }

    project.plugins.withId('kotlin-kapt') {
        project.apply plugin: 'scabbard.gradle'

        project.scabbard {
            enabled(true)
        }
    }
}
arunkumar9t2 commented 4 years ago

It does not work when using allprojects or subprojects because this block runs before other plugins declaration in sub project build.gradles are executed, so scabbard thinks kapt is not there.

@digitalbuddha thanks! I was just typing the same thing which is to apply the plugin only when kapt is added. Below are blocks for both Kotlin and groovy.

subprojects {
  plugins.withId('kotlin-kapt') {
     apply plugin: 'scabbard.gradle'
      scabbard {
          enabled(true)
      }
  }
}

Kotlin

subprojects {
  plugins.withId("kotlin-kapt") {
    apply(plugin ="scabbard.gradle")
    the<ScabbardPluginExtension>().configure(closureOf<ScabbardSpec> {
      enabled(true)
    })
  }
}

I'll update the docs. @ZacSweers I tested the above kotlin config on CatchUp and it seems to work, please let me know how it goes.

ZacSweers commented 4 years ago

I see. Why is scabbard dependent on kapt? I feel like it's trying a bit too hard to magically cover cases and the result is that it's a bit limited to a single happy path usage as a result

arunkumar9t2 commented 4 years ago

I see. Why is scabbard dependent on kapt?

It is not actually dependent just that it needs to detect whether kapt is available so that scabbard's processor can be applied on kapt config when available instead of annotationProcessor.

that it's a bit limited to a single happy path usage as a result

I agree. I assumed specifying plugin order (i.e apply scabbard at the last) would be enough (it does work that way) but overlooked issue when applied via subprojects. I have an idea to remove all the ceremony and make it reliable, will work on it priority for next release.

In the mean time, could you confirm if plugin application is the issue and any of the above solutions fixes your use case? Would like to rule out any other issue. Thanks!

antonicg commented 4 years ago

Im having also a problem in a multimodule project and I think it is related. I set up the configuration @digitalbuddha suggested and it is building the images for most of the components except for the root ones if I set the failOnError as false. If I set it as true it is giving me the following error:

> Task :base:kaptDebugKotlin
e: <REDACTED>/BaseSessionComponentProvider.java:31: error: cannot find symbol
    protected kotlin.reflect.KClass<DaggerBaseSessionComponent> graphClass() {
                                    ^
  symbol:   class DaggerBaseSessionComponent
  location: class BaseSessionComponentProvider
e: <REDACTED>/BaseRatingComponentProvider.java:29: error: cannot find symbol
    protected kotlin.reflect.KClass<DaggerBaseRatingComponent> graphClass() {
                                    ^
  symbol:   class DaggerBaseRatingComponent
  location: class BaseRatingComponentProvider
e: [kapt] An exception occurred: java.lang.RuntimeException: Scabbard processor failed
    at dev.arunkumar.scabbard.plugin.processor.graphviz.GraphVizBindingGraphProcessor.process(GraphVizBindingGraphProcessor.kt:342)
    at dev.arunkumar.scabbard.plugin.ScabbardBindingGraphPlugin.visitGraph(ScabbardBindingGraphPlugin.kt:46)
    at dagger.internal.codegen.validation.BindingGraphValidator.runPlugins(BindingGraphValidator.java:101)
    at dagger.internal.codegen.validation.BindingGraphValidator.visitPlugins(BindingGraphValidator.java:91)
    at dagger.internal.codegen.validation.BindingGraphValidator.isValid(BindingGraphValidator.java:65)
    at dagger.internal.codegen.ComponentProcessingStep.isValid(ComponentProcessingStep.java:254)
    at dagger.internal.codegen.ComponentProcessingStep.processRootComponent(ComponentProcessingStep.java:151)
    at dagger.internal.codegen.ComponentProcessingStep.process(ComponentProcessingStep.java:131)
    at dagger.internal.codegen.ComponentProcessingStep.process(ComponentProcessingStep.java:62)
    at dagger.internal.codegen.validation.TypeCheckingProcessingStep.lambda$process$0(TypeCheckingProcessingStep.java:51)
    at com.google.common.collect.RegularImmutableMap.forEach(RegularImmutableMap.java:185)
    at dagger.internal.codegen.validation.TypeCheckingProcessingStep.process(TypeCheckingProcessingStep.java:48)
    at dagger.internal.codegen.ComponentProcessingStep.process(ComponentProcessingStep.java:124)
    at dagger.internal.codegen.ComponentProcessingStep.process(ComponentProcessingStep.java:62)
    at dagger.internal.codegen.statistics.DaggerStatisticsCollectingProcessingStep.process(DaggerStatisticsCollectingProcessingStep.java:52)
    at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:330)
    at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:181)
    at org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor.process(incrementalProcessors.kt)
    at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:147)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1068)
    at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:79)
    at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:35)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:224)
    at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:187)
    at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:98)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:97)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:107)
    at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:82)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:557)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:82)
    at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:107)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:548)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:177)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:165)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:55)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:84)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:42)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:104)
    at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1558)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: Scabbard processor failed
    at dev.arunkumar.scabbard.plugin.processor.graphviz.GraphVizBindingGraphProcessor.process(GraphVizBindingGraphProcessor.kt:320)
    ... 61 more
Caused by: javax.annotation.processing.FilerException: Attempt to reopen a file for path <REDACTED>/BaseComponent/<REDACTED>.BaseComponent.png
    at com.sun.tools.javac.processing.JavacFiler.checkFileReopening(JavacFiler.java:535)
    at com.sun.tools.javac.processing.JavacFiler.createResource(JavacFiler.java:431)
    at org.jetbrains.kotlin.kapt3.base.incremental.IncrementalFiler.createResource(incrementalProcessors.kt:99)
    at dev.arunkumar.scabbard.plugin.output.DefaultOutputManager.createOutputFiles(DefaultOutputManager.kt:24)
    at dev.arunkumar.scabbard.plugin.processor.graphviz.GraphVizBindingGraphProcessor.process(GraphVizBindingGraphProcessor.kt:74)
arunkumar9t2 commented 4 years ago

Hey @antonicg, thank you for reporting. That specific error (FilerException) is currently fixed on master as part of #34. Also may I know if you are using full graph validation?

I am working on improving the Gradle plugin syntax and trying to avoid all the ceremony required when using subprojects etc. I am targeting a release soon. Unfortunately, I do not publish snapshot artifacts yet for you to try the fix.

May I understand if gutter icons and images are generated when failOnError is false, at least for some components?

antonicg commented 4 years ago

@arunkumar9t2 Yes, I was using the fullBindingGraphValidation when I set the failOnError as true. But the images for the most of the components are generated if I set the failOnError as false. It is also generating the images no matter the value of fullBindingGraphValidation.

Glad to hear that a release will be a release soon with the fix, I will try then 👌

arunkumar9t2 commented 4 years ago

I just released 0.2.0 which contains fixes for issues mentioned in this thread.

  1. @ZacSweers' usage by subprojects or allprojects. This is now handled by the plugin itself. When the plugin is applied to a root project, it will automatically configure all subprojects making it easier to apply on multi-module projects. Additionally, the ceremony for configuring from KTS is now not needed.

    -scabbard.configure(closureOf<ScabbardSpec> {
    +scabbard { // this : ScabbardPluginExtension 
        enabled = true
        failOnError = false
    + }
    - })
  2. @jgindin, @antonicg The FilerException issue is also fixed as part of #34.

Would be happy to know if this resolves the issues, thanks.

arunkumar9t2 commented 4 years ago

As mentioned in my previous comment, core issues that would cause the annotation processor to not run/fail was addressed. I am closing this for now, please feel free to open again if there are any issues.