Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 356713

Summary: Allow to synchronize with validator life cycle
Product: [Modeling] TMF Reporter: Aaron Digulla <digulla>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: enhancement    
Priority: P3 CC: henrik.lindberg, knut.wannheden, sebastian.zarnekow
Version: 2.0.0   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Aaron Digulla CLA 2011-09-05 05:17:28 EDT
Scenario: To validate a model in the editor, I need to parse a different resource. This is somewhat expensive.

What I would like to do is to parse this once when validation starts and flush the cache afterwards.

The most simple solution would be to make org.eclipse.xtext.validation.AbstractDeclarativeValidator.internalValidate() non-final. That would allow me to override it, prime the cache, call super, flush the cache.

Alternatively, add hooks to the validator which tell me when a new validation of a resource starts and when it's finished.
Comment 1 Sebastian Zarnekow CLA 2011-09-06 14:40:59 EDT
You are free to implement your own subtype of DefaultResourceValidator which is used to validate a complete resource. Please note that it's usually a bad idea to load a resource which is not put into the resource set. The resource set serves as a very nice cache for parsed resourcess ;-)

Also have a look at the IResourceScopeCache.

I'll close this one as I don't see a reason to add hooks to the validator itself which is called by other EMF components and thereby has no such thing as a dedicated 'start' and 'stop' validation. Feel free to reopen if I missed something.
Comment 2 Aaron Digulla CLA 2011-09-07 07:47:50 EDT
In my case, the "resource" is a Groovy script, so loading it into a ResourceSet isn't an option as far as I understand EMF. Parsing and compiling that script is expensive and I need to do it again if the Groovy script changes. So I need to put the parse result into a cache.

Right now, a DSL might have an optional Groovy script.

I need to populate/update the cache when the validation is run for each DSL file.

My current solution is to get the URL of the Groovy script and then get the timestamp in every validation method and update the cache.

This is some overhead since I only need to do this check once when validation starts because the Groovy script won't change while I run the validation on a single resource.

So the best solution for me would be to override internalValidate() because that runs all checks. I could populate my cache once before I call super.
Comment 3 Knut Wannheden CLA 2011-09-07 08:19:23 EDT
You might also be able to use getContext() which returns a modifiable Map<Object, Object>. To that you can add anything you like. It will then be available to all checks as part of the current validation run. So you could add a call to every check which needs this cached data: getFoo()

public Foo getFoo() {
  Foo foo = (Foo) getContext().get("FOO");
  if (foo == null)
    foo = someExpensiveCalculation();
  return foo;
}
Comment 4 Knut Wannheden CLA 2011-09-07 08:20:32 EDT
Oops. That should of course be:

public Foo getFoo() {
  Foo foo = (Foo) getContext().get("FOO");
  if (foo == null) {
    foo = someExpensiveCalculation();
    getContext().put("FOO", foo);
  }
  return foo;
}
Comment 5 Henrik Lindberg CLA 2011-09-07 13:28:08 EDT
(In reply to comment #2)
> In my case, the "resource" is a Groovy script, so loading it into a ResourceSet
> isn't an option as far as I understand EMF. Parsing and compiling that script
> is expensive and I need to do it again if the Groovy script changes. So I need
> to put the parse result into a cache.

You can sort of do what Xtext does - create a model with a single class "GroovyScript", that has a String feature called sourceText. 

When compiling the script, associate the result with the model.
From there, you can start using more services, like export IEObjectDescription instances based on what you parsed in the grovvy script.etc. 

I do something similar for Ruby code, but in my case, I build a more elaborate model out of what parsed, and I then export IEObjectDescriptions for that model.