Constrain operations on DotExpression

I have a concept "PartyDeclaration" with child "Party" and a name. The "Party" concept has a child "input" of type InputDeclaration. The InputDeclaration can be accessed via the concept "InputRef", and the PartyDeclaration via the concept "PartyRef". I want to be able to access this input from a PartyRef with a DotExpression, and thus my InputRef concept extends IOperation. This works, I now can access all inputs via a dot after the parties name. See the following picture:

But as you can see, the auto-complete menu includes the input from all the parties, not just the one from which it is accessed (here Y). I tried to add "can be child" constraints to InputReference, so that the operand and operation of the DotExpression have to point to the same Party. My attempt is as follows:

Now, I do get no suggestions when trying to do a dot expression. I realised that this was because "node" is null at the moment when this constraint is called and thus the comparison does not work. Does anyone have a solution for this problem? I cannot think of a solution that does not have to access "node" itself.

Thanks in advance for any answers!


Comment actions Permalink

Within your concept constraint, there is a section where you can provide a "scope" for a reference (the "ref" in your PartyRef concept). You want to build a scope based on the left side of the Dot operation. There are (at least) two ways how you can define your scope, see

If you opt for "using reference scope", you use the contextNode that is passed in to naviagte in your AST to the Party, collect all its inputs in a sequence. Then, you could return a "ListScope", which expects a collection of things it should contain. Hope this helps.

Comment actions Permalink

Thank you so much for answering!

I am not sure I understand completely though. You suggest that I should build a scope based on the left side of the Dot Expression, which is a PartyRef. So I tried adding a reference scope on "ref" in PartyRef, the way you suggested, as follows:

But doesn't this just restrict what "ref" in PartyRef can point to? It results in the following situation, where I cannot use PartyRef's anywhere in my program, because "The reference Y (ref) is out of search scope".

Did I specify the reference scope in the wrong file or did I do something wrong with the definition of the scope itself?

Thanks again for any answers!

Comment actions Permalink

Yeah, I misspoke, you need to create a scope for the reference inside your InputRef concept. 

You need to do

contextNode.ancestor<DotExpression, +>;

to get the inputs, assuming that your InputRef is a child of DotExpression, which also holds the PartyRef child called "partyRef".

I'm not sure why, in your screenshot, there is "", since I would assume "ref" already points to a node of concept "Party", but you get the idea, right?

Don't forget the "+" in the "ancestor<...>" operation to include the contextNode itself in the lookup (based on your structure, the contextNode might already be the DotExpression you are looking for.

Comment actions Permalink

Thanks you for the quick reply! 

Now I got the idea! With your code snippet and your explanation I was able to make it work perfectly.

"ref" actually points to a "PartyDeclaration", which in turn contains the "Party" itself, that's why I have to call "".

My final working constraint now looks like this: 

I am really grateful for your help :)

Comment actions Permalink

Very good.

I would probably factor out the cast to PartyRef, since the ":" operator might give you a NullReferenceException at runtime.

node<DotExpression> dotExpr = contextNode.ancestor<concept = DotExpression, +>;
ifInstanceOf(dotExp.operand as PartyRef partyRef) {
return ListScope.forNamedElements(;

return new EmptyScope();

Did you know that, when you select the "ancestor" operation in your code and you press "CTRL+ALT+V" (or "CMD+ALT+V" on a Mac I assume) MPS will automatically create a local variable for you?

Comment actions Permalink

Thanks for the tips!


Please sign in to leave a comment.