Limiting the contents of the completion menu

Hello again,

I have a simple record structure like so:

record RECT
   NBits : UnsignedBit [ 5 ]
   Xmin  : SignedBit [ NBits ]
   Xmax  : SignedBit [ NBits ]
  ...

end record

When I activate code completion within the square brackets, I see two concepts: FieldReference and NumericIndex, which is perfect. However, once I select FieldReference I would like to confine the new code completion list to show only fields names in the current record that come before the current field I'm editing. I'm using the following in my FieldReference editor:

( % field % -> { name } )

I end up with a list of all field names in all records in my document. It seems like I need to use SModel to select what to display, but I'm not sure where (or how) I would do that. If this is possible, how would a go about adding this functionality to my editor?

Thanks,

Kevin

0
10 comments
Avatar
Permanently deleted user

Hello, Kevin,

You can take a look at how to limit scopes at the calculator tutorial here: http://www.jetbrains.com/mps/docs/tutorial.html#Creating_a_scope_for_InputFieldReference

Regards,

Konstantin

0

Hi Konstantin,

OK, I was able to limit the scope to show only fields in the current record using the following:

node < Record > record = enclosingNode . ancestor < concept = Record > ;

return record . descendants < concept = FieldDeclaration > ;          

However, I'd like to show only the fields inside the record that come before the current position. For example, if I have the following:

record  MATRIX                                 

   HasScale : UnsignedBit [ 1 ]                

   if ( HasScale := 1 )                        

      NScaleBits : UnsignedBit [ 5 ]           

      ScaleX : FixedPointBit [ NScaleBits ]    

      ScaleY : FixedPointBit [ NScaleBits ]    

   end if                                      

   HasRotate : UnsignedBit [ 1 ]               

   if ( HasRotate := 1 )                       

      NRotateBits : UnsignedBit [ 5 ]          

      RotateSkew : FixedPointBit [ <abstract concept> ]

      RotateSkew1 : FixedPointBit [ NRotateBits ]

   end if                                      

   NTranslateBits : UnsignedBit [ 5 ]          

   TranslateX : SignedBit [ NTranslateBits ]   

   TranslateY : SignedBit [ NTranslateBits ]   

end record                                     

and if the cursor is located at <abstract concept> in the RotateSkew field, I'd like to show only HasScale, NScaleBits, ScaleX, ScaleY, HasRotate, and NRotateBits. Is there an equivalent in sModel to the preceding/following axes in XSLT? Ideally, the method could take a node as a parameter indicating when the traversal should stop. I'm not seeing anything like this in the docs, so I'm assuming I will need to write the equivalent.

Thanks again,

Kevin

0
Avatar
Permanently deleted user

Hello, Kevin,

You can use referenceNode and enclosingNode variable inside of scope block in order to limit the scope.

Regards,

Konstantin

0

We have prev-sibling(s)/next-sibling(s) operation applicable to model node.

If it was base languge (java) I would write code like this below:

local_vars_example.PNG


public sequence<node<>> getAllLocalVarsBefore(node<> n) {
  list<node<>> result = new arraylist<node<>>;
  node<Statement> anchor = n.ancestor<concept = Statement, +>;
  while (anchor != null) {
    result.addAll(anchor.prev-siblings);
    anchor = anchor.ancestor<concept = Statement>;
  }
  return result.where({~it => it.isInstanceOf(LocalVariableDeclarationStatement); }).select({~it => it : LocalVariableDeclarationStatement.localVariableDeclaration; });
}

This code collects all declaration of local variables preceding node n.

If you replace Statement and LocalVariableDeclaration with their counterparts, it will probabaly work for your language.

As Konstantin mentioned, you can use enclosingNode as the input.



Attachment(s):
local_vars_example.PNG
0

Hi Igor,

Thanks for the sample code. I'll give this a try. I do have more questions, but I'll start those on other threads to keep the thoughts separate.

Thanks,

Kevin

0

Hi guys,

I ended up getting this to work with the following:

node < Record > record = enclosingNode . ancestor < concept = Record > ;                                 

sequence < node < FieldDeclaration > > declarations = record . descendants < concept = FieldDeclaration > ;

return declarations . cut ( declarations . size - declarations . indexOf ( enclosingNode . parent ) ) ;                        

My language doesn't support arbitrary nesting, so I was able to get away with cutting the list at the declaration that is being edited (via enclosingNode.parent). A couple questions came up from this:

1. Does sModel NOT have an IfElseStatement

2. Does sequence<>.indexOf determine the index from the end of the list or, perhaps, does cut remove from right-to-left as the index increases? The index in declarations.cut didn't work as I expected.

Anyway, it is working. Thanks for the help!

-Kevin

0

Great to hear !

1. Does sModel NOT have an IfElseStatement

smodel language doesn't have IfStatement because smodel language is extention of base language (which does have IfStatement).

Your code has been actually writen using combination: base language + collections lang + smodel lang,

therefore you should have had no problems inserting if-statements into your code.

2. Does sequence<>.indexOf determine the index from the end of the list or, perhaps, does cut remove from right-to-left as the index increases?

'cut' operation removes N trailing elements from collection.

You would, probably, prefer the  'take' operation here. (see also doc on collections: http://www.jetbrains.net/confluence/display/MPS/Collections+language)

Regards, Igor.

0

Hi Igor,

Thanks for the clarifications. FWIW, I have been able to create IfStatements, but I don't see how to create "else" clauses.

Thanks,

Kevin

0

Put caret after closing curly brace of 'if-statement', then perform right-transform (space , ctrl+space) or type 'else{' or 'else if'.

~Igor.

0

Hi Igor,

OK, that's working for me. I was simply typing ctrl-space after the closing curly brace, which does not bring up a code completion menu. So, typing space first was the trick.

Thanks!

Kevin

0

Please sign in to leave a comment.