Guice error in tests after adding Formatter [SOLVED] [message #1838986] |
Wed, 10 March 2021 23:11 |
Volker Wegert Messages: 182 Registered: July 2009 |
Senior Member |
|
|
"It's always to do things properly, and now I'm properly stuck."
I've been working on a set of two stacked grammars (renamed to MyBaseDsl and MyExtendedDsl below). I've added some validation logic and associated unit tests, and it all worked. I then proceeded to implement some tooling to import stuff from somewhere else and generate the DSL representation of what I imported, and that worked as well (*). I wasn't happy with the generated output, so I adapted the MWE2 workflow to generate a formatter stub and implemented some formatting rules. They work both in the editor and during the import process. Now I wanted to add some unit tests both for the formatter and the import logic - and discovered I can't execute any of the unit tests successfully any more. I'm basically getting the same Guice error for all of the existing tests:
org.junit.jupiter.engine.execution.JupiterEngineExecutionContext close
SEVERE: Caught exception while closing extension context: org.junit.jupiter.engine.descriptor.ClassExtensionContext@6f6a7463
com.google.inject.CreationException: Guice creation errors:
1) No implementation for mydsl.formatting2.MyBaseDslFormatter was bound.
at org.eclipse.xtext.service.MethodBasedModule.configure(MethodBasedModule.java:58)
1 error
at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:435)
at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:154)
at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
at com.google.inject.Guice.createInjector(Guice.java:95)
at com.google.inject.Guice.createInjector(Guice.java:72)
at com.google.inject.Guice.createInjector(Guice.java:62)
at mydsl.MyBaseDslStandaloneSetupGenerated.createInjector(MyBaseDslStandaloneSetupGenerated.java:29)
at mydsl.MyBaseDslStandaloneSetupGenerated.createInjectorAndDoEMFRegistration(MyBaseDslStandaloneSetupGenerated.java:23)
at mydsl.MyBaseDslStandaloneSetup.doSetup(MyBaseDslStandaloneSetup.java:13)
at mydsl.MyExtendedDslStandaloneSetupGenerated.createInjectorAndDoEMFRegistration(MyExtendedDslStandaloneSetupGenerated.java:21)
at mydsl.tests.MyExtendedDslInjectorProvider.internalCreateInjector(MyExtendedDslInjectorProvider.java:40)
at mydsl.tests.MyExtendedDslInjectorProvider.getInjector(MyExtendedDslInjectorProvider.java:28)
at mydsl.tests.MyExtendedDslInjectorProvider.setupRegistry(MyExtendedDslInjectorProvider.java:65)
at org.eclipse.xtext.testing.extensions.InjectionExtension$RegistryReset.setup(InjectionExtension.java:71)
at org.eclipse.xtext.testing.extensions.InjectionExtension$RegistryReset.<init>(InjectionExtension.java:65)
at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$getOrComputeIfAbsent$4(ExtensionValuesStore.java:86)
at org.junit.jupiter.engine.execution.ExtensionValuesStore$MemoizingSupplier.get(ExtensionValuesStore.java:205)
at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.evaluate(ExtensionValuesStore.java:182)
at org.junit.jupiter.engine.execution.ExtensionValuesStore$StoredValue.access$100(ExtensionValuesStore.java:171)
at org.junit.jupiter.engine.execution.ExtensionValuesStore.lambda$closeAllStoredCloseableValues$1(ExtensionValuesStore.java:65)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
at java.base/java.util.concurrent.ConcurrentHashMap$ValueSpliterator.forEachRemaining(ConcurrentHashMap.java:3605)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.junit.jupiter.engine.execution.ExtensionValuesStore.closeAllStoredCloseableValues(ExtensionValuesStore.java:68)
at org.junit.jupiter.engine.descriptor.AbstractExtensionContext.close(AbstractExtensionContext.java:74)
at org.junit.jupiter.engine.execution.JupiterEngineExecutionContext.close(JupiterEngineExecutionContext.java:53)
at org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.cleanUp(JupiterTestDescriptor.java:222)
at org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.cleanUp(JupiterTestDescriptor.java:57)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$cleanUp$9(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.cleanUp(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:87)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:84)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
I'm seeing these errors both when running the unit tests within Eclipse as well as during the Maven build.
I've tried to reproduce these issues with a fresh set of plug-ins, but so far I haven't succeeded. I've tried to debug the issue, but all I've been able to establish is that the RuntimeModule of the "base DSL" is actually called and that it does provide a reference to the corresponding formatter implementation. I've already wiped and re-generated the manifest files and the generated test injection providers to ensure that I didn't introduce some dependency/visibility problems by accident, but no luck. How would you suggest to narrow down this issue?
I somehow need to repair these plug-ins - starting over is not an option. Unfortuately, I have no idea what is causing the issue and how to narrow down possible causes.
Thanks
Volker
Xtext 2.25.0.v20210301-1429
(*) I may have forgotten to actually check whether the unit tests where executable at that point - I don't really remember.
[Updated on: Thu, 11 March 2021 10:59] Report message to a moderator
|
|
|
|
Re: Guice error in tests after adding Formatter [message #1838995 is a reply to message #1838994] |
Thu, 11 March 2021 07:46 |
Volker Wegert Messages: 182 Registered: July 2009 |
Senior Member |
|
|
Thanks for looking into this!
Christian Dietrich wrote on Thu, 11 March 2021 01:56how is the inheritance hierarchy of your modules
"core" plug-in:
org.eclipse.xtext.service.AbstractGenericModule
org.eclipse.xtext.service.DefaultRuntimeModule
mydsl.AbstractMyBaseDslRuntimeModule
mydsl.MyBaseDslRuntimeModule
mydsl.AbstractMyExtendedDslRuntimeModule
mydsl.MyExtendedDslRuntimeModule
IDE plug-in:
org.eclipse.xtext.service.AbstractGenericModule
org.eclipse.xtext.ide.DefaultIdeModule
mydsl.ide.AbstractMyBaseDslIdeModule
mydsl.ide.MyBaseDslIdeModule
mydsl.ide.AbstractMyExtendedDslIdeModule
mydsl.ide.MyExtendedDslIdeModule
UI plug-in:
org.eclipse.xtext.service.AbstractGenericModule
org.eclipse.xtext.ui.DefaultUiModule
mydsl.ui.AbstractMyBaseDslUiModule
mydsl.ui.MyBaseDslUiModule
mydsl.ui.AbstractMyExtendedDslUiModule
mydsl.ui.MyExtendedDslUiModule
Christian Dietrich wrote on Thu, 11 March 2021 01:56and where are bindings for the formatter and where not
mydsl.AbstractMyBaseDslRuntimeModule --> mydsl.formatting2.MyBaseDslFormatter
mydsl.AbstractMyExtendedDslRuntimeModule --> mydsl.formatting2.MyExtendedDslFormatter
mydsl.ide.AbstractMyBaseDslIdeModule --> no binding
mydsl.ide.AbstractMyExtendedDslIdeModule --> no binding
mydsl.ui.AbstractMyBaseDslUiModule --> no binding
mydsl.ui.AbstractMyExtendedDslUiModule --> no binding
No additional bindings are present in any of the non-abstract pre-generated module implementations - they are completely unchanged.
FWIW, the formatter inheritance hierarchy looks like this:
org.eclipse.xtext.formatting2.AbstractFormatter2
mydsl.formatting2.MyBaseDslFormatter
mydsl.formatting2.MyExtendedDslFormatter
To me, it looks exactly like in the "clean" example where I can not reproduce the issue...
EDIT: I had an extraneous package level (.ma.) in there - removed for consistency with initial posting.
[Updated on: Thu, 11 March 2021 08:52] Report message to a moderator
|
|
|
|
|
|
Re: Guice error in tests after adding Formatter [message #1839012 is a reply to message #1839005] |
Thu, 11 March 2021 10:58 |
Volker Wegert Messages: 182 Registered: July 2009 |
Senior Member |
|
|
Christian Dietrich wrote on Thu, 11 March 2021 04:19it looks like the runtime modules dont inherit from each other
You're right, they don't - neither in my broken set of plug-ins nor in the newly created example where the tests work...
I'm trying to wrap my head around this - let me try to sum up what I understood so far:
The generated extended injection provider uses an anonymous subclass of the extended StandaloneSetup. For createInjectorAndDoEMFRegistration(), the extended StandaloneSetup first calls the base StandaloneSetup. The base StandaloneSetup uses an injector configured with the base RuntimeModule, while the extended StandaloneSetup should - in theory - use the extended runtime module. If I understand the intent of this approach correctly, that should make it unnecessary for the modules to have an inheritance relationship. The injector configured using the extended RuntimeModule should simply be registered after the one using the base RuntimeModule.
Problem is - that's not happening, and now I know why. A classic case of PEBKAC. Since my base language only serves as a type and rule library and only has a very basic root element (literally BaseDummy: 'Foo' bar=STRING;), the BaseFormatter is generated empty. That of course makes it invalid because it is neither abstract nor does it provide an implemention of format(Object, IFormattableDocument). Yesterday-me probably saw this error, thought "naw, this formatter won't ever be used" and hit the quick fix to make the class abstract. Needless to say, this was one of my less brilliant ideas... In my newly created plug-ins I simply left the default "Hello Xtext!" grammar in place, and that has enough meat not to generate an empty formatter.
(It didn't help that the message "No implementation for %s was bound." is used for multiple error conditions. A simple "You're trying to instantiate an abstract class, dummy" would have saved me a day... But that may just be my Guice frustration speaking...)
|
|
|
Powered by
FUDForum. Page generated in 0.04179 seconds