Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Implicitly add method call to generated interface.
Implicitly add method call to generated interface. [message #1754650] Tue, 21 February 2017 10:15 Go to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
Hi,

I'am developing a DSL which relies on Xbase and allows some simple implementations for methods. In my JVMModelInferrer I created a player attribute of type I<RoleName>Player. Thus, I can refer to it without explicit declaration.

However, whenever I invoke a method on this player Attribute I would like to add it to the generated Interface implicitly. Unfortunately, I've no idea how to hook into Xbase inside the JvmModelInferrer in order to retrieve method names and attributes.

CollSpec:
    importSection=XImportSection?
    module = Module;


Module:
    'module' name=QualifiedName
    collaboration = Collaboration;


Collaboration:
    'collaboration' name=ValidID '{'
    (
            (roles+=CoordinatorRole) &
            (roles+=NonCoordinatorRole+)
    )
    '}'
;

CoordinatorRole:
    'coordinator' 'role' Role
;

NonCoordinatorRole:
    'role' Role
;

fragment Role:
    name=ValidID '{'
    features+=Feature*
    '}'
;

...

Feature:
    Property | Operation;

Property:
    name=ValidID ':' type=JvmTypeReference;

Operation:
    (isPlayerQualifierSet?='playable') 'op' name=ValidID
    '('(params+=FullJvmFormalParameter
    (',' params+=FullJvmFormalParameter)*)?')'
    ':' type=JvmTypeReference
    body=XBlockExpression?;


In the following example I'd like to add the doSomething Method of role B to IBPlayer interface.

collaboration Test {
    coordinator role A {
    }
    role B {
        test:String
        playable op bar() :String {
            player.doSomething(String test)
        }
    }
}
Re: Implicitly add method call to generated interface. [message #1754651 is a reply to message #1754650] Tue, 21 February 2017 10:20 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
can you please post the expected java code as well. is the interface inferred or is it a existing class? you want to be ablte to call a method that does not exist? so let it drop from the sky?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Tue, 21 February 2017 10:25]

Report message to a moderator

Re: Implicitly add method call to generated interface. [message #1754656 is a reply to message #1754651] Tue, 21 February 2017 11:21 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
Thanks for your reply!
Christian Dietrich wrote on Tue, 21 February 2017 10:20
can you please post the expected java code as well.

For each Role a class and an interface is generated.
The class gets the following method:
public String bar() {
    player.performBRoleDoSomething() // something like getPlayer().doSomething() would be preferred actually.
    return null;
}

and the interface gets the performBRoleDoSomething() method.

Christian Dietrich wrote on Tue, 21 February 2017 10:20
is the interface inferred or is it a existing class?

both, here an excerpt of my Inferer:
def dispatch void infer(NonCoordinatorRole role, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase, CollSpec collSpec){
        acceptor.accept(role.toClass('''«collSpec.module.fullyQualifiedName».«role.name»Role''')) [
            documentation = role.documentation
            if(!isPreIndexingPhase) {
                superTypes += AbstractRole.typeRef
                var playerRef = typesFactory.createJvmField()
                playerRef.type = typeRef('''«collSpec.module.fullyQualifiedName».I«role.name»RolePlayer''')
                playerRef.simpleName = 'player'
                playerRef.visibility = JvmVisibility.PRIVATE
                playerRef.type
                members += playerRef
            }
            for(feature : role.features) {
                switch feature {

                    Property : {
                        members += feature.toField(feature.name, feature.type)
                        members += feature.toGetter(feature.name, feature.type)
                        members += feature.toSetter(feature.name, feature.type)
                    }

                    Operation : {
                        members += feature.toMethod(feature.name, feature.type) [
                            documentation = feature.documentation
                            for(p : feature.params) {
                                parameters += p.toParameter(p.name, p.parameterType)
                            }
                            body = feature.body
                        ]
                    }
                }
            }
        ]
    }

    def void inferPlayerInterface(Role role, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase, CollSpec collSpec) {
        acceptor.accept(role.toClass('''«collSpec.module.fullyQualifiedName».I«role.name»RolePlayer''')) [
            setInterface = true
            for (feature : role.features) {
                if (feature instanceof Operation) {
                    if (feature.isPlayerQualifierSet) {
                        members += feature.toMethod('''perform«role.name»Role«feature.name.toFirstUpper»''', feature.type) [
                            documentation = feature.documentation
                            for(p : feature.params) {
                                parameters += p.toParameter(p.name, p.parameterType)
                            }

//                            body = feature.body
                        ]
                    }
                }
            }
        ]
    }


Christian Dietrich wrote on Tue, 21 February 2017 10:20
you want to be ablte to call a method that does not exist? so let it drop from the sky?

Actually yes, it shall be dispatched at run time. So it does not drop from the sky but the complementing implementation is provided somewhere else. In the end there should be no fixed player attribute but for the moment this would be ok.

[Updated on: Tue, 21 February 2017 11:24]

Report message to a moderator

Re: Implicitly add method call to generated interface. [message #1754661 is a reply to message #1754656] Tue, 21 February 2017 11:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
yes but where is defined that there is a doSomething and its not doSomethingElse?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754663 is a reply to message #1754661] Tue, 21 February 2017 11:44 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
This is what I mean with implicit definition. This is also the reason for generating the interface. The DSL is the first step of a 2-step development strategy. In the second phase the interface needs to be implemented by a class.
By writing player.doSomething() i want to require that a corresponding player really provides this method.
Return types for such methods are not of interest so far. Thus I currently don't care about them.
Re: Implicitly add method call to generated interface. [message #1754666 is a reply to message #1754663] Tue, 21 February 2017 12:09 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
well the only thing i see is that you can traverse the node model to find out which method names are wanted and then add them in the inferrer

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754667 is a reply to message #1754666] Tue, 21 February 2017 12:13 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
Okay, this is basically what I expected, but where can i hook into that?
Traversing the feature.body seems a little bit tricky because almost everything is an XExpression and I assume that not everything allows such a method call. Which model elements of XExpression are the ones to take care of?

Thanks in advance.
Re: Implicitly add method call to generated interface. [message #1754670 is a reply to message #1754667] Tue, 21 February 2017 12:36 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
this is the only thing you can do.

you shoud have a look at XMemberFeatureCalls


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754686 is a reply to message #1754670] Tue, 21 February 2017 14:42 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
While having a look at XMemberFeatureCall in Xbase Definition I thought about a special rule, which could simplify parsing. Something like
PlayerFeatureCall returns xBase::XExpression:
    {PlayerFeatureCall}
    'player'
    ((".")
    feature=[types::JvmIdentifiableElement|IdOrSuper] (
            =>explicitOperationCall?='('
            (
                    memberCallArguments+=XExpression (',' memberCallArguments+=XExpression)*
            )?
            ')')?
    );

Unfortunately, this code snippet seems to be wrong - when typing player.doSomething( ) it is not recognized as a special rule.
Re: Implicitly add method call to generated interface. [message #1754692 is a reply to message #1754686] Tue, 21 February 2017 15:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
id simply use nodemodel and have a look at the text for the stuff at the beginning of the rule and see if it is player

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754717 is a reply to message #1754692] Tue, 21 February 2017 18:39 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
Christian Dietrich wrote on Tue, 21 February 2017 15:32
id simply use nodemodel and have a look at the text for the stuff at the beginning of the rule and see if it is player

So still traversing XExpressions? Or did I get something wrong? What do you mean with "beginning of the rule and see if it is player".
Re: Implicitly add method call to generated interface. [message #1754718 is a reply to message #1754717] Tue, 21 February 2017 18:57 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
yes traversing the expressions and find the one that look like player.xxxx

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754934 is a reply to message #1754718] Fri, 24 February 2017 09:22 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
What is the right place to traverse the tree? Right now I'm doing this in the JvmModelInferrer. The problem is that I can find them, but they are not added to the interface - so at least the new interface is not generated. A reason for this might be, that the IDE (IntelliJ in my case) tries to resolve types before and cannot find them off cause, thus it interrupts the building process - but I'm not sure about this.
Re: Implicitly add method call to generated interface. [message #1754935 is a reply to message #1754934] Fri, 24 February 2017 09:29 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
can you please show what you are doing in your code.

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754937 is a reply to message #1754935] Fri, 24 February 2017 09:34 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
Sure.

In the JvmInferrer I start with inferring the root element.
def dispatch void infer(CollSpec collSpec, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
        infer(collSpec.module.collaboration,acceptor,isPreIndexingPhase,collSpec)
        collSpec.module.collaboration.roles.forEach [
            infer(it,acceptor,isPreIndexingPhase,collSpec)
        ]
        collSpec.module.collaboration.roles.forEach [
            inferPlayerInterface(it,acceptor,isPreIndexingPhase,collSpec)
        ]
    }


The interface is generated like this:
def void inferPlayerInterface(Role role, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase, CollSpec collSpec) {
        acceptor.accept(role.toClass('''«collSpec.module.fullyQualifiedName».I«role.name»RolePlayer''')) [
            setInterface = true
            for(feature : role.features) {
                if(feature instanceof Operation) {
                    if(feature.isPlayerQualifierSet) {
                        members += feature.toMethod('''perform«role.name»Role«feature.name.toFirstUpper»''', feature.type) [
                            setDefault = false
                            documentation = feature.documentation
                            for(p : feature.params) {
                                parameters += p.toParameter(p.name, p.parameterType)
                            }
                        ]
                    }
                    var playerReferences = feature?.body?.findPlayerReferences
                    for(featureCall : playerReferences) {
                        println(featureCall)
                        var op = typesFactory.createJvmOperation
                        members += featureCall.toMethod('''perform«role.name»Role«feature.name.toFirstUpper»«featureCall.feature.simpleName.toFirstUpper»''',if(featureCall.explicitReturnType) featureCall.returnType else Void.typeRef) [
                            setDefault = false
                            setAbstract = true
                        ]
                    }
                }
            }
        ]
    }

The method findPlayerReferences returns the correct references - I added them as a specific modeling element to my grammar:
PlayerFeatureCall returns xBase::XExpression:
    (=>'player' '.' {PlayerFeatureCall}
    //('<' typeArguments+=JvmArgumentTypeReference (',' typeArguments+=JvmArgumentTypeReference)* '>')?
    feature=[types::JvmIdentifiableElement|IdOrSuper] (
            =>explicitOperationCall?='('
            (
                    //memberCallArguments+=XShortClosure
                    //|
                    memberCallArguments+=XExpression (',' memberCallArguments+=XExpression)*
            )?
            ')')?
    (=>explicitReturnType?='returns' returnType=JvmTypeReference)?
    //memberCallArguments+=XClosure?
    );

XPrimaryExpression returns xBase::XExpression:
    XConstructorCall |
    XBlockExpression |
    XSwitchExpression |
    XSynchronizedExpression |
    XFeatureCall |
    XLiteral |
    XIfExpression |
    XForLoopExpression |
    XBasicForLoopExpression |
    XWhileExpression |
    XDoWhileExpression |
    XThrowExpression |
    XReturnExpression |
    XTryCatchFinallyExpression |
    XParenthesizedExpression |
    PlayerFeatureCall
;
Re: Implicitly add method call to generated interface. [message #1754938 is a reply to message #1754937] Fri, 24 February 2017 09:41 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
i dont see where you traverse the node model

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754939 is a reply to message #1754938] Fri, 24 February 2017 09:43 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
the findPlayerReferences call traverses the body, which is an XExpression.

private def dispatch List<PlayerFeatureCall> findPlayerReferences(XExpression expr) {
        return newArrayList
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(Void expr) {
        return newArrayList
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XBlockExpression expr) {
        var result = newArrayList
        for(el : expr.expressions) {
            result.addAll(el.findPlayerReferences)
        }
        result
    }
    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XClosure expr) {
        var result = newArrayList
        result.addAll(expr.expression.findPlayerReferences)
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XIfExpression expr) {
        var result = newArrayList
        result.addAll(expr.getIf.findPlayerReferences)
        result.addAll(expr.getThen.findPlayerReferences)
        result.addAll(expr.getElse.findPlayerReferences)
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XForLoopExpression expr) {
        var result = newArrayList
        result.addAll(expr.forExpression.findPlayerReferences)
        result.addAll(expr.eachExpression.findPlayerReferences)
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XBasicForLoopExpression expr) {
        var result = newArrayList
        result.addAll(expr.eachExpression.findPlayerReferences)
        result.addAll(expr.expression.findPlayerReferences)
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XSwitchExpression expr) {
        var result = newArrayList
        result.addAll(expr.getSwitch.findPlayerReferences)
        result.addAll(expr.getDefault.findPlayerReferences)
        for(el : expr.cases) {
            result.addAll(el.findPlayerReferences)
        }
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XCasePart expr) {
        var result = newArrayList
        result.addAll(expr.getCase.findPlayerReferences)
        result.addAll(expr.getThen.findPlayerReferences)
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XAbstractWhileExpression expr) {
        var result = newArrayList
        result.addAll(expr.getPredicate.findPlayerReferences)
        result.addAll(expr.getBody.findPlayerReferences)
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XMemberFeatureCall expr) {
        var result = newArrayList
        result.addAll(expr.memberCallTarget.findPlayerReferences)
        result.addAll(expr.implicitFirstArgument.findPlayerReferences)
        result.addAll(expr.implicitReceiver.findPlayerReferences)
        result.addAll(expr.actualReceiver.findPlayerReferences)
        for(el : expr.memberCallArguments) {
            result.addAll(el.findPlayerReferences)
        }
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(PlayerFeatureCall expr) {
        var result = newArrayList
        result.add(expr)
        for(el : expr.memberCallArguments) {
            result.addAll(el.findPlayerReferences)
        }
        result
    }

    private def dispatch List<PlayerFeatureCall> findPlayerReferences(XAbstractFeatureCall expr) {
        var result = newArrayList
        result.addAll(expr.implicitFirstArgument.findPlayerReferences)
        result.addAll(expr.implicitReceiver.findPlayerReferences)
        result.addAll(expr.actualReceiver.findPlayerReferences)
        for(el : expr.actualArguments) {
            result.addAll(el.findPlayerReferences)
        }
        result
    }


Otherwise I don't know what you mean by node model.
Re: Implicitly add method call to generated interface. [message #1754941 is a reply to message #1754938] Fri, 24 February 2017 10:32 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
AST !== NodeModel

Model:
	elements+=Element*
;

Element:
	"element" name=ID "{"
		operation=Operation
	"}"
;

Operation:
	"op" name=ID "("")" body=XBlockExpression
;


/*
 * generated by Xtext 2.11.0.RC2
 */
package org.xtext.example.mydsl.jvmmodel

import com.google.inject.Inject
import org.eclipse.xtext.Action
import org.eclipse.xtext.nodemodel.ICompositeNode
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.xtext.example.mydsl.myDsl.Element
import org.xtext.example.mydsl.services.MyDslGrammarAccess
import org.eclipse.xtext.RuleCall

/**
 * <p>Infers a JVM model from the source model.</p> 
 * 
 * <p>The JVM model should contain all elements that would appear in the Java code 
 * which is generated from the source model. Other models link against the JVM model rather than the source model.</p>     
 */
class MyDslJvmModelInferrer extends AbstractModelInferrer {

	@Inject extension JvmTypesBuilder

	@Inject extension MyDslGrammarAccess

	def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(element.toInterface("demo.I" + element.name + "Player", [])) [
			if (element.operation !== null) {
				val node = NodeModelUtils.findActualNodeFor(element.operation.body)
				// search the nodemodel. this is just an example. make sure you catch all cases
				if (node !== null) {
					for (e : node.asTreeIterable) {
						val ge = e.grammarElement
						if (ge instanceof Action) {
							if (ge === XMemberFeatureCallAccess.XMemberFeatureCallMemberCallTargetAction_1_1_0_0_0) {
								if (e instanceof ICompositeNode) {
									for (ex : e.children) {
										val gex = ex.grammarElement
										if (gex instanceof RuleCall) {
											if (gex.rule === XMemberFeatureCallRule) {
												val text = ex.text.trim
												if ("player".equals(text)) {
													var next = ex.nextSibling
													while (next !== null) {
														if (next.grammarElement ==
															XMemberFeatureCallAccess.
																featureJvmIdentifiableElementCrossReference_1_1_2_0) {
																	val ftext = next.text.trim
																	members +=
																		element.toMethod(ftext, Void.TYPE.typeRef)[]
																	next = null
																} else {
																	next = next.nextSibling
																}
															}
														}
													}
												}
											}
										}
									}
								}

							}
						}
					}
				]
				acceptor.accept(element.toClass("demo." + element.name)) [
					members += element.toField("player", ("demo.I" + element.name + "Player").typeRef)[]
					if (element.operation !== null) {
						members += element.operation.toMethod(element.operation.name, Void.TYPE.typeRef) [
							body = element.operation.body
						]
					}
				]
			}
		}
		


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754942 is a reply to message #1754941] Fri, 24 February 2017 10:39 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
p.s.

you might start traversing the ast as you do,

but you may never follow cross references but use NodeModelUtils to get the node and text e.g
class MyDslJvmModelInferrer extends AbstractModelInferrer {

	@Inject extension JvmTypesBuilder

	@Inject extension MyDslGrammarAccess

	def dispatch void infer(Element element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
		acceptor.accept(element.toInterface("demo.I" + element.name + "Player", [])) [
			if (element.operation !== null) {
				for (XMemberFeatureCall c : EcoreUtil2.getAllContentsOfType(element.operation.body,
					XMemberFeatureCall)) {
					val node = NodeModelUtils.findNodesForFeature(c,
							XbasePackage.Literals.XMEMBER_FEATURE_CALL__MEMBER_CALL_TARGET).head
					if (node !== null) {
						val text = node.text.trim
						if ("player" == text) {
							val node2 = NodeModelUtils.findNodesForFeature(c,
							XbasePackage.Literals.XABSTRACT_FEATURE_CALL__FEATURE).head
							if (node2 !== null) {
								val text2 = node2.text.trim
								members+= element.toMethod(text2, Void.TYPE.typeRef)[]
							}
						
						}
					}
				}
			}
		]
		acceptor.accept(element.toClass("demo." + element.name)) [
			members += element.toField("player", ("demo.I" + element.name + "Player").typeRef)[]
			if (element.operation !== null) {
				members += element.operation.toMethod(element.operation.name, Void.TYPE.typeRef) [
					body = element.operation.body
				]
			}
		]
	}
}



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicitly add method call to generated interface. [message #1754955 is a reply to message #1754942] Fri, 24 February 2017 13:46 Go to previous messageGo to next message
Markus Wutzler is currently offline Markus WutzlerFriend
Messages: 11
Registered: October 2015
Junior Member
Thanks! This works perfect but one issue remains. I need to replace the defined method names like doSomething with more complex ones, e.g., performBRoleDoSomething. Currently I receive an Issue, that doSomething is undefined for the type I...Player. Where do I have to hook in to translate the method name to resolve this properly?
Re: Implicitly add method call to generated interface. [message #1754960 is a reply to message #1754955] Fri, 24 February 2017 14:40 Go to previous message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
sry have no idea on that. what about moving each operation to a own (inner class)

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Previous Topic:[SOLVED] Bring rule call and cross-reference under one feature
Next Topic:XtextGradlePlugin configuration problem
Goto Forum:
  


Current Time: Tue Apr 16 19:29:52 GMT 2024

Powered by FUDForum. Page generated in 2.08662 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top