Supporting IntelliSense Parameter Info (Managed Package Framework)

The IntelliSense Parameter Info is a ToolTip that displays the signature of a method as the user types. The ToolTip is shown when the user types the parameter list start character (typically an open parenthesis) for the method parameter list. As each parameter is entered and the parameter separator (typically a comma) is typed, the ToolTip is updated to show the next parameter in bold face.

The managed package framework (MPF) classes provide support for managing the Parameter Info ToolTip, all that is needed is cooperation from the parser in detecting what characters have been typed so far, as well as a list of the method signatures and the associated parameters to search for the method being typed.

Implementation

The IScanner scanner specifies the triggers associated with entering a method signature. Specifically, the trigger value ParameterStart is set when a parameter list start character (typically an open parenthesis) is typed and parsed. This starts the Parameter Info process. When a parameter separator (typically a comma) is typed and parsed, the trigger value ParameterNext is set, which causes the Parameter Info ToolTip to be updated and show the next parameter in bold face. When the parameter list end character (typically a close parenthesis) is typed and parsed, the trigger value ParameterEnd is set.

The ParameterStart trigger value initiates a call to the MethodTip method on the Source class and the MethodTip method, in turn, calls the ParseSource method parser with the parse reason value of MethodTip. The parser determines if the identifier before the parameter list start character is a recognized method name and returns a list of matching method signatures in the AuthoringScope object. If any method signatures were found, the Parameter Info ToolTip is displayed with the first signature in the list. This ToolTip is then updated as more of the signature is typed. When the parameter list end character is typed, the Parameter Info ToolTip is removed from view.

注意

To ensure the Parameter Info ToolTip is properly formatted, you must override the properties on the Methods class to supply the appropriate characters. The base Methods class assumes a C#-style method signature. See the Methods class for details on how this can be done.

Enabling Support for the Parameter Info

You must have the CodeSense registry entry set to 1 to support any IntelliSense operation. This registry entry can be set with a named parameter passed to the ProvideLanguageServiceAttribute user attribute associated with the language package. The language service classes read the value of this registry entry from the EnableCodeSense property on the LanguagePreferences class.

In addition, the ShowCompletion registry entry must be set to 1 to indicate support for the IntelliSense Parameter Info operation. This registry entry is used to set the ParameterInformation property of the LanguagePreferences class. When the ParameterInformation property returns true, the Parameter Info ToolTip can be shown. The ShowCompletion registry entry can be set with a named parameter supplied to the ProvideLanguageServiceAttribute attribute.

Supporting the Parameter Info ToolTip in the Scanner

The scanner must be able to detect the parameter list start and end characters as well as the parameter separator character and set the appropriate TokenTriggers value for each character.

Example

Here is a simplified example of detecting the parameter list characters and setting the appropriate TokenTriggers values for each. Note how the trigger values are combined with the brace match value. This example is for illustrative purposes only and does not reflect how a proper scanner should be written. Ideally, the detection for the parameter list characters occurs only when it is logical for a method to appear at that particular place in the source file. In addition, the next and end characters in the parameter list should set the trigger only if they were preceded by the parameter list start character, which would require tracking a state for entering a parameter list. This example uses brute force and sets the triggers for all characters that match the parameter list delimiters, letting the parser handle the details.

using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;

namespace MyLanguagePackage
{
    public class MyScanner : IScanner
    {
        private const string braces = "()[]{}";
        private const char parameterListStartChar = '(';
        private const char parameterListEndChar   = ')';
        private const char parameterNextChar      = ',';

        private string m_line;   // line of text to parse.
        private int    m_offset; // where next token starts in line.


        public void SetSource(string source, int offset)
        {
            m_line   = source;
            m_offset = offset;
        }

        public bool ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo,
                                                   ref int state)
        {
            bool fFoundToken = GetNextToken(m_offset, tokenInfo, ref state);
            if (fFoundToken)
            {
                m_offset = tokenInfo.EndIndex + 1;
            }
            return fFoundToken;
        }


