[Mono-dev] csharp tab completion.

Miguel de Icaza miguel at novell.com
Thu Mar 12 13:01:38 EDT 2009


Hello,

    A follow up: this contains a cleaned up version of the patch, a few
old hacks have been removed, and the sample now actually builds.


> Hello,
> 
>     I cooked this patch on my last trip and just got it polished enough
> that it is worth posting to the mailing list.
> 
>     A feature frequently requested is for the `csharp' interactive shell
> is to provide bash-like tab completion so that you can quickly explore
> the API without having to look things up.    The getline.cs library
> already provided a mechanism for doing tab completion, but the support
> was not implemented.
> 
>     The challenge was to reuse the current gmcs parser without having to
> dramatically modify it and still provide completions.   The support
> works like this.
> 
>     The parser and tokenizer work together so that the tokenizer upon
> reaching the end of the input generates the following tokens:
> GENERATE_COMPLETION followed by as many COMPLETE_COMPLETION token and
> finally the EOF token.
> 
>     GENERATE_COMPLETION needs to be handled in every production where
> the user is likely to press the TAB key in the shell (or in the future
> the GUI, or an explicit request in an IDE).   COMPLETE_COMPLETION must
> be handled throughout the grammar to provide a way of completing the
> parsed expression.  See below for details. 
> 
>     For the member access case, I have added productions that mirror the
> non-completing productions, for example:
> 
>   primary_expression DOT IDENTIFIER GENERATE_COMPLETION 
>   {
> 	LocatedToken lt = (LocatedToken) $3;
> 	$$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location);
>   }
> 
> This mirrors:
> 
>   primary_expression DOT IDENTIFIER opt_type_argument_list
>   {
> 	LocatedToken lt = (LocatedToken) $3;
> 	$$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location);
>   }
> 
>    The CompletionMemberAccess is a new kind of Mono.CSharp.Expression
> that does the actual lookup.   It internally mimics some of the
> MemberAccess code but has been tuned for this particular use.
> 
>    After this initial token is processed GENERATE_COMPLETION the
> tokenizer will emit COMPLETE_COMPLETION tokens.   This is done to help
> the parser basically produce a valid result from the partial input it
> received.    For example it is able to produce a valid AST from "(x"
> even if no parenthesis has been closed.   This is achieved by sprinkling
> the grammar with productions that can cope with this "winding down"
> token, for example this is what parenthesized_expression looks like now:
> 
> parenthesized_expression
> 	: OPEN_PARENS expression CLOSE_PARENS
> 	  {
> 		$$ = new ParenthesizedExpression ((Expression) $2);
> 	  }
> 	//
> 	// New production
> 	//
> 	| OPEN_PARENS expression COMPLETE_COMPLETION
> 	  {
> 		$$ = new ParenthesizedExpression ((Expression) $2);
> 	  }
> 	;
> 
>     Once we have wrapped up everything we generate the last EOF token.
> 
>     When the AST is complete we actually trigger the regular semantic
> analysis process.   The DoResolve method of each node in our abstract
> syntax tree will compute the result and communicate the possible
> completions by throwing an exception of type CompletionResult.
> 
>     This is the bit that I am not very comfortable with, I had to
> provide both the prefix string and the results to allow the completion
> engine to render things properly.
> 
>     So for example if the user type "T" and the completion is "ToString"
> we return "oString".
> 
>     Attached is the patch for review.
> 
> Future Work:
> 
>     I have only implemented support for completion right now in two
> spots: declared variables and member access, so stuff like foo.<TAB>
> will produce the completions for foo properly and foo.T<TAB> will
> produce the completions for anything in foo that starts with a T.   
> 
>     There are many other places missing (using declarations, type
> parameters for example, and I am sure there are many other opportunities
> missing), I might add those in the future if there is enough interest,
> or even better, you can get yourself started with compiler technology
> and email us patches ;-)
> 
> GSharp:
> 
>     The GUI version perhaps needs to implement this in a GUI-ish way
> when the user presses a dot for example, or when the user presses a
> hotkey.   The GUI version also has the benefit that it can distinguish
> the user pressing tab from the user pasting some text with a tab.
>  
> Miguel
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: auto-complete-csharp-2
Type: text/x-patch
Size: 22409 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20090312/cc347160/attachment.bin 


More information about the Mono-devel-list mailing list