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
Please sign in to leave a comment.
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
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
Hello, Kevin,
You can use referenceNode and enclosingNode variable inside of scope block in order to limit the scope.
Regards,
Konstantin
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:
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
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
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
Great to hear !
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.
'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.
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
Put caret after closing curly brace of 'if-statement', then perform right-transform (space , ctrl+space) or type 'else{' or 'else if'.
~Igor.
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