Using results from language interpreter in JavaValidator [message #697371] |
Sat, 16 July 2011 12:34 |
Jonathan Blakes Messages: 4 Registered: February 2011 |
Junior Member |
|
|
[This is from a question I incorrectly asked on the Xtext 2.0 documentation disqus.]
I am creating an interpreted language. After editing and saving a language file my IXtextBuilderParticipant interprets the file to provide information to several Eclipse Views about the results. I would also like to somehow be able to use these results in my JavaValidator so that it can provide feedback in the XtextEditor about which operations caused problems.
My inital attempt used a private variable in the JavaValidator in which I store the results of the interpreter to which I pass the root EObject of my grammar:
public MyDSLJavaValidator extends AbstractMyDSLJavaValidator {
private Result result;
@Check
public void checkRoot(Root root) {
result = new Interpreter().interpret(root);
}
@Check
public void checkSomething(Something something) {
// regular checking
if (result != null) {
// result aware checking
}
}
But @szarnekow responded with:
Quote:You should not store the result in the validator as the instance will be shared for different resources. Attach the result to the resource instead (probably as an EAdapter). I'd recommend to use the IResourceScopeCache.
Which sounds like exactly what I wanted (I saw that the validator was meant to be a singleton from the RuntimeModule but didn't know how to get around this).
Unfortunately I don't see how I can implement this suggestion, can anyone here offer me an example that does so? (Googling was not successful)
I know that I can get an IResourceScopeCache by injection but how do I:
a) set a value in the cache so I can retrieve it?
b) attach the result to the resource using an EAdapter? (which seems to be used for notifications not storage)
Other questions I have are:
c) Does the check method for the Root EObject get called before the others? And if not is there a way to have it do so to ensure that the result is available to all the other check methods (providing it can be correctly interpreted)?
d) can I have 2 JavaValidators, one with the results and one without? Would this be inefficient?
Thanks,
Jon
Edit: the thread title "Hook after edits" also refers to the same ideas but without providing a concrete answer.
[Updated on: Sat, 16 July 2011 14:43] Report message to a moderator
|
|
|
|
|
Re: Using results from language interpreter in JavaValidator [message #697907 is a reply to message #697862] |
Mon, 18 July 2011 10:28 |
Sebastian Zarnekow Messages: 3118 Registered: July 2009 |
Senior Member |
|
|
Hi Jon,
the resource scope cache uses the adapter approach internally. Sorry for
any confusion that I caused with the reference to EAdapter.
Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
On 18.07.11 10:26, forums-noreply@eclipse.org wrote:
> Hello Sebastian.
>
> Thanks for answering my questions.
> I can see how to add a second validator now (d) - I thought it would
> override the other one but the methods are named after the class not the
> interface so that is OK.
>
> (a + b) I had cobbled together the following, but your answer is much
> neater and I will try that.
>
>
> public class MyDslValidator extends AbstractDNAplJavaValidator {
>
> @Inject
> private IResourceScopeCache resourceScopeCache;
>
> /**
> * Used by getRegisteredAdapter to obtain the ResourceAdapter. */
> class Type {}
>
> /* * Sebastian Zarnekow wrote, in response to Jonathan Blakes:
> * You should not store the result in the validator as the instance will
> * be shared for different resources. Attach the result to the resource *
> instead (probably as an EAdapter). I'd recommend to use the *
> IResourceScopeCache. */
> /**
> * Used to add functionality to the current resource (like the result of the
> * interpretation) and cache it in such a way that it is discard as soon as
> * the model changes.
> */
> class ResourceAdapter extends AdapterImpl {
> private Root root;
> public ResourceAdapter(Root root) {
> this.root = root;
> }
> public boolean isAdapterForType(Object type) {
> if (type == Type.class) return true;
> return false;
> }
> public Result getResult() {
> return resourceScopeCache.get("Root", root.eResource(), new
> Provider<Result>() {
> public Result get() {
> Interpreter interpreter = new Interpreter(root);
> return interpreter.getResult();
> }
> );
> }
>
> /**
> * Add a ResourceAdapter to the resource being validated.
> * @param root The root EObject of the grammar.
> */
> @Check
> public void checkRoot(final Root root) {
> // Add a ResourceAdapter to the resource being validated
> EList<Adapter> adapters = root.eResource().eAdapters();
> if (Iterables.isEmpty((Iterables.filter(adapters,
> ResourceAdapter.class)))) {
> adapters.add(new ResourceAdapter(root));
> }
> }
>
> /**
> * Accessor that goes via a ResourceAdapter to get the cached Result.
> */
> private Result getResult() {
> return ((ResourceAdapter)
> EcoreUtil.getRegisteredAdapter(getCurrentObject().eResource(),
> Type.class)).getResult();
> }
>
> @Check
> public void checkSomething(Something something) {
> Result = getResult();
> ...
>
>
> How come you didn't use an eAdapter as you suggested before? I this
> there anything wrong with the approach that I used?
>
> Best regards,
>
> Jon
|
|
|
Powered by
FUDForum. Page generated in 0.04355 seconds