Add tutorial for adding more completion types and added new completion
[mono.git] / mcs / docs / compiler.txt
index 6971c437236b75b5b885abdde28ef2385b739c8c..e99d5d34e013befc7568d52da4b8846a6a91d7bc 100755 (executable)
          
          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.
+       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.
 
        So for example if the user type "T" and the completion is
        "ToString" we return "oString".
 
+** Enhancing Completion
+
+       Code completion is a process that will be curated over time.  
+       Just like producing good error reports or warnings is an
+       iterative process to find a good balance, the code completion
+       engine in the compiler will require tuning to find the right
+       balance for the end user. 
+
+       This section explains the basic process by which you can
+       improve the code completion by using a real life sample.
+
+       Once you add the GENERATE_COMPLETION token to your grammar
+       rule, chances are, you will need to alter the grammar to
+       support COMPLETE_COMPLETION all the way up to the toplevel
+       production.
+
+       To debug this, you will want to try the completion with either
+       a sample program or with the `csharp' tool.
+
+       I use this setup:
+
+       $ csharp -v -v
+
+       This will turn on the parser debugging output and will
+       generate a lot of data when parsing its input.
+
+       To start with a new completion scheme, type your C# code and
+       then hit the tab key to trigger the completion engine.  In the
+       generated output you will want to look for the first time that
+       the parser got the GENERATE_COMPLETION token, it will look
+       like this:
+
+       lex     state 414       reading GENERATE_COMPLETION value {interactive}(1,35):
+
+       The first word `lex' indicates that the parser called the
+       lexer at state 414 (more on this in a second) and it got back
+       from the lexer the token GENERATE_COMPLETION.   If this is a
+       kind of completion chances are, you will get an error
+       immediately as the rules at that point do not know how to cope
+       with the stream of COMPLETE_COMPLETION tokens that will
+       follow, they will look like this:
+
+       error   syntax error
+       pop     state 414       on error
+       pop     state 805       on error
+       pop     state 628       on error
+       pop     state 417       on error
+       
+       The first line means that the parser has entered the error
+       state and will pop states until it can find a production that
+       can deal with the error.   At that point an error message will
+       be displayed.
+
+       Open the file `y.output' which describes the parser states
+       generated by jay and search for the state that was reported
+       previously in `lex' that got the GENERATE_COMPLETION:
+
+       state 414
+               object_or_collection_initializer : OPEN_BRACE . opt_member_initializer_list CLOSE_BRACE  (444)
+               object_or_collection_initializer : OPEN_BRACE . member_initializer_list COMMA CLOSE_BRACE  (445)
+               opt_member_initializer_list : .  (446)
+       
+       We now know that the parser was in the middle of parsing an
+       `object_or_collection_initializer' and had alread seen the
+       OPEN_BRACE token.
+
+       The `.' after OPEN_BRACE indicates the current state of the
+       parser, and this is where our parser got the
+       GENERATE_COMPLETION token.   As you can see from the three
+       rules in this sample, support for GENERATE_COMPLETION did not
+       exist.
+
+       So we must edit the grammar to add a production for this case,
+       I made the code look like this:
+
+       member_initializer
+               [...]
+               | GENERATE_COMPLETION 
+                 {
+                       LocatedToken lt = $1 as LocatedToken;
+                       $$ = new CompletionElementInitializer (GetLocation ($1));
+                 }
+               [...]
+
+       This new production creates the class
+       CompletionElementInitializer and returns this as the value for
+       this.   The following is a trivial implementation that always
+       returns "foo" and "bar" as the two completions and it
+       illustrates how things work:
+
+       public class CompletionElementInitializer : CompletingExpression {
+               public CompletionElementInitializer (Location l)
+               {
+                       this.loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       string [] = new string [] { "foo", "bar" };
+                       throw new CompletionResult ("", result);
+               }
+
+               // 
+               // You should implement CloneTo if your CompletingExpression
+               // keeps copies to Statements or Expressions.   CloneTo
+               // is used by the lambda engine, so you should always
+               // implement this
+               //
+               protected override void CloneTo (CloneContext clonectx, Expression t)
+               {
+                       // We do not keep references to anything interesting
+                       // so cloning is an empty operation.
+               }
+       }
+       
+
+       We then rebuild our compiler:
+
+       (cd mcs/; make cs-parser.jay)
+       (cd tools/csharplib; make install)
+
+       And re-run csharp:
+
+       (cd tools/csharp; csharp -v -v)
+
+       Chances are, you will get another error, but this time it will
+       not be for the GENERATE_COMPLETION, we already handled that
+       one.   This time it will be for COMPLETE_COMPLETION.  
+
+       The remaining of the process is iterative: you need to locate
+       the state where this error happens.   It will look like this:
+
+       lex     state 623       reading COMPLETE_COMPLETION     value {interactive}(1,35):
+       error   syntax error
+       
+       And make sure that the state can handle at this point a
+       COMPLETE_COMPLETION.   When receiving COMPLETE_COMPLETION the
+       parser needs to complete constructing the parse tree, so
+       productions that handle COMPLETE_COMPLETION need to wrap
+       things up with whatever data they have available and just make
+       it so that the parser can complete.
+
+       To avoid rule duplication you can use the
+       opt_COMPLETE_COMPLETION production and append it to an
+       existing production:
+
+       foo : bar opt_COMPLETE_COMPLETION {
+           ..
+       }
+
 * Miscellaneous
 
 ** Error Processing.