locked
Question on Automatic Completion List in custom Language Service (VS2010 Isolated shell) RRS feed

  • Question

  • Hello,

    I have a custom language service written using the managed package framework (MPF) in a VS2010 isolated shell app.

    I can get the automatic completion list to appear in the editor when ctrl+space is pressed.
    My custom ViewFilter class receives the call to HandlePreExec(..) with the COMPLETEWORD command.
    I guess this subsequently results in a call to the AuthoringScope.GetDeclarations(..) where I populate my list of completion keywords for VS to display.

    However, HandlePreExec(..) with COMPLETEWORD command is called only when I press the Ctrl+Space keys.
    How do I get VS to call HandlePreExec(...) with COMPLETEWORD as soon as I begin typing some characters in the editor ? (I am looking at providing the same behavior as in VS2010)

    Does it have something to do with the GetLanguagePreferences() override in my LanguageService class.
    I have set the LanguagePreferences.AutoListMembers and LanguagePreferences.EnableCodeSense to 'true' in the LanguageService.GetLanguagePreferences(...) overridden method.

    Also in the [ProvideLanguageService] attribute in the package, I have set the following
        [ProvideLanguageService(typeof(MyLanguageService), MyLanguageName, 0,
            CodeSense = true,
            EnableCommenting = true,
            ShowCompletion = true,
            AutoOutlining = true)]
     
    So the question then is:
    How do I get VS to call HandlePreExec(...) with COMPLETEWORD as soon as I begin typing some characters in the editor ?

    Thanks,
    CC

     

    Wednesday, May 5, 2010 5:23 PM

Answers

  • Hello CC. I had the need for this same feature and was able to implement it. You must override the OnCommand method in your source implementation file. 99% of the code is from the Source.cs file in the SDK, with a couple of additions. Here is my whole method. Look for the comment that starts with

    //BSR: Fire word completion for every letter typed

     

       //Here we override OnCommand to get our own behaviors (ie. fire word completion on every character typed)
       //This was copied from Common/Source/CSharp/LanguageService/Source.cs, changes marked with BSR
       public override void OnCommand(IVsTextView textView, VsCommands2K command, char ch)
       {
         if (textView == null || this.LanguageService == null || !this.LanguageService.Preferences.EnableCodeSense)
          return;
    
         bool backward = (command == VsCommands2K.BACKSPACE || command == VsCommands2K.BACKTAB ||
           command == VsCommands2K.LEFT || command == VsCommands2K.LEFT_EXT);
    
         int line, idx;
    
         Microsoft.VisualStudio.NativeMethods.ThrowOnFailure(textView.GetCaretPos(out line, out idx));
    
         TokenInfo info = GetTokenInfo(line, idx);
         TokenTriggers triggerClass = info.Trigger;
    
         //BSR: Fire word completion for every letter typed
         //If a character was typed, and character is a letter, and a completion set is not currently being displayed
         if (command == Microsoft.VisualStudio.VSConstants.VSStd2KCmdID.TYPECHAR && char.IsLetter(ch) && !this.CompletionSet.IsDisplayed)
         {
          //Do not fire completions when typing a comment, number, or "string"
          if (info.Color != TokenColor.Comment && info.Color != TokenColor.Number && info.Color != TokenColor.String)
          {
            //Fire completion
            this.Completion(textView, info, ParseReason.CompleteWord);
            return;
          }
         }
    
         if ((triggerClass & TokenTriggers.MemberSelect) != 0 && (command == VsCommands2K.TYPECHAR))
         {
          ParseReason reason = ((triggerClass & TokenTriggers.MatchBraces) == TokenTriggers.MatchBraces) ? ParseReason.MemberSelectAndHighlightBraces : ParseReason.MemberSelect;
          this.Completion(textView, info, reason);
          return; //BSR: Return needed here otherwise member completion doesn't work when method tips are showing
         }
         else if ((triggerClass & TokenTriggers.MatchBraces) != 0 && this.LanguageService.Preferences.EnableMatchBraces)
         {
          if ((command != VsCommands2K.BACKSPACE) && ((command == VsCommands2K.TYPECHAR) || this.LanguageService.Preferences.EnableMatchBracesAtCaret))
          {
            this.MatchBraces(textView, line, idx, info);
          }
         }
         //displayed & a trigger found
         // todo: This means the method tip disappears if you type "ENTER" 
         // while entering method arguments, which is bad.
         if ((triggerClass & TokenTriggers.MethodTip) != 0 && this.methodData.IsDisplayed)
         {
          if ((triggerClass & TokenTriggers.MethodTip) == TokenTriggers.ParameterNext)
          {
            //this is an optimization
            methodData.AdjustCurrentParameter((backward && idx > 0) ? -1 : +1);
          }
          else
          {
            //this is the general case
            this.MethodTip(textView, line, (backward && idx > 0) ? idx - 1 : idx, info);
          }
         }
         else if ((triggerClass & TokenTriggers.MethodTip) != 0 && (command == VsCommands2K.TYPECHAR) && this.LanguageService.Preferences.ParameterInformation)
         {
          //not displayed & trigger found & character typed & method info enabled
          this.MethodTip(textView, line, idx, info);
         }
         else if (methodData.IsDisplayed)
         {
          //displayed & complex command
          this.MethodTip(textView, line, idx, info);
         }
       }

    • Proposed as answer by bralston Monday, May 10, 2010 9:30 PM
    • Marked as answer by Chao Kuo Thursday, May 13, 2010 2:33 AM
    Monday, May 10, 2010 9:30 PM

