0
votes

Due to the discussion a working example was created and added to https://github.com/Johanvdberg/mcrl2.xtext, see the test.multiname.* and test.reflang.* eclipse projects.

Multiname is defined by the grammar

grammar test.multiname.dsl.MultiNameDsl with org.eclipse.xtext.common.Terminals

generate multiNameDsl "http://www.multiname.test/dsl/MultiNameDsl"

Model:
    modules+=Module+;

Module:
    'begin module' name=ID
    vars+=Vars*
    funcs+=Funcs*
    'end_module';

VarName:
    name=ID;

FuncName:
    name=ID;

Name:
    VarName | FuncName;

Funcs:
    'func' left=FuncName (bracket?='(' ')')? '=' right=[Name] ';';

Vars:
    'var' VarName ';';

Files with this grammar will look like

begin module test1
var t1v1;
var t1v2;
end_module

or

begin module test2
var t2v1;
var t2v2;
end_module

The grammar of the language that will reference the above language, RefLang

grammar test.reflang.dsl.RefDsl with org.eclipse.xtext.common.Terminals

generate refDsl "http://www.reflang.test/dsl/RefDsl"
import "http://www.multiname.test/dsl/MultiNameDsl" as multi

Model:
    ref_from=Import
    refs=DataRef;

Import:
    'import' imports=[multi::Module];

DataRef:
    'ref_vars' data+=[multi::VarName|FQN] (',' data+=[multi::VarName|FQN])*;

FQN:
    ID ("." ID)*;

and a file with the above grammar looks like:

import test2
ref_vars test2.t2v1, test1.t1v1

The desire behavior is that ref_vars can only be from the modules specified with import, in the above file that is test2 and var test1.t1v1 is not correct.

The scope provider for RefLang is:

override getScope(EObject context, EReference reference) {
    if (context instanceof DataRef) {
        if (reference == RefDslPackage.Literals.DATA_REF__DATA) {
            val rootElement = EcoreUtil2.getRootContainer(context)
            return super.getScope(context, reference);
        }
    }
    return super.getScope(context, reference);
}

But I cannot access the model element test2 defined in the multiname language and reference from the RefLang by using rootElement. All the attributes rootElement.ref_from.imports.{vars, funcs} are null.

Note the questioned changed a bit and thew working, these changes was made based on comment on the old question.

Old question I have two grammars A and B where grammar B reference elements from the grammar A:

Model:
    import_model=Import
    flows=FlowData;

Import :
    'import' importURI=STRING ';';


FlowData:
    'flows' data+=[A::Flow|FQN] (',' data+=[A::Flow|FQN])* ';';

FQN: ID ("." ID)*;

importURI define the file that use grammar A and contain the definition of Flow begin referenced.

Using context menu as in https://christiandietrich.wordpress.com/2011/10/15/xtext-calling-the-generator-from-a-context-menu/ the model of grammar B can be accessed. How can the model of the file specified by importURI be accesses in the same handler?

Update 1

Addition to the MWE2 file related to the import:

fragment = scoping.ImportNamespacesScopingFragment2 auto-inject {}
referencedResource="platform:/resource/.../A.genmodel"

in the grammar file

import "http://www..../A" as A

dependency in grammar B's dsl project plugin.xml to the dsl project of grammar A was added. Dependency of the ide and ui projects to ide and ui was also added, respectively.

The complete model of grammar A need to be accessed. Grammar A define a system and grammar B define where data is in the system and the union of the two model needs to be converted.

More than one configuration (model) may exist for each model of grammar A.

1
It actually can't (directly) imports are imports only and not a reference. Is it sufficient to simply follow the flow references or do you need to follow unused imports as well ? Did you setup scoping correct to work with the old import Uri syntax? Please elaborate - Christian Dietrich
please see update 1 - Johan
Import Uri is not used if you use imported names based scoping . And still the question: is this about import Uri (data references not working in editor) or is this about following the data references or about loading the unused importUri file somewhere e.g. Inside the handler - Christian Dietrich
load the importUri in a handler of grammar B. The editor part works. - Johan
I doubt that. It will work if you import another non existing file as well. - Christian Dietrich

1 Answers

1
votes

you seem to be a guy that really hats assignments in grammars

Funcs:
'func' left=FuncName (bracket?='(' ')')? '=' right=[Name] ';';

Vars:
'var' varName=VarName ';';

here is the scopeprovider that works fine for me

class MyDslScopeProvider extends AbstractMyDslScopeProvider {

    override getScope(EObject context, EReference reference) {
        if (context instanceof DataRef) {
            if (reference == MyDslPackage.Literals.DATA_REF__DATA) {
                val rootElement = EcoreUtil2.getContainerOfType(context, Model)
                val names = <Name>newArrayList
                val importedModule = rootElement?.ref_from?.imports
                if (importedModule !== null) {
                    for (v : importedModule.vars.map[varName]) {
                        names += v
                    }
                    for (f : importedModule.funcs.map[left]) {
                        names += f
                    }
                }
                // this is the unqualified variant
                // return Scopes.scopeFor(names)
                // this is the unqualified variant
                return Scopes.scopeFor(names, [QualifiedName.create(importedModule.name, it.name)], IScope.NULLSCOPE)
            }
        }
        return super.getScope(context, reference);
    }

}

furthermore the usage of spaces in keywords is code smell and might lead to unexpected behaviour

and you should consider simple sames only for the references (in scoping - see my comment - and in grammar ref=[XXX|ID]