2016-11-24 9 views
1

Ich möchte einige der Objekte aus einer anderen Datei in XText zum Geltungsbereich hinzufügen. Um zu zeigen, was ich brauche, ich habe dieses Spielzeug Grammatik:Einfache Importanweisung in XText

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals 
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl" 

Model: 
    (imports += Import)* 
    (classes += ClassDef)*; 

Import: 
    'import' filename += STRING;  

ClassDef: 
    'class' name=ID ('extends' extends=[ClassDef])?; 

Lets sagen, dass ich nur die Klassen zu erweitern, um der Lage sein soll, die vor einer bestimmten Klasse definiert sind, und nur diejenigen, die mit dem gleichen Anfangsbuchstaben beginnen, wie Die Klasse wird definiert.

Eine empfohlene Vorgehensweise ist über scoping. Hier ist der Umfang Anbieter, der es innerhalb einer einzigen Datei tut:

package org.xtext.example.mydsl.scoping 
import .... 

class MyDslScopeProvider extends AbstractMyDslScopeProvider { 
    override getScope(EObject context, EReference reference){ 
     if(reference == MyDslPackage.Literals.CLASS_DEF__EXTENDS){ 
      if(! (context instanceof ClassDef)) {return IScope.NULLSCOPE } 
      val root = (context as ClassDef).getRootContainer 
      val classes = root.getAllContentsOfType(ClassDef) 
      val before = classes.subList(0, classes.indexOf(context)) 
      val fstLetter = (context as ClassDef).name.charAt(0) 
      val haveSame1stLetter = before.filter[name.charAt(0) == fstLetter]   
      return Scopes::scopeFor(haveSame1stLetter) 
     } 
    } 
} 

ich die Klassendeklarationen in der Lage sein wollen, zugreifen aus importierten Dateien wie folgt aus:

// --- c --- 
class Xlib 
class Xextend extends Xlib 

// --- main.mydsl --- 
import "lib.mydsl" 
class A 
class Xmain extends Xlib 

Ich habe einige widersprüchliche Vorschläge gefunden über die Verwendung von importURI Sache, aber es scheint nicht für mich zu arbeiten und scheint, und veraltete Art der Dinge jetzt zu tun.

Die Dokumentation erwähnt, dass für Querressourcenreferenzen ich wahrscheinlich brauchen:

  • eine Instanz IGlobalScopeProvider schaffen,
  • Export Elemente als Teil IResourceDescription
  • convert zwischen einem QualifiedName und seiner String-Darstellung
  • implementieren und binden meine eigenen IDefaultResourceDescriptionStrategy
  • get IContainer von IContainer.Manager
  • erhalten IResourceDescriptions (die Pluralform beachten) von IContainer

... und noch vielen anderen Dingen. Leider fügen sie sich nicht zu einem zusammenhängenden Bild dessen zusammen, was ich tun muss, um ein gewünschtes Verhalten zu erreichen.


Edit: Nach Svens Vorschlag, den ich mit der Lösung kommen haben. Wenn jemand interessiert ist - ich habe den Code in this gist veröffentlicht.

Antwort

1

Es gibt anständige Standardimplementierungen für alle Dienste geben Sie erwähnt haben, so dass Sie sie nicht implementieren müssen, es sei denn Sie möchten ändern, wie sie funktionieren.

Es wird zwar davon abgeraten, den importUri-Mechanismus zu verwenden, aber stattdessen sollten Sie eine namensbasierte Verknüpfung verwenden, die zuverlässiger ist.

Xtext verwaltet automatisch einen Index für Sie, der global sichtbare qualifizierte Namen enthält.Es gibt zwei Seiten des Index:

1. auf den Index Beitrag

Während der ResourceDescriptionManager Indizierung wird für benannte Elemente gefragt. Die Standardimplementierung fügt alle Elemente mit einem Eigenschaftsnamen hinzu. Wenn Sie dieses Verhalten ändern möchten, können Sie die Klasse DefaultResourceDescriptionStrategy untergliedern und createEObjectDesciptions überschreiben. Zum Beispiel Sie das Stammelement des Modells exportieren könnte den einfachen Namen der Ressource verwendet wird, ermöglichen

Import : 
    'import' referencedModel+=[Model|STRING] 
; 

Dies würde nur erlauben, Dateien zu importieren, wenn Sie Dateien aus verschiedenen Ordnern unterstützen möchten importieren, würde ich empfehlen, Namespaces zu verwenden.

namespace foo; 
type Bar {} 

andere Datei

import foo.Bar 
type Foo extends Bar 

2. Verwenden des Index

Der Umfang Provider automatisch Delegierten der GlobalScopeProvider, die die Beschreibungen aus dem Index bieten. Wenn Sie also sicherstellen, dass die Elemente korrekt indexiert sind (siehe 1.), werden sie automatisch im Scope-Provider angezeigt.

0

Hallo, ich kann dir nicht wirklich folgen. Entweder Sie verwenden einfach Import-Uri, obwohl es nicht empfohlen wird https://www.eclipse.org/forums/index.php?t=msg&th=1078818&goto=1736351&#msg_1736351 oder Sie verwenden namespacebasiertes Scoping (wissen nicht, ob Sie relative Importe oder ausgefallene Uri-Schemata unterstützen wollen), indem Sie den Namenprovider (geben Sie dem Element den Namen .elementname) und importimedamespaceawareocalscopeprovider an (drehen Import zu einem Import xxx xxx. *)

können Sie bitte weitere Hinweise auf Ihre Anforderungen

+0

Hallo, ich habe versucht, ein Beispiel zu geben, was ich erreichen möchte – Kostya

+0

Haben Sie mehrere Ordner/Pakete/Projekte und relative/absolute Importe oder nur Dateien neben dem aktuellen –

+0

Derzeit sind alle Dateien in der gleichen Mappe. Aber ich möchte Ordner als eine Möglichkeit für die Zukunft haben. – Kostya