0

I am writing on a Xtext grammar that uses XExpressions and also operates on Eclasses. Now I want to also be able to access Eclasses from the XExpression, for example I write an expression like this:

Eclass1.attribute1 = Eclass2.attribute1

I would like to know, how I can use the Eclass from within the XExpression?

Grammar

grammar org.xtext.example.mydsl.Mydsl with 
org.eclipse.xtext.xbase.Xbase

import "http://www.eclipse.org/emf/2002/Ecore" as ecore

generate mydsl "http://www.xtext.org/example/mydsl/Mydsl"

Model:
(operations += Operation)*;

terminal ATTR : ID ('.' ID)+;

Operation:
'operation' left=[ecore::EClass|ATTR] 'and' right=
 [ecore::EClass|ATTR] 'defined' 'as' condition=XExpression
;

Inferrer/ Infer method

def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
      acceptor.accept(element.toClass("example.mydsl")) [
        for (operation : element.operations) {
            left = operation.left
            right = operation.right
            if (left.eIsProxy()) {
                left = EcoreUtil.resolve(left, operation) as EClass
            }   
            if (right.eIsProxy()) {
                right = EcoreUtil.resolve(right, operation) as EClass
            }
            //field for right class left out, but works the same
            members += left.toField(left.name,typeRef(left.EPackage.name+"."+left.name))    
            members += operation.toMethod("conditionExpr", 
            typeRef(Void.TYPE)) [
                body = operation.condition
            ]       
        }
    ]

}

RuntimeModule

    class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {

       def Class<? extends ImplicitlyImportedFeatures> bindImplicitlyImportedTypes() {
       return MyImportFeature
}

}

MyImportFeature

