Advanced reference resolution in xtext, how do I customize the scoping/index correctly?

97 views Asked by At

I try to show a minimal working example that describes my problem:

Grammar

This is the xtext grammar I created for this example. (The real grammar of course is much more complex and also involves an advanced expression-language)

grammar org.example.dsl.DSL with org.eclipse.xtext.common.Terminals

generate dsl "http://www.example.org/dsl/DSL"

Model:
  elements+=Declaration*
;

QualifiedName:
  ID ('.' ID)*
;

Declaration:
  SimpleTypeDeclaration |
  SectionDeclaration |
  FieldDeclaration
;

SimpleTypeDeclaration:
  "type" name=ID "=" primitive=IntegerType
;

IntegerType
  {IntegerType} "int"
;

SectionDeclaration:
  "section" name=ID "{"
    elements+=FieldDeclaration*
  "}"
;

TypeDeclaration:
  SimpleTypeDeclaration |
  SectionDeclaration
;

FieldDeclaration:
  name=ID ":" type=[TypeDeclaration|QualifiedName] ("=" value=ValueExpression)?
;

ValueExpression:
  FieldReference |
  SimpleValue
;

FieldReference:
  ref=[FieldDeclaration|QualifiedName]
;

SimpleValue:
  {SimpleValue} "sentinel"
;

Example-Code in Example-Language

This is some example code in the language I described above.

type Foo = int

section A {
  foo: Foo = sentinel
}

section B {
  a: A

  // here I want to assign the value of a subfield of `a`
  // to fubar
  fubar: Foo = a.foo // crucial point
} 

Global Index of the Example-Code snippet

The default Indexer of the Example-Code snippet would generate the following global-scope index for referencing:

[Foo, A, A.foo, B, B.a, B.fubar]

So with the correct scope I would be able to reference all those objects by these identifiers in my code on reference-resolution.

But the crucial point in the code snippet will not be resolved, because B.a.foo respectively a.foo will not be in the index.

What I thought of and tried so far (incomplete solutions)

  1. I thought of customizing the Index, so that it would additionally put B.a.foo into the index.

    • but that would pollute the index with potentially so many unnecessary resource URIs that I never would want to be referencing from the global scope.
    • (e.g. I just want to be able to reference a fields subfields from within the section I'm referencing it from)
  2. Create a new Rule in the grammar called Selection => make qualified selection of fields explicit by providing a custom ScopeProvider. But there are some Problems I encountered:

    • If I still provide the possibility to reference everything via QualifiedNames the grammar and resolution always think it is a typereference as before and will not ask my custom scopeprovider to provide the reference for the Selection rule, which overloads the dot-operator (.)
    • If I remove the referencing mechanism [TypeDeclaration|QualifiedName] replacing it with a [TypeDeclaration|ID] I would have to customize the scoping for every base type and subreference and would not leverage the powerful default qualified-name-resolution of xtext.

My Question now

Does anybody know about a standard or best solution to the problem I descibed?

0

There are 0 answers