Repository: quarkusio/quarkus
Issue: QuarkusGenerateCode gradle task is not incremental

## Describe the bug

When running `quarkusBuild` or `quarkusDev`, it triggers `quarkusGenerateCode` task. This tasks is always ran, even when no change happen.

### Expected behavior
The task should be `UP-TO-DATE`, if no changes happen to 

 
### Actual behavior
The task always is always ran

## To Reproduce

Steps to reproduce the behavior:
1. Create a simple project 
2. run `./gradlew quarkusBuild` multiple times, it never will be `UP-TO-DATE`.



Changed files:
integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java

diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java b/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
index b8dee8f1741..f61804ee4a8 100644
--- a/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
+++ b/devtools/gradle/src/main/java/io/quarkus/gradle/QuarkusPlugin.java
@@ -153,11 +153,9 @@ public void execute(Task test) {
                     compileJavaTask.getOptions().setAnnotationProcessorPath(annotationProcessorConfig);
 
                     compileJavaTask.dependsOn(quarkusGenerateCode);
-                    quarkusGenerateCode.setSourceRegistrar(compileJavaTask::source);
 
                     JavaCompile compileTestJavaTask = (JavaCompile) tasks.getByName(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME);
                     compileTestJavaTask.dependsOn(quarkusGenerateCodeTests);
-                    quarkusGenerateCodeTests.setSourceRegistrar(compileTestJavaTask::source);
 
                     Task classesTask = tasks.getByName(JavaPlugin.CLASSES_TASK_NAME);
                     Task resourcesTask = tasks.getByName(JavaPlugin.PROCESS_RESOURCES_TASK_NAME);
@@ -204,27 +202,24 @@ public void execute(Task test) {
                     tasks.withType(Test.class).forEach(configureTestTask);
                     tasks.withType(Test.class).whenTaskAdded(configureTestTask::accept);
 
-                    sourceSets.create(QuarkusGenerateCode.QUARKUS_GENERATED_SOURCES).getOutput()
+                    SourceSet generatedSourceSet = sourceSets.create(QuarkusGenerateCode.QUARKUS_GENERATED_SOURCES);
+                    generatedSourceSet.getOutput()
                             .dir(QuarkusGenerateCode.QUARKUS_GENERATED_SOURCES);
-                    sourceSets.create(QuarkusGenerateCode.QUARKUS_TEST_GENERATED_SOURCES).getOutput()
+                    SourceSet generatedTestSourceSet = sourceSets.create(QuarkusGenerateCode.QUARKUS_TEST_GENERATED_SOURCES);
+                    generatedTestSourceSet.getOutput()
                             .dir(QuarkusGenerateCode.QUARKUS_TEST_GENERATED_SOURCES);
+
+                    // Register the quarkus-generated-code
+                    for (String provider : QuarkusGenerateCode.CODE_GENERATION_PROVIDER) {
+                        mainSourceSet.getJava().srcDir(new File(generatedSourceSet.getJava().getOutputDir(), provider));
+                        testSourceSet.getJava().srcDir(new File(generatedTestSourceSet.getJava().getOutputDir(), provider));
+                    }
+
                 });
 
         project.getPlugins().withId("org.jetbrains.kotlin.jvm", plugin -> {
             tasks.getByName("compileKotlin").dependsOn(quarkusGenerateCode);
             tasks.getByName("compileTestKotlin").dependsOn(quarkusGenerateCodeTests);
-
-            // Register the quarkus-generated-code
-            SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class)
-                    .getSourceSets();
-            SourceSet mainSourceSet = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
-            SourceSet testSourceSet = sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME);
-            SourceSet generatedSourceSet = sourceSets.getByName(QuarkusGenerateCode.QUARKUS_GENERATED_SOURCES);
-            SourceSet generatedTestSourceSet = sourceSets.getByName(QuarkusGenerateCode.QUARKUS_TEST_GENERATED_SOURCES);
-            for (String provider : QuarkusGenerateCode.CODE_GENERATION_PROVIDER) {
-                mainSourceSet.getJava().srcDir(new File(generatedSourceSet.getJava().getOutputDir(), provider));
-                testSourceSet.getJava().srcDir(new File(generatedTestSourceSet.getJava().getOutputDir(), provider));
-            }
         });
     }
 
diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java
index 0b1dbb5537e..6ec53119ea6 100644
--- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java
+++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java
@@ -1,10 +1,13 @@
 package io.quarkus.gradle.tasks;
 
+import java.io.File;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Properties;
@@ -16,6 +19,8 @@
 import org.gradle.api.plugins.Convention;
 import org.gradle.api.plugins.JavaPluginConvention;
 import org.gradle.api.tasks.CompileClasspath;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputDirectories;
 import org.gradle.api.tasks.SourceSet;
 import org.gradle.api.tasks.TaskAction;
 
@@ -33,10 +38,12 @@ public class QuarkusGenerateCode extends QuarkusTask {
     public static final String QUARKUS_TEST_GENERATED_SOURCES = "quarkus-test-generated-sources";
     // TODO dynamically load generation provider, or make them write code directly in quarkus-generated-sources
     public static final String[] CODE_GENERATION_PROVIDER = new String[] { "grpc", "avdl", "avpr", "avsc" };
+    public static final String[] CODE_GENERATION_INPUT = new String[] { "proto", "avro" };
 
     public static final String INIT_AND_RUN = "initAndRun";
     private Set<Path> sourcesDirectories;
-    private Consumer<Path> sourceRegistrar;
+    private Consumer<Path> sourceRegistrar = (p) -> {
+    };
     private boolean test = false;
 
     public QuarkusGenerateCode() {
@@ -53,6 +60,29 @@ public FileCollection getClasspath() {
         return QuarkusGradleUtils.getSourceSet(getProject(), SourceSet.MAIN_SOURCE_SET_NAME).getCompileClasspath();
     }
 
+    @InputFiles
+    public Set<File> getInputDirectory() {
+        Set<File> inputDirectories = new HashSet<>();
+
+        final String inputSourceSetName = test ? SourceSet.TEST_SOURCE_SET_NAME : SourceSet.MAIN_SOURCE_SET_NAME;
+        Path src = getProject().getProjectDir().toPath().resolve("src").resolve(inputSourceSetName);
+
+        for (String input : CODE_GENERATION_INPUT) {
+            Path providerSrcDir = src.resolve(input);
+            if (Files.exists(providerSrcDir)) {
+                inputDirectories.add(providerSrcDir.toFile());
+            }
+        }
+
+        return inputDirectories;
+    }
+
+    @OutputDirectories
+    public FileCollection getGeneratedOutputDirectory() {
+        final String generatedSourceSetName = test ? QUARKUS_TEST_GENERATED_SOURCES : QUARKUS_GENERATED_SOURCES;
+        return QuarkusGradleUtils.getSourceSet(getProject(), generatedSourceSetName).getOutput().getDirs();
+    }
+
     @TaskAction
     public void prepareQuarkus() {
         getLogger().lifecycle("preparing quarkus application");
@@ -118,10 +148,6 @@ public void setSourcesDirectories(Set<Path> sourcesDirectories) {
         this.sourcesDirectories = sourcesDirectories;
     }
 
-    public void setSourceRegistrar(Consumer<Path> sourceRegistrar) {
-        this.sourceRegistrar = sourceRegistrar;
-    }
-
     public void setTest(boolean test) {
         this.test = test;
     }
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
index da308b09bf3..251bcb0baaa 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/builder/QuarkusModelBuilderTest.java
@@ -77,8 +77,8 @@ private void assertWorkspace(WorkspaceModule workspaceModule, File projectDir) {
                 new File(projectDir, "build/classes/java/test"));
         final SourceSet sourceSourceSet = workspaceModule.getSourceSourceSet();
         assertEquals(new File(projectDir, "src/main/resources"), sourceSourceSet.getResourceDirectory());
-        assertEquals(1, sourceSourceSet.getSourceDirectories().size());
-        assertEquals(new File(projectDir, "src/main/java"), sourceSourceSet.getSourceDirectories().iterator().next());
+        assertEquals(5, sourceSourceSet.getSourceDirectories().size());
+        assertThat(sourceSourceSet.getSourceDirectories()).contains(new File(projectDir, "src/main/java"));
     }
 
     private File getResourcesProject(String projectName) throws URISyntaxException, IOException {