Hey all, I'm trying to add an additional source se...
# kotlin-dsl
a
Hey all, I'm trying to add an additional source set to a JvmTestSuite I have the following and it looks like I cannot reference any classes from that source set in the one created for the JvmTestSuite
Copy code
testing {
    suites {
        getByName<JvmTestSuite>("functionalTest") {
            sources {
                kotlin.srcDir(layout.buildDirectory.dir("generated/api/src/main/kotlin"))
            }
            dependencies {
                ...
            }
        }
    }
}
The JvmTestSuite is previously created btw
Looks like its an issue from IntelliJ side 😢
v
Actually, you should usually not configure paths anyway, or you will miss the task dependencies to generate or update the sources. Instead you should configure the task that generates the files as
srcDir
directly. Given it properly declares its outputs, they become source files and all consumers automatically have the necessary task dependencies.
Not sure whether that will solve your concrete problem though, for that an MCVE could probably help. Besides that your question seems to have little relevance to the channel topic. ;-)
a
Hey @Vampire, yes my bad, I will provide a MCVE let me just setup a repo. In the meanwhile what I'm trying to do is include generated code in my main and functionalTest sourceSets, and the way Im doing works but for intellij it seems the IDEA can't understand that 😅
and was wondering if anyone else had this problem
v
the way Im doing works
It might appear to work and maybe even work in some cases. But if you manually configured a path, it most probably does not cleanly work in all cases, and is discouraged bad practice. And I personally never had problems with IntelliJ and generated code when properly configuring it. 🙂 Mainly with Java, but I'd hope with Kotlin it is not much different.
a
Here is the MCVE https://github.com/chriptus13/OASGeneratorWIP My issue is with functionalTest configuration which in IDEA does not recognise configured sourceSets as per image
I've also tried with the approach you mentioned
Instead you should configure the task that generates the files as
srcDir
directly.
With it also main code does not recognise it
like this
v
You should usually not use the
-all
distribution. There are 2 use-cases I know where it might help, one does not affect you and the other is a pretty rare edge case that most probably does not affect you. In all other cases it is just a waste of time, bandwidth, and disk space for each and everone and everything executing such a build. Ok, so now seeing your MCVE it is exactly like I said. It works "sometimes", but not all source consumers have a dependency on the generation task. Only the
compileKotlin
and
compileFunctionalTestKotlin
have a dependency as you manually configured it. That means any other consumer of source files (static code analysis tasks, sources jar task, ......) do not have a dependency. If they happen to run before the generation task the files are missing or stale from a previous run, if they happen to run after, they might get the correct files accidentally. Whenever you have a
dependsOn
where on the left-hand side is not a lifecycle task, that is a code smell and a strong sign that you are doing something wrong which is bad practice and discouraged. Besides that, the MCVE is not V, the generation task fails with
Copy code
Error resolving schema #/components/schemas/Orders
java.net.URISyntaxException: Illegal character in opaque part at index 2: D:\...\OASGeneratorWIP\app\specs\api-oas.yaml
Also, calling
.get()
on a
Property
at configuration time is a very bad idea. It destroys the sense of lazy evaluation only at execution time. (line 32) There it should probably be
.map { it.asFile.absolutePath }
instead and
.asFile.absolutePath
in the next line. So using this patch:
Copy code
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2a5a268..31c4f69 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,5 +1,4 @@
 import org.openapitools.codegen.languages.KotlinSpringServerCodegen
