eclipse / xtext

Eclipse Xtext™ is a language development framework

Home Page:http://www.eclipse.org/Xtext

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Couldn't resolve reference to JvmExecutable" in the context of inheritence

smeyer198 opened this issue · comments

We are working on the domain-specific language CrySL and we have implemented a grammar using xtext. Currently, most parts are working as expected. However, there is one problem when it comes to parsing the models. To be more precise, we face the error "Couldn't resolve reference to JvmExecutable '[...]'" in some indefinite cases. We were not able to find the causing problem with debugging. However, we observed some unexpected behavior related to inherited Java classes.

General problem:

Consider $3$ classes $A$, $B$ and $C$ with the hierarchy $C$ and $B$ extend (or implement) $A$. All three models use a same method $M$. If we run our prorgram and parse exactly one class, there is no problem. If we parse class $A$ first and then either $B$ or $C$, there is no problem. However, if we parse first $B$ or $C$, and then $A$, or first $A$, then $B$, and then $C$, we get the error "Couldn't resolve reference to JvmExecutable $M$" only for $C$.

Concrete Example

We consider the interfaces java.security.Key, javax.crypto.SecretKey and java.crypto.PublicKey. The interfaces SecretKey and PublicKey implement the interface Key. According to our grammar, we created the following models:

Key.crysl

SPEC java.security.Key

OBJECTS 
	byte[] keyMaterial;

EVENTS
	ge1: keyMaterial = getEncoded();
[...]

SecretKey.crysl

SPEC javax.crypto.SecretKey

OBJECTS 
	byte[] keyMaterial;
	
EVENTS
	ge1: keyMaterial = getEncoded();
[...]

PublicKey.crysl

SPEC java.security.PublicKey

OBJECTS 
	byte[] keyMaterial;

EVENTS
	ge1: keyMaterial = getEncoded();
[...]

If we parse Key and SecretKey or Key and PublicKey in that order, everything works fine. However, if we parse PublicKey or SecretKey first and then Key, we get the error file: [...].crysl:7: Couldn't resolve reference to JvmExecutable 'getEncoded'. We get the same error, when we parse Keyfirst, then PublicKey (at this point everything is fine) and then SecretKey. Also we get the error, when we parse Key, then SecretKey (at this point everything is fine) and then Key again.

Ideas

We expect that the problem occurs due to the relation ship between superclasses and subclasses. We created models for other Java classes and we were able to observe the same thing: If we parse the superclass (Key) first and one subclass (either SecretKey or PublicKey), then everything is fine. However, if we parse a subclass first, then the error occurs for the superclass (i.e. the reference for the superclass cannot be resolved). Similar, if we hava a superclass ('Key), then a subclass ('PublicKey'), and then a different subclass ('SecretKey), that is unrelated to the first subclass (PublicKey), we get the error for the second subclass (PublicKey).

We have quite some models (see here), which all can be parsed without problems, because they don't share any relations (except Key and SecretKey). Therefore, we strongly assume that the grammar is correct and the problem is somewhere else.

Infos

We have tried different xtext version: 2.10 - 2.32
We parse the models with the XtestResourceSet class:

final Resource resource = resourceSet.getResource(URI.createFileURI(ruleFile.getAbsolutePath()), true);

The whole part can be seen here

The parsing process is independent. That is, we parse one file at a time, i.e. we parse one file, we process the contents, we close the file, and continue with the next file.

I hope these are enough information to explain our problem.

naive question: why not parse all files together / index all files first and then resolve?
would e.g. require to remove
this.resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);

Thank you for your quick answer! Can you explain what you mean with indexing all files first and then resolve?

pseudocode

for (file : files) {
resourceSet.getResource(URI.createUri(...), true)
}
EcoreUtil.resolveAll(resourceSet)
for (resource : resourceSet.getResource()) {
// validate, generate etc
}

Ah, I see. We will try to do it this way. Can you explain, why it would be required to remove the line this.resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);? Otherwise, we will get back to this issue, when we are done

with
this.resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);

resourceSet.getResource(URI.createUri(...), true)
will already resolve and thus (re)introduce the order problem

pseudocode

for (file : files) { resourceSet.getResource(URI.createUri(...), true) } EcoreUtil.resolveAll(resourceSet) for (resource : resourceSet.getResource()) { // validate, generate etc }

We implemented this approach and it worked. We don't face the error anymore. Thank you very much for support. From our side the issue is solved.