Repository: analysis-dev/diktat (kotlin)

Issue:
Gradle plug-in: unable to specify inputs if Groovy DSL is used
Try to build the [example project](https://github.com/saveourtool/diktat/tree/master/examples/gradle-groovy-dsl) which uses the Groovy DSL. The build will fail:

```console
C:\diktat\examples\gradle-groovy-dsl>gradle build                                                                                                        
FAILURE: Build failed with an exception.

* Where:
Build file 'C:\diktat\examples\gradle-groovy-dsl\build.gradle' line: 9

* What went wrong:
A problem occurred evaluating root project 'gradle-groovy-dsl'.
> No signature of method: build_8ip68wiz5ht9rnwfbccz91le2.diktat() is applicable for argument types: (build_8ip68wiz5ht9rnwfbccz91le2$_run_closure2) values: [build_8ip68wiz5ht9rnwfbccz91le2$_run_closure2@408bf572]
  Possible solutions: getAt(java.lang.String), with(groovy.lang.Closure), tap(groovy.lang.Closure)

* 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

BUILD FAILED in 1s
```

Apparently, the Groovy DSL doesn't understand this Kotlin signature:

```kotlin
    /**
     * Configure input files for diktat task
     *
     * @param action configuration lambda for `PatternFilterable`
     */
    fun inputs(action: PatternFilterable.() -> Unit) {
        action.invoke(patternSet)
    }
```

An empty `inputs { }` block is ok:

```groovy
diktat {
    inputs {
    }
    reporter = "plain"
    debug = false
}
```

Any attempt to specify the include or exclude rules within the block will lead to a failure.

## Environment information
* diktat version: 1.2.1
* build tool (maven/gradle): Gradle (6.8 and 7.4)
* how is diktat run (CLI, plugin, etc.): gradle plug-in
* kotlin version: 1.7.0
* operating system: Windows

Pull request:
### What's done:
* Update build.gradle in examples
* Add functional test for Groovy DSL with explicit inputs
* Fix docs for `diktatExtension.output`: reporter treats any non-empty string as a file name, there are no special values
* Remove `dependsOn` relation between `test` and `functionalTest`, use `shouldRunAfter` instead

This pull request closes #1422

Patch:
diff --git a/diktat-gradle-plugin/build.gradle.kts b/diktat-gradle-plugin/build.gradle.kts
index 3a1b0f0423..95c506dbe5 100644
--- a/diktat-gradle-plugin/build.gradle.kts
+++ b/diktat-gradle-plugin/build.gradle.kts
@@ -27,8 +27,9 @@ repositories {
 }
 
 // default value is needed for correct gradle loading in IDEA; actual value from maven is used during build
-val ktlintVersion = project.properties.getOrDefault("ktlintVersion", "0.43.0") as String
-val diktatVersion = project.version.takeIf { it.toString() != Project.DEFAULT_VERSION } ?: "1.1.0"
+// To debug gradle plugin, please set `diktatVersion` manually to the current maven project version.
+val ktlintVersion = project.properties.getOrDefault("ktlintVersion", "0.46.1") as String
+val diktatVersion = project.version.takeIf { it.toString() != Project.DEFAULT_VERSION } ?: "1.2.1"
 val junitVersion = project.properties.getOrDefault("junitVersion", "5.8.1") as String
 val jacocoVersion = project.properties.getOrDefault("jacocoVersion", "0.8.7") as String
 dependencies {
@@ -107,7 +108,7 @@ val functionalTest = sourceSets.create("functionalTest") {
     runtimeClasspath += output + compileClasspath
 }
 tasks.getByName<Test>("functionalTest") {
-    dependsOn("test")
+    shouldRunAfter("test")
     testClassesDirs = functionalTest.output.classesDirs
     classpath = functionalTest.runtimeClasspath
     maxParallelForks = Runtime.getRuntime().availableProcessors()
@@ -131,7 +132,7 @@ jacocoTestKit {
     applyTo("functionalTestRuntimeOnly", tasks.named("functionalTest"))
 }
 tasks.jacocoTestReport {
-    dependsOn(tasks.withType<Test>())
+    shouldRunAfter(tasks.withType<Test>())
     executionData(
         fileTree("$buildDir/jacoco").apply {
             include("*.exec")
diff --git a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatExtension.kt b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatExtension.kt
index 48595df852..f2d4c5e1c9 100644
--- a/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatExtension.kt
+++ b/diktat-gradle-plugin/src/main/kotlin/org/cqfn/diktat/plugin/gradle/DiktatExtension.kt
@@ -34,8 +34,7 @@ open class DiktatExtension(
     var reporter: String = "plain"
 
     /**
-     * Type of output
-     * Default: System.out
+     * Destination for reporter. If empty, will write to stdout.
      */
     var output: String = ""
 
diff --git a/examples/gradle-groovy-dsl/build.gradle b/examples/gradle-groovy-dsl/build.gradle
index b471212824..034bb0c144 100644
--- a/examples/gradle-groovy-dsl/build.gradle
+++ b/examples/gradle-groovy-dsl/build.gradle
@@ -7,5 +7,6 @@ repositories {
 }
 
 diktat {
-    inputs { include ("src/**/*.kt") }
+    inputs { it.include ("src/**/*.kt") }
+    diktatConfigFile = file(rootDir.path + "/diktat-analysis.yml")
 }


Test patch:
diff --git a/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginGroovyFunctionalTest.kt b/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginGroovyFunctionalTest.kt
index 27200776e0..d883729d26 100644
--- a/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginGroovyFunctionalTest.kt
+++ b/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/DiktatGradlePluginGroovyFunctionalTest.kt
@@ -27,14 +27,26 @@ class DiktatGradlePluginGroovyFunctionalTest {
     }
 
     @Test
-    fun `should execute diktatCheck on default values`() {
+    fun `should execute diktatCheck with default values`() {
         val result = runDiktat(testProjectDir, shouldSucceed = false)
 
-        val diktatCheckBuildResult = result.task(":${DiktatGradlePlugin.DIKTAT_CHECK_TASK}")
-        requireNotNull(diktatCheckBuildResult)
-        Assertions.assertEquals(TaskOutcome.FAILED, diktatCheckBuildResult.outcome)
-        Assertions.assertTrue(
-            result.output.contains("[FILE_NAME_MATCH_CLASS]")
+        assertDiktatExecuted(result)
+    }
+
+    @Test
+    fun `should execute diktatCheck with explicit configuration`() {
+        buildFile.appendText(
+            """${System.lineSeparator()}
+                diktat {
+                    inputs { it.include("src/**/*.kt") }
+                    reporter = "plain"
+                    diktatConfigFile = file(rootDir.path + "/diktat-analysis.yml")
+                }
+            """.trimIndent()
         )
+
+        val result = runDiktat(testProjectDir, shouldSucceed = false)
+
+        assertDiktatExecuted(result)
     }
 }
diff --git a/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt b/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt
index 246c54f705..4a0d552e28 100644
--- a/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt
+++ b/diktat-gradle-plugin/src/functionalTest/kotlin/org/cqfn/diktat/plugin/gradle/Utils.kt
@@ -2,7 +2,10 @@ package org.cqfn.diktat.plugin.gradle
 
 import org.gradle.buildinit.plugins.internal.modifiers.BuildInitDsl
 import org.gradle.internal.impldep.org.junit.rules.TemporaryFolder
+import org.gradle.testkit.runner.BuildResult
 import org.gradle.testkit.runner.GradleRunner
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.jupiter.api.Assertions
 import java.io.File
 import java.util.concurrent.atomic.AtomicInteger
 
@@ -71,3 +74,12 @@ private fun GradleRunner.withJaCoCo(number: Int) = apply {
             }
         }
 }
+
+fun assertDiktatExecuted(result: BuildResult) {
+    val diktatCheckBuildResult = result.task(":${DiktatGradlePlugin.DIKTAT_CHECK_TASK}")
+    requireNotNull(diktatCheckBuildResult)
+    Assertions.assertEquals(TaskOutcome.FAILED, diktatCheckBuildResult.outcome)
+    Assertions.assertTrue(
+        result.output.contains("[FILE_NAME_MATCH_CLASS]")
+    )
+}