"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
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 Key
first, 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.