We’re defining the TestEnvironment for HeavyTests....
# arrow-meta
i
We’re defining the TestEnvironment for HeavyTests. Does anyone know how we can run code strings through our compiler plugin and pass the generated meta data (e.g.:
.class
) to a directory, which is within the Idea Instance we create during each test. Similar what we do know with the existing compiler plugin test’s. We’re blocked on that.
r
please, it would be great to have a concrete example to have a better understanding about the problem 🙏
i
Let’s say I have this String:
Copy code
package test

import arrow.higherKind
        
@higherkind
class Id<out A>(val value: A)
        
val x: IdOf<Int> = Id(1)
How would I get the package which is generated with all the descriptors we generate? Or in the case of typeclass plugin.
Copy code
object Test {
        fun <F> Kind<F, Int>.addOne(M: Mappable<F> = given): Kind<F, Int> =
          map { it + 1 }
      }
which we transform to
Copy code
object Test {
            fun <F> Kind<F, Int>.addOne(M: Mappable<F> = given): Kind<F, Int> =
              M.run { map { it + 1 } }
          }
I would then like to take that package and move it our Test Environment, which boots a complete ide instance with it’s own sandbox, etc. In other words. The Test Environment needs to be aware of the byte code
@Joachim Ansorg May you help me here in explaining 😅 I am also very fresh in that topic.
We could certainly start with
How to pass Strings to compiler-plugins
and move forward.
s
Strings to compiler plugins
- gradle config?
Or if you mean code snippets, probably you can pass directory with .kt files
j
@Imran/Malic You've explained this well.
The IntelliJ plugin reads the data generated by the compiler plugins to resolve references to the new types, etc. Currently this data is in
.class
files in a folder called
build
, which is Gradle's default. If the references can't be resolved, then red error markers are shown in the editor. Now we'd like add CI tests to the IntelliJ plugin to make sure the reference resolving, etc. is working as it should.
This means that the tests need the data which is generated by the compiler plugins.
These might be possible solutions: 1. Use code snippets defined in a test. This is what @Imran/Malic mentioned above. The test would execute the compiler plugins on that snippet, take the generated data and copy it into the temporary IntelliJ project 2. define a set of
.kt
files on disk and let Gradle generate the data before
gradle test
is run. The IDE tests copies that data into the temporary IntelliJ project and then runs the tests which use it
(1) would be more versatile
(2) might be easier, but I'm not sure if it's good enough
i
That is very understandable 🙂 Thank you @Joachim Ansorg
r
Thanks for the information! I think it could be useful to know how we are evaluating expressions in the current tests: 1. Run the compilation 2. Get the directory where
.class
are located 3. Load those classes 4. Run a function and check the result Could it be useful for you?
j
with my current, limited understanding of the Arrow world I think that steps 1 and 2 would be enough to be able to use this in tests of idea-plugin. If it's possible to generate and access the
.class
data in a test for a code snippet, then IntelliJ could make use of the
.class
data
r
Great @Joachim Ansorg, do you have a test in which I can see this issue? I'm trying to think about an assertion because the directory is not shown to the user right now. It would be very useful for me to see a concrete example of test with the desired source code that cannot be executed right now and maybe we could improve the current DSL together to add this feature for Intellij IDEA plugin tests
i
I am refining the Test Environment for the IDE, which is similar to the compiler part but defines it’s Environment based on the TestFramework from IntelliJ. I am not sure if we can join them together, but I am sure we can depend on the process which happens inside
compile
https://github.com/arrow-kt/arrow-meta/blob/8882df9702cc57bf0e637fa8eeb8aef0a293fc3a/testing-plugin/src/main/kotlin/arrow/meta/plugin/testing/TestingLibraryWrapper.kt#L20 to get the MetaData the example is similar to what is defined here https://github.com/arrow-kt/arrow-meta/blob/623b75e5db4cccda40f5cfd4ead0616d30372be5/compiler-plugin/src/test/kotlin/arrow/meta/plugins/typeclasses/TypeClassesTest.kt#L68 Only that we will process this code within an ide environment. Unfortunately, we can not add the compiler-plugin to the Ide Environment, yet. That’s why we needed help to get the MetaData. What we can do instead is add generated files to the build folder, which exists in the Ide instance.
Currently, I cant show you an example for that, because we’re still defining the Environment part, but we can already add the MetaData.
t
So did I understand correctly that you want to run compiler plugins on code snippets defined as a string in a test, then load the compiled class files? My compile-testing library does this. But afaik you were already using it for tests in arrow-meta? 🤔
i
Yep exactly, we need to know where the Metadata is stored. Can you show me how @tschuchort?
t
@Rachel made a PR for this recently, so I assume that somewhere in the existing tests for arrow-meta you are already doing something like this. You can read the metadata annotations in class and module files via kotlinx-metadata-jvm.
Or if @Joachim Ansorg is correct you can grab the output folder with all the created class and resource files from
KotlinCompilation.Result::outputFolder
and let intellij do its thing.
What my library does is essentially the whole compilation process just like Gradle does. So anything you can do with Gradle output should also be possible with kotlin-compile-testing, in principle. Though that may include doing unneccessary steps of the compilation, depending on your use case.
https://github.com/tschuchortdev/kotlin-compile-testing Currently the testing of compiler plugins is kinda unergonomic and only available in the snapshot build because you have to pass the compiler plugin classpath instead of being able to give instances of
ComponentRegistrar
directly. But a PR for that is practically finished and will be merged and released within the next few days.
r
Thanks @tschuchort! Right, we are already using
outputFolder
though we don't show that directory to the user because we created a specific way to write assertions for a compiler plugin. @Imran/Malic, if compiler-plugin cannot be added to the IDE environment yet, how are code snippets being compiled right now?
@Imran/Malic, @Joachim Ansorg, sorry, I'm trying to figure out the problem but I cannot imagine the situation. It would be very useful for me to see a concrete example of test with the desired source code though it cannot be executed right now, just for knowing your goal. Thanks!
Ups I found it thank you 🙂
t
You can compile a Kotlin source string like in the example in the github readme. The
outputFolder
is a property of the result you get back. The tricky part is passing the compiler plugin you want to test over the
pluginClasspath
. This won't be necessary anymore as soon as PR #27 is merged, then you can just pass a reference to the
ComponentRegistrar
directly
i
Thanks to everyone. I hope I can get back to you @tschuchort when I get into issues 🙂
t
Sure