Understanding the XTend/XText source

100 views
Skip to first unread message

redhat...@gmail.com

unread,
Mar 31, 2016, 11:14:36 PM3/31/16
to Xtend Programming Language
I would like to do some hacking into XTend but am having quite a bit of trouble wading through the XTend/XText source. I am currently trying to find where xtend property access is converted into java getter and setter calls (So 'obj.property = value' becomes 'obj.setProperty (value)'). Someone with a better understanding of how XTend works want to point me to the right source file?

Christian Dietrich

unread,
Apr 1, 2016, 2:32:46 AM4/1/16
to Xtend Programming Language, redhat...@gmail.com
Have a look at

org.eclipse.xtext.xbase.scoping.batch.AbstractSessionBasedScope.processAsPropertyNames(QualifiedName, NameAcceptor)

redhat...@gmail.com

unread,
Apr 1, 2016, 7:31:39 PM4/1/16
to Xtend Programming Language, redhat...@gmail.com
Thank you, that is what I was looking for and will most definitely be helpful in implementing some other things I plan on exploring.

Unfortunately it doesn't cover all of what I thought it would. If I'm correctly understanding the part you pointed me to it only deals with replacing names with other names (e.g. "property" with "getProperty"). This works for getters/setters but not If I wanted to do something more complex. Like replace, for example, one method and its arguments with a different method call with different arguments. Basically what I'm looking for is the current location to replace an entire XExpression with a different XExpression. Is there a good place to do this, or does the XText/XTend code base not really support that?

Christian Dietrich

unread,
Apr 2, 2016, 3:04:44 AM4/2/16
to Xtend Programming Language, redhat...@gmail.com

this is not directly supported. can you be more specific about your usecase

redhat...@gmail.com

unread,
Apr 3, 2016, 10:39:37 PM4/3/16
to Xtend Programming Language, redhat...@gmail.com
I'm attempting to implement bracket access overloading. I've almost got it working using the following code.

    protected void _computeTypes(final XAbstractFeatureCall featureCall, ITypeComputationState state) {
        List<? extends IFeatureLinkingCandidate> candidates = state.getLinkingCandidates(featureCall);
        IFeatureLinkingCandidate best = (IFeatureLinkingCandidate) getBestCandidate(candidates);

        // If type was unable to be resolved and has one argument of type
        // closure it might be bracket access
        if (best instanceof UnresolvableFeatureCall)
        {
            EList<XExpression> args = featureCall.getActualArguments();
            if (args.size () == 1 && args.get(0) instanceof XClosure)
            {
                XExpression expression = ((XClosure) args.get(0)).getExpression();
                if (expression instanceof XBlockExpression)
                    expression = ((XBlockExpression) expression).getExpressions().get(0);

                args.clear();

                XMemberFeatureCall get = XbaseFactory.eINSTANCE.createXMemberFeatureCall();
               
                EObject parent = featureCall.eContainer();
                Object value = parent.eGet(featureCall.eContainingFeature(), false);
                if (value instanceof List)
                {
                    List list = (List) value;
                    int pos = list.indexOf (featureCall);
                    get.setMemberCallTarget(featureCall);
                        list.add(pos, get);
                } else
                {
                    parent.eSet(featureCall.eContainingFeature(), get);
                    get.setMemberCallTarget(featureCall);
                }

                get.getMemberCallArguments().add(expression);
                _computeTypes(featureCall, state);

                candidates = state.getLinkingCandidatesByName(QualifiedName.create("get"), get);
                best = (IFeatureLinkingCandidate) getBestCandidate(candidates);

                get.setFeature (best.getFeature());
                state.computeTypes(expression);
                return;
            }
        }

        if (best.isTypeLiteral()) {
            checkTypeParameterNotAllowedAsLiteral(featureCall, (JvmType) best.getFeature(), state);
        }
        best.applyToComputationState();
    }

The problem here is that the 'get' XMemberFeatureCall is never rolled into the resolved types so further calls don't resolve correctly ('list[0]' compiles but 'list[0].charAt(0)' does not). Calling 'best.applyToComputationState()' for the get linking candidates would resolve the type problem, but as the XExpression doesn't have any Nodes back it other problems arise. One possible way to solve the problem would be to create the Nodes and Grammer elements to go along with the XExpressions, but I'm rather at a loss on how to do that.

redhat...@gmail.com

unread,
Apr 5, 2016, 3:19:11 AM4/5/16
to Xtend Programming Language, redhat...@gmail.com
Finally got it working. You can see the code here if you're interested.


On Saturday, April 2, 2016 at 12:04:44 AM UTC-7, Christian Dietrich wrote:

lum...@gmail.com

unread,
Apr 6, 2016, 11:10:27 AM4/6/16
to Xtend Programming Language, redhat...@gmail.com
Interesting; to what extent have you implemented the functionality?
I assume for the moment only to implement an indexing operator?

redhat...@gmail.com

unread,
Apr 6, 2016, 1:50:50 PM4/6/16
to Xtend Programming Language, redhat...@gmail.com, lum...@gmail.com
Yes, at the moment I've only implemented the bracket operator. I do have plans to implement some other functionality (for example a default method).

In order to implement setting of indexed elements (array[i] = value) I need to edit the language syntax definition. Editing plugins/org.eclipse.xtext/src/org/eclipse/xtext/XText.xtext doesn't seem to have any affect. Do I need to compile the xtext file beyond running './gradlew assemble -PbuildServer'?

lum...@gmail.com

unread,
Apr 7, 2016, 8:35:03 AM4/7/16
to Xtend Programming Language, redhat...@gmail.com, lum...@gmail.com
Excellent work I must say, it's a considerable QOL improvement.

Reading through the issue, I agree with most what Max Bureck has to say on using the Java 8 pattern (SAM types) for default methods (option 1).
I don't suspect that the disadvantages mentioned actually occur all that often; and that if they occur, the ambivalence can be solved by the introduction of the "operator_apply" (or specific casting).
So implementing both option 1 & 3 would in my book be the biggest gain.
Reply all
Reply to author
Forward
0 new messages