Why does my custom scope not work?


so I'm trying to implement some scoping (like in the MPS Calculator example - my XXXReference also is of type Expression, so it's merely the same). However, now I'm fighting against the annoying problem, that MPS always takes any kind of expression, available in the scope of my solution, as a possible candidate for a reference, but I do not want that! So I tried to solve it using inherited scope, reference scope and also the deprecated variant search scope. I was able to include my own stuff in the drop down menu for referencing, however, MPS won't let me remove the other stuff it puts in the drop down menu (which should not be there). Currently, my assumption is that reference scope kinda should allow me to build up the scope from scratch, as I only return the scope I created, and search scope joins a default scope (from where?) with the one I created. Am I right or totally off track? Or isn't there any way to somehow remove such existing, other Expression from the drop down menu? I also tried to constrain it with can be parent, which actually also did not work (still all kinds of Expression possible).

More specific:

I have a concept Operation which itself has Parameters (another concept). An operation may by annotated with Pre-/Postconditions (own concepts extending NodeAttribute). Each Pre-/Postcondition has one child of type Expression. And it's exactly inside this expression where I only want to refer to the parameters of the operation the pre-/postcondition is annotating, but nothing else.

Any ideas or hints?

Thanks in advance,

Inside the "actions" aspect of your language you can create a "Node Substitute Actions", which provides different actions to add/remove entries to/from the completion menu.
thx, will try it!
but first, what has substituting to do with creating references?
Im not sure if I really understand your problem. Have you also tried "can be ancestor" or only "can be parent"?
hm, just to clarify whether me or MPS is wrong:

suppose I have a concept named A and a concept enabling references to this concept A, named AReference. Now why does MPS generate a method signature (sorry for calling it that way, but I don't know how to else call it) that looks like ...->join(ISearchScope | sequence<node<AReference>>) if using 'search scope (I know it's deprecated, but nevertheless, I think it still should work). Should the signature look like something ...->join(ISearchScope | sequence<node<A>>)'', as I want to reference instances of concept A and not references to instances of concept A. I'm a little baffled right now.
I suppose you created the "search scope" as the "default scope" of AReference. Then it is right that you see "join(ISearchScope | sequence<node<AReference>>)". You need to create a "referent constraint" for the reference to A.
The concept constraint for AReference has to look like this:
concepts constraints AReference { 
  can be child <none> 
  can be parent <none> 
  can be ancestor <none> 
  <<property constraints>> 
  link {a} 
    referent set handler:<none> 
      (model, exists, contextNode, contextRole, position, scope, referenceNode, linkTarget, enclosingNode, containingLink, operationContext)->join(ISearchScope | sequence<node<A>>) { 
        <no statements> 
    presentation : 
      <no presentation> 
  default scope 
    <no default scope> 
yep, my fault, wrong location. Hm, my problem simply is that I do not want MPS to add stuff to the scope I define. This is quite an annoying behavior. Why is there the possibility to define a custom scope, yet MPS adds all kind of stuff, one actually does no need there (just because it assumes that I may be needed)?
This really depends on particular use case. In general if you redefine scope you modify set of available (visible) elements for particular reference. In addition some other popup menu items can be provided there from actions aspect (as Sascha mentioned before).

Can you try to be more specific while describing your problem or m.b. you can share sample project with us to ensure we are solving the problem you have.
The problem is simple: I have a reference scope, where I only want to show parameters of an operation, that can be used in a pre/postcondition, applied to the operation. I'm using the same scheme as in the Calculator example (ParameterReference is of type expression, as the contents of a pre/postcondition are expressions itself - as the output field in the Caluclator example). However, now in the drop down menu, if I'm about to edit the expression of the pre/postcondition, I see everything (everything hereby means all JDK types I import, as my model also makes use of Classes, Interfaces and the like....). The only thing I want to do is create a scope like in the following

SimpleRoleScope.forNamedElements(contextNode.ancestor<concept = Operation>.parameterList, link/ParameterList : parameters/);

which in the should end only contain the parameters of the oepration where a condition is added, but nothing else - however, this does not happen. I always see all kinds of JDK types, my own Classes and so on...it's just, I want to remove that stuff and I don't get why MPS puts it all there, also I specifically define the scope contents with the above expression.
That has nothing to do with the scope for your ParameterReference. You are allowing Expressions in your pre/postconditions and because an AbstractClassifierReference is an Expression, MPS puts it into the completion menu. You see all imported classes because AbstractClassifierReference is a smart reference which means that MPS automatically creates an instance of AbstractClassifierReference for each class.

There are two ways to remove these entries. You can forbid instances of AbstractClassifierReference inside your pre/postcondition by defining a can be ancestor constraint for your pre/postcondition. The otherway is to use Node Substitute Actions, as I already mentioned.

Please sign in to leave a comment.