[Xtext 2.1] property databinding in own dsl [message #757800] |
Mon, 21 November 2011 18:00 |
Max Goltzsche Messages: 40 Registered: November 2011 |
Member |
|
|
Hey,
in case of the domainmodel example: What would be the best approach to realise a databinding in a custom dsl?
With databinding I mean typing a (nested) property in some view input's attribute so that it can be read and written in different states of the application like e.g. in JSF, Flex etc..
entity.referenceA.referenceB
Is there some extension point in xbase for this case?
regards,
Max
[Updated on: Thu, 24 November 2011 01:57] Report message to a moderator
|
|
|
|
|
Re: property databinding in own dsl [message #758635 is a reply to message #758268] |
Thu, 24 November 2011 01:53 |
Max Goltzsche Messages: 40 Registered: November 2011 |
Member |
|
|
Hey,
I've found a shorter solution using xbase by writing an own XMemberFeatureCall rule which does not offer method calls:
grammar org.company.lang with org.eclipse.xtext.xbase.Xbase
generate lang "http://www.company.org/lang/Lang"
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types
...
Input:
'input' binding=DataBinding;
DataBinding returns xbase::XExpression:
XFeatureCall
({xbase::XMemberFeatureCall.memberCallTarget=current} '.'
feature=[types::JvmIdentifiableElement|ValidID])*;
Now, I'm able to write sth like this assuming the root scope contains the entity variable a:
XMemberFeatureCalls are already handled by the XbaseScopeProvider.
I do not want method calls, blocks and control flow statements. Just a simple property binding / property path.
Now, it works so far that I cannot write:
input a.name.substring(0, 1) because this is not defined in the syntax but I can write:
Although the syntax is correct the method has no arguments and that's what is displayed in the IDE.
I may modify the scope to forbid method calls or override the error message in a validator - Is it possible to override other error messages like this one?
regards,
Max
[Updated on: Thu, 24 November 2011 02:26] Report message to a moderator
|
|
|
|
Re: property databinding in own dsl [message #758887 is a reply to message #758667] |
Fri, 25 November 2011 04:52 |
Max Goltzsche Messages: 40 Registered: November 2011 |
Member |
|
|
I've implemented this validator method to solve my problem:
@Check
def checkInputBinding(Input input) {
val binding = input.getBinding() as XMemberFeatureCall;
val feature = binding.getFeature();
try {
// retrieve expression's return type
val method = feature as JvmOperation;
val exprReturnTypeName = binding.getType(true).getType().identifier
val getterPrefix = if (exprReturnTypeName.toLowerCase == "java.lang.boolean") "is" else "get"
// transform to setter method name if current method's name matches getter signature
val methodName = method.identifier
val regex = "^(.*?\\.)" + getterPrefix + "([A-Z][\\w]*)\\(\\)$"
val setterName = methodName.replaceFirst(regex, "$1set$2(" + exprReturnTypeName + ")")
if (methodName != setterName) { // if method is getter
val callTarget = binding.getMemberCallTarget();
val featuresAvailable = callTarget.getType(true).getType().eContents();
val methodsAvailable = featuresAvailable.filter(typeof(JvmOperation))
for (m : methodsAvailable)
if (m.identifier.startsWith(setterName))
return; // if setter is also available
}
} catch(ClassCastException e) { }
// else: is not a property binding
error("Valid property binding required. Please register a property with getter and setter.", UclPackage$Literals::INPUT__BINDING)
}
But a I agree with you: Extending the scope provider would be better.
Where is the best position to filter the possible XMemberFeatureCalls in the scope?
Thought about sth like:
if (call.eContainingFeature() == UclPackage.Literals.INPUT__BINDING)
// ... {do filter} ...
But where to put it?
Maybe the best solution would be to extend FilteredDelegatingScope and overwrite the filtering Predicate.apply() method but how to inject it?
regards,
Max
[Updated on: Fri, 25 November 2011 06:12] Report message to a moderator
|
|
|
Re: property databinding in own dsl [message #758902 is a reply to message #758887] |
Fri, 25 November 2011 06:59 |
Max Goltzsche Messages: 40 Registered: November 2011 |
Member |
|
|
Finally, after reading some other posts I realised, that in this case it is better to use a validator: The user sees the scope he expects and gets a message that informs him about the required property binding.
However, I had another problem where I wanted to hide every method of a boundary class in the scope because I generate methods from expressions in a view language. Inside a expression several view properties should be visible but not my generated methods. Also the problem targeted with this thread should be solved by a custom implementation of VisibilityService and binding in MyLangRuntimeModule:
public class UclVisibilityService extends VisibilityService {
@Inject
private IJvmModelAssociations associations;
@Override
public boolean isVisible(final JvmMember jvmMember, JvmDeclaredType contextType) {
final EObject o = associations.getPrimarySourceElement(jvmMember.eContainer());
if (o instanceof View && jvmMember instanceof JvmOperation)
return false;
return super.isVisible(jvmMember, contextType);
}
}
regards,
Max
[Updated on: Fri, 25 November 2011 07:00] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.03835 seconds