Home » Modeling » TMF (Xtext) » Parsing in-memory codes with crossrefs between resources in RCP application(I need to parse in-memory pseudocodes split into several chunks using Xtext. The chunks have crossreferences between each other. It works from an RCP application if the content is in files in the work)
Parsing in-memory codes with crossrefs between resources in RCP application [message #1795760] |
Fri, 28 September 2018 06:40 |
Daniel Darvas Messages: 10 Registered: July 2014 |
Junior Member |
|
|
Hello,
TL;DR: I need to parse in-memory pseudocodes split into several chunks using Xtext. The chunks have crossreferences between each other. It works from an RCP application if the content is in files in the workspace, also from a standalone application for in-memory pseudocodes (using 'createInjectorAndDoEMFRegistration'), but now I need to combine the two approaches, i.e. parsing in-memory pseudocodes in RCP app, but the crossreference resolution between resources do not work.
In my project I am parsing pseudocode split into several files using Xtext.
When executed as Eclipse RCP application, the crossreferences between files in the editor work as expected, this is nice.
When executed as a command line application, I follow the method described in the FAQ (https://wiki.eclipse.org/Xtext/FAQ#How_do_I_load_my_model_in_a_standalone_Java_application.C2.A0.3F): I use new MyLanguageStandaloneSetup().createInjectorAndDoEMFRegistration(); to get an injector, then inject a Provider<XtextResourceSet> resourceSetProvider, create an XtextResourceSet, set the OPTION_RESOLVE_ALL to true, then for each chunk of the pseudocode to be parsed I create a new resource in the resource set:
Resource resource = resourceSet.createResource(URI.createURI("dummy:/" + (i++) + ".ext");
InputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
resource.load(inputStream, resourceSet.getLoadOptions());
This works well too, the crossreferences between the resources are resolved correctly.
Now I need to combine these two approaches. In my Eclipse RCP application I need to be able to parse files in the workspace, as well as pseudocodes that exist only in memory, i.e., not backed by any file in the workspace. Of course, the second approach described above is not expected to work out of the box, as it uses createInjectorAndDoEMFRegistration(). The parsing of in-memory pseudocodes work with that, but I get exceptions ("Passed org.eclipse.xtext.builder.clustering.CurrentDescriptions is not based on a resource set") and GUI glitches in the editor, as expected.
If instead of creating a new injector I fetch the injector used by the GUI (via the getInjector method of the Activator in my ui project), the crossreference resolution between different dummy:/ resources do not work, and I get "ERROR org.eclipse.xtext.linking.lazy.LazyLinkingResource - resolution of uriFragment '|30' failed." errors. If I use the activator's injector but with platform:/ URIs pointing to existing files, it seems to work.
What is different between the automatically created injector and the one created by createInjectorAndDoEMFRegistration that prevents me from parsing the dummy:/ resources properly, with crossreference resolution between different resources in the same resource set? May I fix it somehow or am I doing something stupid? Unfortunately the nicer, ExecutableExtensionFactory-based solution (as mentioned in http://koehnlein.blogspot.com/2012/11/xtext-tip-how-do-i-get-guice-injector.html) to get the injector is not an option, but I assume it would not make any difference as I'd get the same injector.
You can find an MWE attached. The key part of it is the following code (in org.xtext.example.mydsl.ui.CustomMydslActivator):
Injector injector = MydslActivator.getInstance().getInjector(ORG_XTEXT_EXAMPLE_MYDSL_MYDSL);
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource res1 = resourceSet.createResource(URI.createURI("dummy:/1.mydsl"));
res1.load(new ByteArrayInputStream("person A; Hello A! Hello B!".getBytes(StandardCharsets.UTF_8)), resourceSet.getLoadOptions());
Resource res2 = resourceSet.createResource(URI.createURI("dummy:/2.mydsl"));
res2.load(new ByteArrayInputStream("person B;".getBytes(StandardCharsets.UTF_8)), resourceSet.getLoadOptions());
EcoreUtil.resolveAll(resourceSet); // just in case
Model model1 = (Model)res1.getContents().get(0);
System.out.println(model1.getGreetings().get(1).getPerson()); // Prints: org.xtext.example.mydsl.myDsl.impl.PersonImpl@51038633 (eProxyURI: dummy:/1.mydsl#|1)
System.out.println(model1.getGreetings().get(1).getPerson().eIsProxy()); // Prints: true. Apparently, the proxy cannot be resolved.
Thanks a lot for any suggestion,
Daniel
|
|
|
Re: Parsing in-memory codes with crossrefs between resources in RCP application [message #1795772 is a reply to message #1795760] |
Fri, 28 September 2018 10:57 |
|
hi,
- i wonder how you managed to create that broken zip file. (some bad mixing of windows paths inside the file nams)
- the usecase you describe is non xtext supports out of the box
- main problem is dummy uris. and containers. and visible containers. and indexing ......
- you might be able to cheat around that
public class CustomMydslActivator extends MydslActivator {
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
// Yes, it really does not belong here, put here only for the purposes of the MWE.
Injector injector = MydslActivator.getInstance().getInjector(ORG_XTEXT_EXAMPLE_MYDSL_MYDSL);
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption("DUMMY", Boolean.TRUE);
// this is a terrible bad idea
// resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource res1 = resourceSet.createResource(URI.createURI("dummy:/1.mydsl"));
res1.load(new ByteArrayInputStream("person A; Hello A! Hello B!".getBytes(StandardCharsets.UTF_8)), resourceSet.getLoadOptions());
System.out.println(res1.getErrors());
Resource res2 = resourceSet.createResource(URI.createURI("dummy:/2.mydsl"));
res2.load(new ByteArrayInputStream("person B;".getBytes(StandardCharsets.UTF_8)), resourceSet.getLoadOptions());
System.out.println(res2.getErrors());
EcoreUtil.resolveAll(resourceSet); // (not) just in case
Model model1 = (Model)res1.getContents().get(0);
System.out.println(model1.getGreetings().get(1).getPerson()); // Prints: org.xtext.example.mydsl.myDsl.impl.PersonImpl@51038633 (eProxyURI: dummy:/1.mydsl#|1)
System.out.println(model1.getGreetings().get(1).getPerson().eIsProxy()); // Prints: true. Apparently the proxy cannot be resolved.
}
}
class MyDslUiModule extends AbstractMyDslUiModule {
def Class<? extends IResourceDescriptionsProvider> bindIResourceDescriptionsProvider() {
CheatingResourceDescriptionsProvider
}
override Class<? extends IAllContainersState.Provider> bindIAllContainersState$Provider() {
return CheatingContainerStateProvider
}
}
public class CheatingResourceDescriptionsProvider extends ResourceDescriptionsProvider {
public static class CheatingResourceSetBasedResourceDescriptions extends ResourceSetBasedResourceDescriptions {
}
@Inject
private Provider<CheatingResourceSetBasedResourceDescriptions> resourceSetBasedResourceDescriptions;
@Override
public IResourceDescriptions getResourceDescriptions(ResourceSet resourceSet) {
if (Boolean.TRUE.equals(resourceSet.getLoadOptions().get("DUMMY"))) {
ResourceSetBasedResourceDescriptions d = resourceSetBasedResourceDescriptions.get();
d.setContext(resourceSet);
return d;
}
return super.getResourceDescriptions(resourceSet);
}
}
public class CheatingContainerStateProvider extends ContainerStateProvider {
@Inject
private ResourceSetBasedAllContainersStateProvider containerStateProvider;
@Override
public IAllContainersState get(IResourceDescriptions context) {
if (context instanceof CheatingResourceSetBasedResourceDescriptions) {
return containerStateProvider.get(context);
}
return super.get(context);
}
}
(no guarantees)
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
|
|
| |
Goto Forum:
Current Time: Fri Apr 26 16:34:25 GMT 2024
Powered by FUDForum. Page generated in 0.03164 seconds
|