        private bool GetNextToken(int startIndex, TokenInfo tokenInfo, ref int state)
        {
            bool bFoundToken = false;      // Assume we are done with this line.
            int  index       = startIndex;

            if (index < m_line.Length)
            {
                bFound = true;            // We are not done with this line.
                tokenInfo.StartIndex = index;
                char c = m_line[index];

                if (Char.IsPunctuation(c))
                {
                    tokenInfo.Type     = TokenType.Operator;
                    tokenInfo.Color    = TokenColor.Keyword;
                    tokenInfo.EndIndex = index;
                    if (braces.IndexOf(c) != -1)
                    {
                        tokenInfo.Trigger = TokenTriggers.MatchBraces;
                    }
                    if (c == parameterListStartChar)
                    {
                        tokenInfo.Trigger |= TokenTriggers.ParameterStart;
                    }
                    else if (c == parameterListNextChar)
                    {
                        tokenInfo.Trigger |= TokenTriggers.ParameterNext;
                    else if (c == parameterListEndChar)
                    {
                        tokenInfo.Trigger |= TokenTriggers.ParameterEnd;
                    }
                }
                else if (Char.IsWhitespace(c))
                {
                    do
                    {
                        ++index;
                    }
                    while(index < m_line.Length &&
                          Char.IsWhiteSpace(m_line[index]));
                    tokenInfo.Type     = TokenType.Whitespace;
                    tokenInfo.Color    = TokenColor.Text;
                    tokenInfo.EndIndex = index - 1;
                }
                else
                {
                    do
                    {
                        ++index;
                    }
                    while(index < m_line.Length &&
                          !Char.IsPunctuation(m_line[index]) &&
                          !Char.IsWhiteSpace(m_line[index]));
                    tokenInfo.Type     = TokenType.Identifier;
                    tokenInfo.Color    = TokenColor.Identifier;
                    tokenInfo.EndIndex = index - 1;
                }
            }
            return bFoundToken;
        }
    }
}

Supporting the Parameter Info ToolTip in the Parser

Since the implementation of the parser is entirely up to the developer of the language, only general guidelines can be given here on how to use the AuthoringScope and AuthoringSink classes. The Source class does make some assumptions about what is contained in these two classes at the time the Parameter Info ToolTip is displayed and updated and these assumptions are covered here.

The parser is given the parse reason value of MethodTip when the parameter list start character is typed. The location given in the ParseRequest object is immediately after the parameter list start character. The parser must collect the signatures of all method declarations available at that position and store them in a list in your version of the AuthoringScope object. How this list is implemented is up to you but it must include the method name, method type (or return type), and a list of possible parameters. This list is later searched for the method signature or signatures to display in the Parameter Info ToolTip.

The parser must then parse the line specified by the ParseRequest object to gather the name of the method being entered as well as how far along the user is in typing parameters. This is accomplished by passing the name of the method to the StartName method on the AuthoringSink object and then calling the StartParameters method when the parameter list start character is parsed, calling the NextParameter method when the parameter list next character is parsed, and finally calling the EndParameters method when the parameter list end character is parsed. The results of these method calls are used by the Source class to update the Parameter Info ToolTip appropriately.

Example

Here is a line of text the user might enter. The numbers below the line indicate which step is taken by the parser at that position in the line (assuming parsing moves left to right). The assumption here is that everything before the line has already been parsed for method signatures, including the "myfunc" method signature.

    myfunc("a string",3);
         ^^          ^ ^
         12          3 4

The steps that the parser takes are outlined below:

  1. The parser calls the StartName method on the AuthoringSink object with the text "myfunc".

  2. The parser calls StartParameters on the AuthoringSink object.

  3. The parser calls NextParameter on the AuthoringSink object.

  4. The parser calls EndParameters on the AuthoringSink object.

See Also

Concepts

Language Service Features (Managed Package Framework)