All replies

  • Hello, CC

    What’s your editor? Is it the core editor or your custom editor?

    You could execute the AUTOCOMPLETE command using IOleCommandTarget.Exec Method after your keypress. You could use Package.GetGlobalService to get the IOleCommandTarget object to execute the environment command.

    If I misunderstood you, feel free to let me know.

    Thanks

    Chao

    Monday, May 10, 2010 9:52 AM
  • Hello CC. I had the need for this same feature and was able to implement it. You must override the OnCommand method in your source implementation file. 99% of the code is from the Source.cs file in the SDK, with a couple of additions. Here is my whole method. Look for the comment that starts with

    //BSR: Fire word completion for every letter typed

     

       //Here we override OnCommand to get our own behaviors (ie. fire word completion on every character typed)
       //This was copied from Common/Source/CSharp/LanguageService/Source.cs, changes marked with BSR
       public override void OnCommand(IVsTextView textView, VsCommands2K command, char ch)
       {
         if (textView == null || this.LanguageService == null || !this.LanguageService.Preferences.EnableCodeSense)
          return;
    
         bool backward = (command == VsCommands2K.BACKSPACE || command == VsCommands2K.BACKTAB ||
           command == VsCommands2K.LEFT || command == VsCommands2K.LEFT_EXT);
    
         int line, idx;
    
         Microsoft.VisualStudio.NativeMethods.ThrowOnFailure(textView.GetCaretPos(out line, out idx));
    
         TokenInfo info = GetTokenInfo(line, idx);
         TokenTriggers triggerClass = info.Trigger;
    
         //BSR: Fire word completion for every letter typed
         //If a character was typed, and character is a letter, and a completion set is not currently being displayed
         if (command == Microsoft.VisualStudio.VSConstants.VSStd2KCmdID.TYPECHAR && char.IsLetter(ch) && !this.CompletionSet.IsDisplayed)
         {
          //Do not fire completions when typing a comment, number, or "string"
          if (info.Color != TokenColor.Comment && info.Color != TokenColor.Number && info.Color != TokenColor.String)
          {
            //Fire completion
            this.Completion(textView, info, ParseReason.CompleteWord);
            return;
          }
         }
    
         if ((triggerClass & TokenTriggers.MemberSelect) != 0 && (command == VsCommands2K.TYPECHAR))
         {
          ParseReason reason = ((triggerClass & TokenTriggers.MatchBraces) == TokenTriggers.MatchBraces) ? ParseReason.MemberSelectAndHighlightBraces : ParseReason.MemberSelect;
          this.Completion(textView, info, reason);
          return; //BSR: Return needed here otherwise member completion doesn't work when method tips are showing
         }
         else if ((triggerClass & TokenTriggers.MatchBraces) != 0 && this.LanguageService.Preferences.EnableMatchBraces)
         {
          if ((command != VsCommands2K.BACKSPACE) && ((command == VsCommands2K.TYPECHAR) || this.LanguageService.Preferences.EnableMatchBracesAtCaret))
          {
            this.MatchBraces(textView, line, idx, info);
          }
         }
         //displayed & a trigger found
         // todo: This means the method tip disappears if you type "ENTER" 
         // while entering method arguments, which is bad.
         if ((triggerClass & TokenTriggers.MethodTip) != 0 && this.methodData.IsDisplayed)
         {
          if ((triggerClass & TokenTriggers.MethodTip) == TokenTriggers.ParameterNext)
          {
            //this is an optimization
            methodData.AdjustCurrentParameter((backward && idx > 0) ? -1 : +1);
          }
          else
          {
            //this is the general case
            this.MethodTip(textView, line, (backward && idx > 0) ? idx - 1 : idx, info);
          }
         }
         else if ((triggerClass & TokenTriggers.MethodTip) != 0 && (command == VsCommands2K.TYPECHAR) && this.LanguageService.Preferences.ParameterInformation)
         {
          //not displayed & trigger found & character typed & method info enabled
          this.MethodTip(textView, line, idx, info);
         }
         else if (methodData.IsDisplayed)
         {
          //displayed & complex command
          this.MethodTip(textView, line, idx, info);
         }
       }

    • Proposed as answer by bralston Monday, May 10, 2010 9:30 PM
    • Marked as answer by Chao Kuo Thursday, May 13, 2010 2:33 AM
    Monday, May 10, 2010 9:30 PM
  • Hi CC,

    I am also trying to implement the same thing but not able to do so.

    I tried the steps given in the below URL but not able to inculde syntax coloring inside the Isolated IDE...

    http://msdn.microsoft.com/en-us/library/bb165744.aspx

    If possible, please share with me the steps of creating and registering the custom language service pack

    TIA.

    Waiting for your reply.

     

    Thanks,

    Niteesh

    • Edited by NiteeshYadav Thursday, November 24, 2011 1:22 PM
    Thursday, November 24, 2011 1:22 PM