class MyImportFeature extends ImplicitlyImportedFeatures{
override protected getStaticImportClasses() {
    (super.getStaticImportClasses() + #[PackageFromWorkSpace]).toList
}

}

1 Answers1

0

I Am not sure if i get your question. Ususally EMF generates constants for EAttributes so if you want to access the attributes themselfs so you could either do MyDslPackage.Literals.GREETING__NAME or MyDslPackage.eINSTANCE.getGreeting_Name()

can you give some more hints on what you actually want to do

update: here is a snippet on how to get a java class from a reference to an eclass

Thingy:{
    val EClass eclazz = f.clazz
    val uri = EcorePlugin.getEPackageNsURIToGenModelLocationMap(true).get(eclazz.EPackage.nsURI)
    val rs = new ResourceSetImpl
    val r = rs.getResource(uri, true)
    r.load(null)
    val p = r.contents.head
    if (p instanceof GenModel) {
        val genClass = p.findGenClassifier(eclazz)
        if (genClass instanceof GenClass) {
            println(genClass.qualifiedInterfaceName)
            members+=f.toField(eclazz.name, genClass.qualifiedInterfaceName.typeRef)
        }
    }
}
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
  • It's the thing that has the reference to the eclass – Christian Dietrich Sep 01 '17 at 03:46
  • I only have `operation.left` and `operation.right`, but they don´t have `clazz`, although they are of type EClass –  Sep 01 '17 at 08:08
  • Arrrg of course you have left and right I don't since I have named it clazz I thought that was obvious – Christian Dietrich Sep 01 '17 at 08:09
  • I did the example before knowing your grammar – Christian Dietrich Sep 01 '17 at 08:09
  • `uri` is null, seems like it can´t find `eclazz.EPackage.nsURI` in the map –  Sep 01 '17 at 09:16
  • where you your eclasses come from? do you have a ecore and a genmodel and code generated? – Christian Dietrich Sep 01 '17 at 09:17
  • how do you do the scping for the eclasses? – Christian Dietrich Sep 01 '17 at 09:27
  • did you consider to simpy reference the java class instead of the eclass as proposed before? – Christian Dietrich Sep 01 '17 at 09:28
  • I do have the ecore, genmodel and generated code. I didn´t do anything with scoping. I didn´t consider referencing the java classes. Could you give an example on how to do this? –  Sep 01 '17 at 09:45
  • Have a look the domain model example . If you don't have ecore and genmodel where do your eclasses come from – Christian Dietrich Sep 01 '17 at 09:46
  • What do you mean by domain model example, can you provide a link to that? –  Sep 01 '17 at 09:48
  • I have the ecore and genmodel –  Sep 02 '17 at 04:47
  • Sorry I have no idea how to reproduce your situation – Christian Dietrich Sep 02 '17 at 06:05
  • what did you mean by referencing the java classes instead of eclasses? –  Sep 02 '17 at 12:49
  • Xxxx=JvmParametrizedTypeReference (see superttype in domain model example) – Christian Dietrich Sep 02 '17 at 12:49
  • sry where can i find this example, can you please provide a link? –  Sep 02 '17 at 12:57
  • File menu, new, example xtext domain model example – Christian Dietrich Sep 02 '17 at 12:58
  • I forgot to mention that in my runtime Eclipse, I have imported a project with a test file for my grammar and a test ecore model (imdb example). When I open the test file, I can write an expression like `operation imdb.Film and imdb.Actor defined as ...` and at the dots its marked with errors. The point is, that the editor recognizes the EClasses _Actor_ and _Film_ . How can I achive, that _Actor_ and _Film_ can be used in the XExpression? I think, that I need to set a field in the inferrer for _Actor_ and _Film_ but there I´m not sure –  Sep 02 '17 at 15:19
  • also, I have created a git repo https://github.com/mrftothek/firstDSL with the source code –  Sep 02 '17 at 16:27
  • argg you dont have a genmodel and no java classes. – Christian Dietrich Sep 02 '17 at 17:15
  • ok so I need the imdb genmodel? and how do I get the java classes? and what do they even represent? is it like generated java classes like from the xtext grammar? –  Sep 02 '17 at 17:25
  • and yes these are the java classes representing the ecore model – Christian Dietrich Sep 02 '17 at 17:31
  • and you get the java classes by opening, rightclicking the genmodel root i the genmodel editor and select generate java code – Christian Dietrich Sep 02 '17 at 17:34
  • Christian, it´s working! Thank you very much for your time and effort! –  Sep 03 '17 at 10:49
  • how can I use the `ATTR` rule as identifier as in my example? when switching from `QualifiedName` to `ATTR`, the XExpression cant find the Java Class anymore for some reason –  Sep 06 '17 at 20:43
  • Attr conflicts with qualified name from xbase and has to be deleted and replaced with qualified name from xbase – Christian Dietrich Sep 07 '17 at 04:19
  • what´s the reason for that? because it´s a terminal rule? –  Sep 08 '17 at 16:49
  • Yes. And the lexer eats as much as it can – Christian Dietrich Sep 08 '17 at 16:50
  • hmm ok, I would need to add an import to the generated java class from the inferrer. I saw an approach like this https://www.eclipse.org/forums/index.php/t/487230/ , where `ImportedNamespaceAwareLocalScopeProvider` is subclassed and then bound in the RuntimeModule. Can I add arbitrary imports with this approach? –  Sep 09 '17 at 14:55
  • Depends on what you want to do – Christian Dietrich Sep 09 '17 at 15:36
  • I want to have the java class import a package from my workspace. I already added the dependency to it in the xtext project. Can this be achieved by template expressions? –  Sep 09 '17 at 16:08
  • What do you exactly want to achieve ? Setting a body in inferrer ? – Christian Dietrich Sep 09 '17 at 16:12
  • something like members+=entity.toMethod("demo", Void.TYPE.typeRef) [body='''«List»<«String»> list = new «ArrayList»<«String»>();'''] ??? – Christian Dietrich Sep 09 '17 at 16:21
  • no, I want to be able to use methods from a package inside of my XExpression. Therefore I think I need to have the generated java class by the inferrer, import this package. So I would need to set the import section for this java class. –  Sep 09 '17 at 16:53
  • simply use an ximportsection? see domainmodel example – Christian Dietrich Sep 09 '17 at 16:54
  • otherwise customize org.eclipse.xtext.xbase.scoping.batch.ImplicitlyImportedFeatures – Christian Dietrich Sep 09 '17 at 16:55
  • I dont need the import section in my grammar. I just want to be able to access the methods from only this package, inside of my XExpression –  Sep 09 '17 at 16:56
  • then ImplicitlyImportedFeat‌​ures is the place to look at – Christian Dietrich Sep 09 '17 at 16:56
  • doesnt this require the grammar to use `XImportSection` ? –  Sep 09 '17 at 17:02
  • no ImplicitlyImportedFeat‌​ures is used to provide e.g. the xbase libary – Christian Dietrich Sep 09 '17 at 17:02
  • https://github.com/xtext/seven-languages-xtext/blob/master/languages/org.xtext.tortoiseshell/src/org/xtext/tortoiseshell/scoping/TortoiseShellImplicitlyImportedFeatures.xtend I followed this example, I edited the original post. But I can´t see the import of `PackageFromWorkspace` in my inferred java class. Did I override the wrong method? –  Sep 10 '17 at 22:18
  • You need to add the jar to both the project containing the inferrer and the project containing the model files . And you see it only if you use it. And don't forget the binding the mydslruntimemodule – Christian Dietrich Sep 11 '17 at 03:48
  • And you may have to make sure it's exported in the defining plugin – Christian Dietrich Sep 11 '17 at 03:50
  • https://github.com/xtext/seven-languages-xtext/blob/master/languages/org.xtext.tortoiseshell/src/org/xtext/tortoiseshell/TortoiseShellRuntimeModule.xtend#L25 – Christian Dietrich Sep 11 '17 at 03:52
  • Do you mean the example project in the editor by "project containing model files"? –  Sep 11 '17 at 07:07
  • Yes I mean the project containing the yourdsl files – Christian Dietrich Sep 11 '17 at 09:53