-import org.openapitools.generator.gradle.plugin.tasks.GenerateTask

 plugins {
     `common-kotlin`
@@ -29,8 +28,8 @@ openApiGenerate {
     packageName = "<http://org.example.specfirst.app|org.example.specfirst.app>"
     apiPackage = "<http://org.example.specfirst.app|org.example.specfirst.app>"
     modelPackage = "org.example.specfirst.app.model"
-    outputDir = layout.buildDirectory.dir("generated/openapi").get().toString()
-    inputSpec = layout.projectDirectory.file("specs/api-oas.yaml").toString()
+    outputDir = layout.buildDirectory.dir("generated/openapi").map { it.asFile.absolutePath }
+    inputSpec = layout.projectDirectory.file("specs/api-oas.yaml").asFile.absolutePath
     configOptions = mapOf(
         KotlinSpringServerCodegen.INTERFACE_ONLY to "true",
         KotlinSpringServerCodegen.USE_TAGS to "true",
@@ -44,28 +43,20 @@ openApiGenerate {
 kotlin.sourceSets {
     main {
         kotlin {
-            srcDir(layout.buildDirectory.dir("generated/openapi/src/main/kotlin"))
+            srcDir(tasks.openApiGenerate)
         }
     }
     functionalTest {
         kotlin {
-            srcDir(layout.buildDirectory.dir("generated/openapi/src/main/kotlin"))
+            srcDir(tasks.openApiGenerate)
         }
     }
 }

-tasks.compileKotlin {
-    dependsOn(tasks.withType<GenerateTask>())
-}
-
-tasks.compileFunctionalTestKotlin {
-    dependsOn(tasks.withType<GenerateTask>())
-}
-
 testing.suites {
     getByName(TestingSuites.FUNCTIONAL_TEST) {
         dependencies {

         }
     }
-}
\ No newline at end of file
+}
does fix the
get
and
dependsOn
stuff and it works exactly like you are seeing now, it works in main source set but not in the test source set. But having said all that, your main problem is, that IntelliJ can use a given source root only once. As you define the same directory as source directory for both source sets, you waste time by compiling those sources twice. But more importantly, as I said, IntelliJ can only add a directory to one module as source set but in your setup it would need to add it to two modules and that is simply not supported by IntelliJ as this also usually does not make much sense. More typically you have it in one place and depend on it from the other place or the other two places.
🙌 1
Btw. as you do not use the generated Gradle project from the generator, you might also want to disable all those useless auxiliary files with something like
Copy code
diff --git a/app/.openapi-generator-ignore b/app/.openapi-generator-ignore
new file mode 100644
index 0000000..dc40c93
--- /dev/null
+++ b/app/.openapi-generator-ignore
@@ -0,0 +1,2 @@
+/build/generated/openapi/**
+!build/generated/openapi/org/**
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2a5a268..896b8af 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,3 +1,4 @@
+import org.gradle.api.tasks.PathSensitivity.NONE
 import org.openapitools.codegen.languages.KotlinSpringServerCodegen
 import org.openapitools.generator.gradle.plugin.tasks.GenerateTask

@@ -24,6 +25,8 @@ dependencies {
     runtimeOnly(libs.logback)
 }

+val openApiGeneratorIgnoreFile = layout.projectDirectory.file(".openapi-generator-ignore")
+
 openApiGenerate {
     generatorName = "kotlin-spring"
     packageName = "<http://org.example.specfirst.app|org.example.specfirst.app>"
@@ -32,6 +35,7 @@ openApiGenerate {
     outputDir = layout.buildDirectory.dir("generated/openapi").get().toString()
     inputSpec = layout.projectDirectory.file("specs/api-oas.yaml").toString()
     configOptions = mapOf(
+        "sourceFolder" to "",
         KotlinSpringServerCodegen.INTERFACE_ONLY to "true",
         KotlinSpringServerCodegen.USE_TAGS to "true",
         "library" to KotlinSpringServerCodegen.SPRING_BOOT,
@@ -39,6 +43,19 @@ openApiGenerate {
         KotlinSpringServerCodegen.DOCUMENTATION_PROVIDER to "none",
         KotlinSpringServerCodegen.ANNOTATION_LIBRARY to "none",
     )
+    generateApiDocumentation = false
+    generateApiTests = false
+    generateModelDocumentation = false
+    generateModelTests = false
+    ignoreFileOverride = openApiGeneratorIgnoreFile.asFile.absolutePath
+}
+
+//work-around for <https://github.com/OpenAPITools/openapi-generator/issues/10214>
+tasks.openApiGenerate {
+    inputs
+        .files(openApiGeneratorIgnoreFile)
+        .withPathSensitivity(NONE)
+        .withPropertyName("openApiGeneratorIgnoreFile")
 }

 kotlin.sourceSets {
👍 1
a
First of all, thanks for such long and detailed analysis of my issue and for all the good practice tips! Regarding this
Besides that, the MCVE is not V, the generation task fails with
```Error resolving schema #/components/schemas/Orders
java.net.URISyntaxException: Illegal character in opaque part at index 2: D:\...\OASGeneratorWIP\app\specs\api-oas.yaml```
I don't have that issue, do you get it when running
gradle build
? Regarding the main issue I understand the problem is with Intellij, although was wondering if there is a correct way of doing this via gradle that would end up being recognised by IntelliJ.
Ya , I’d already thought about getting rid of the generated Gradle project.
v
I don't have that issue,
Because you probably are on non-Windoze I get it on
gw openApiGenerate
Regarding the main issue I understand the problem is with Intellij, although was wondering if there is a correct way of doing this via gradle that would end up being recognised by IntelliJ.
As I said, do not use the same source dir for two source sets. That will also cause double compilation of the files. You could for example add another source set and then depend on that source set from the two others instead.
a
Sorry,
non-Windoze
?
Will try to use that approach of having a different source set
v
Sorry,
non-Windoze
I guess you use Linux or macOS. On Linux-environment it worked, it just failed on Windows for me. But anyway, I was able to mitigate it, so 🤷‍♂️
👍 1
😂 1
a
In order to define a new sourceSet Gradle will compile it, hence I need its dependencies. I tried by extending the sourceSet configurations with main ones but then I end up with a circular dependency 😓
I guess defining this as a different module would work but I would rather not have the generated files versioned
I managed to do this using two different OAS generator tasks one to generate models only and other to generate the api and then for the sourceSets 1. functionalTest only depends on the model sources 2. main depends on the model+api sources Guess this is the cleanest way I can pull this of 😛