Pante/elementary

[FEATURE REQUEST] First-class module support in JUnit extensions

Closed this issue · 7 comments

CC007 commented

Is your feature request related to a problem? Please describe.
Right now it's a pain to configure the elementary compiler to run the test on a full module.

Describe the solution you'd like
Annotations specific to loading modules, like @Module, @ModulePath, @ModuleSourcePath (and @ProcessorPath would also be useful)

Describe alternatives you've considered
Using the @Options annotation, but this leads to bugs for now.

Additional context
The bug I'm referring to has to do with the MemoryFileManager (line 59):

static URI of(Location location, String type, Kind kind) {
    return URI.create("mem:///" + location.getName() + "/" + type.replace('.', '/') + kind.extension);
}

This method throws an error if the location.getName() contains illegal URI characters (which it does in the case of modules, namely [ and ]).

Pante commented

I think this issue can be split into two separate issues, this for tracking improvements to module support & another for the bug with MemoryFileManager.

Pante commented

Looking at it, I think a decent short-term fix will be to patch the @Options annotation. Personally, I haven't really used Java's modules. Would you mind elaborating on the following? It'll greatly help with fleshing out the feature!

  • What difficulty do you currently face with loading modules?
  • How do you currently load modules?
  • How would an annotation like @Module work?
CC007 commented

The idea would be for those annotations to mimic the --module, --module-path, --module-source-path and --processor-path arguments to the compiler, while also defaulting the base of path arguments to the src/test/resources folder or .m2/repository, rather than the module root folder (depending on which argument we are talking about), so:

@ExtendsWith(JavacExtension.class)
@Options("--module test -d .\\unimportant\\because\\in-memory\\but\\mandatory --module-source-path .\\src\\test\\resources\\modules --module-path my\\path\\to\\.m2\\repository\\my\\path\\to\\annotations\\1.0-SNAPSHOT\\annotations-1.0-SNAPSHOT.jar --processor-path my\\path\\to\\.m2\\repository\\my\\path\\to\\annotations\\1.0-SNAPSHOT\\annotations-1.0-SNAPSHOT.jar")
@Processors(MyAnnotationProcessor.class)
class MyAnnotationProcessorTest { ... }

Would become:

@ExtendsWith(JavacExtension.class)
@Module(name = "test", sourcePath = ".\\modules") // sourcePath is optional and points to src/test/resources by default
@ModulePath("my\\path\\to\\annotations\\1.0-SNAPSHOT\\annotations-1.0-SNAPSHOT.jar")
@ProcessorPath("my\\path\\to\\annotations\\1.0-SNAPSHOT\\annotations-1.0-SNAPSHOT.jar")
@Processors(MyAnnotationProcessor.class)
class MyAnnotationProcessorTest { ... }
CC007 commented

Alternatively, for the module path and processor path, you could maybe specify them by their groupId, artifactId and version:

@ExtendsWith(JavacExtension.class)
@Module(name = "test", sourcePath = ".\\modules")
@ModulePath("my.path.to:annotations:1.0-SNAPSHOT")
@ProcessorPath("my.path.to:annotations:1.0-SNAPSHOT")
@Processors(MyAnnotationProcessor.class)
class MyAnnotationProcessorTest { ... }
CC007 commented

I'm not fully happy with how the module path and processor path are specified in the current implementation in my Pull Request. Right now it feels a bit fragile due to its reliance on OS specific environment variables and the assumption that the .m2 folder is located in the user's home folder.

@Pante Do you have any better ideas? Or will these issues also be resolved by your PR?

Pante commented

My PR covers the use-case where the project that's under test is a module and relies on other modules. It does so by checking if the annotated test class is part of a module and adds all its dependencies to the classpath with zero configuration. I'm not sure if my PR covers 100% of what your PR does.

Pante commented

I’m going to close this issue for now since I believe that adding low-level support for this directly in Compiler addresses most of the use-cases. The only exception being compiling module-info files. Even then, I could not find a way to support it.

Please feel free to reopen/comment on this issue if there’s any use-cases that #168 doesn’t address!