Tuesday, 9 September 2014

Restricting auto-completion options - UI wise

Based on previous scope restriction idea, we can also try to restrict auto-completion for macro:
RFC1213-MIB.mib
          sysDescr OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-only
              STATUS  mandatory
               DESCRIPTION
                      "A textual description of the entity.  This value
                      should include the full name and version
                      identification of the system's hardware type,
                      software operating-system, and networking
                      software.  It is mandatory that this only contain
                      printable ASCII characters."
              ::= { system 1 }
Which corresponds to following grammar:
Mib.xtext
ObjectType returns Identifier:
 name=Object imp=[Object] 'SYNTAX' mibType 'ACCESS' ID 'STATUS' ID
 ('DESCRIPTION' STRING)?
 ('REFERENCE' STRING)?
 ('INDEX' '{' mibType (',' mibType)* '}')?
 ('DEFVAL' '{' INT | STRING '}')?
 value=OidValue;
Currently the auto-completion showed up as :


When following scope restriction code is applied:


MibScopeProvider.xtend
 def IScope scope_Identifier_imp(Identifier id, EReference ref) {
  Scopes::scopeFor(EcoreUtil2::getAllContentsOfType(id.eContainer as Definition,
   com.ravi.mib.xtext.mib.Object).filter[it.name == "OBJECT-TYPE"])
 }
The auto-complete still lists all Objects. However, upon choosing other than "OBJECT-TYPE", Xtext highlights it as an error.


Therefore, we are half way done, now need to make sure the auto-completion list is get filtered as well, apparently that is done separately in MibProposalProvider.xtend (This is under xtext generated ui project).

MibProposalProvider.xtend
class MibProposalProvider extends AbstractMibProposalProvider { 
 override completeObjectType_Imp(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
  lookupCrossReference(assignment.terminal as CrossReference, context, acceptor, [(EObjectOrProxy as com.ravi.mib.xtext.mib.Object).name == "OBJECT-TYPE"])
 }
}

Now all works as it should be.

Few clarifications:
  • Should not make "OBJECT-TYPE" directly as keyword in Xtext as this is used as import. Sure, we can look for a way to overcome this i.e accepting as identifier or keyword based on context, however "OBJECT-TYPE" is rightfully just a macro and not a keyword in ASN.1 (Mib syntax is based on this). Therefore, I prefer to leave it as identifier.
  • I am not sure why auto-completion options for OidValue's parent works without the need to create similiar completeOidValue_parent() method. Hope someone can enlighten me on this.
  • Notice that in this round in method "scope_Identifier_imp", I have used "Scopes::scopeFor(...)" instead of  "new SimpleScope(Scopes::scopedElementsFor(...)". The latter gives us access to EObjectDescription (see also scopedElementsFor() with custom function argument to compute element name). However, for our case - no name customization is done, former is ideal.

No comments:

Post a Comment