public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            Logger.Exec(pguidCmdGroup, nCmdID);
            if (VsShellUtilities.IsInAutomationFunction(Provider.ServiceProvider))
            {
                return(NextCmdHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }

            uint commandID = nCmdID;
            char typedChar = char.MinValue;

            //make sure the input is a char before getting it
            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }

            while (true)
            {
                //check for a commit character
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                    nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||
                    (char.IsWhiteSpace(typedChar) ||
                     JavaSessionCompletions.AutocompleteCommitChars.Contains(typedChar)))
                {
                    if (CompletionSession != null && !CompletionSession.IsDismissed)
                    {
                        if (CompletionSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                        {
                            // Only commit selection if typedChar is not part of the current selection. This will allow typing . when autocompleting package names without closing ACL
                            if (CompletionSession.SelectedCompletionSet.SelectionStatus.Completion.InsertionText.Contains(typedChar))
                            {
                                break;
                            }

                            int adjustCursor = 0;
                            if (CompletionSession.SelectedCompletionSet.SelectionStatus.Completion.InsertionText.EndsWith(")")) // Eclipse returns functions already appended with (); we'll fix up cursor position post insertion
                            {
                                adjustCursor = -1;
                            }

                            JavaSessionCompletions sessionCompletions = null;
                            if (CompletionSession.Properties.TryGetProperty <JavaSessionCompletions>(typeof(JavaSessionCompletions), out sessionCompletions))
                            {
                                sessionCompletions.Commit(CompletionSession, typedChar);
                            }

                            if (adjustCursor != 0)
                            {
                                TextView.Caret.MoveTo(TextView.Caret.Position.BufferPosition.Add(adjustCursor));
                                if (SignatureSession != null)
                                {
                                    SignatureSession.Dismiss();
                                }
                                TriggerSignatureHelp();
                            }

                            Telemetry.Client.Get().TrackTrace(String.Format("ACL Session completed on nCMDID = {0}; typedChar = {1}; adjustCursor = {2}", nCmdID, typedChar, adjustCursor));

                            if (typedChar == char.MinValue || (typedChar == '(' && adjustCursor != 0))
                            {
                                return(VSConstants.S_OK); // don't add the character to the buffer if it's an ENTER, TAB or a open-paran (in the case of a method call)
                            }
                        }
                        else
                        {
                            // If no selection, dismiss the session
                            CompletionSession.Dismiss();

                            Telemetry.Client.Get().TrackTrace(String.Format("ACL Session dismissed on nCMDID = {0}; typedChar = {1}", nCmdID, typedChar));
                        }
                    }
                }
                break;
            }

            // Update param help?
            if (commandID == (uint)VSConstants.VSStd2KCmdID.LEFT)
            {
                if (SignatureSession != null)
                {
                    UpdateCurrentParameter(TextView.Caret.Position.BufferPosition.Position - 1);
                }
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.RIGHT)
            {
                if (SignatureSession != null)
                {
                    UpdateCurrentParameter(TextView.Caret.Position.BufferPosition.Position + 1);
                }
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE)
            {
                if (SignatureSession != null)
                {
                    SnapshotPoint?caretPoint = TextView.Caret.Position.Point.GetPoint(
                        textBuffer => (!textBuffer.ContentType.IsOfType("projection")),
                        PositionAffinity.Predecessor);
                    if (caretPoint.HasValue && caretPoint.Value.Position != 0)
                    {
                        var deleting = TextView.TextSnapshot.GetText(caretPoint.Value.Position - 1, 1).First();
                        if (JavaSignatureHelpSessionSignatures.ParamHelpReevaluateTriggers.Contains(deleting))
                        {
                            UpdateCurrentParameter(caretPoint.Value.Position - 1);
                        }
                        else if (JavaSignatureHelpSessionSignatures.ParamHelpTriggers.Contains(deleting))
                        {
                            SignatureSession.Dismiss();
                            // TODO: May need to launch the nested param help
                        }
                    }
                }
            }

            if (commandID == (uint)VSConstants.VSStd97CmdID.GotoDefn)
            {
                SnapshotPoint?caretPoint = TextView.Caret.Position.Point.GetPoint(
                    textBuffer => (!textBuffer.ContentType.IsOfType("projection")),
                    PositionAffinity.Predecessor);
                if (caretPoint.HasValue && caretPoint.Value.Position != 0)
                {
                    var fireAndForgetTask = new JavaGotoDefinition(TextView, Provider, caretPoint.Value).Run(Provider.EditorFactory);
                }
                return(VSConstants.S_OK);
            }

            // Pass along the command so the char is added to the buffer
            int  retVal  = NextCmdHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            bool handled = false;

            // Trigger Param help?
            if (JavaSignatureHelpSessionSignatures.ParamHelpTriggers.Contains(typedChar) ||
                commandID == (uint)VSConstants.VSStd2KCmdID.PARAMINFO)
            {
                if (SignatureSession != null)
                {
                    SignatureSession.Dismiss();
                }
                TriggerSignatureHelp();

                Telemetry.Client.Get().TrackTrace(String.Format("ParamHelp Session started on nCMDID = {0}; typedChar = {1}", VSConstants.VSStd2KCmdID.PARAMINFO.ToString(), typedChar));
            }
            // Comma found while typing -> update paramhelp
            else if (JavaSignatureHelpSessionSignatures.ParamHelpReevaluateTriggers.Contains(typedChar))
            {
                if (SignatureSession != null)
                {
                    UpdateCurrentParameter();
                }
            }
            // End of param help?
            else if (JavaSignatureHelpSessionSignatures.ParamHelpEndTrigger.Contains(typedChar))
            {
                if (SignatureSession != null)
                {
                    SignatureSession.Dismiss();
                    TriggerSignatureHelp(); // Just in case there is a nested call

                    Telemetry.Client.Get().TrackTrace(String.Format("ParamHelp Session ended and restarted on nCMDID = {0}; typedChar = {1}", commandID, typedChar));
                }
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.HOME ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.BOL ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.BOL_EXT ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.END ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.WORDPREV ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.WORDPREV_EXT ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETEWORDLEFT)
            {
                if (SignatureSession != null)
                {
                    SignatureSession.Dismiss();

                    Telemetry.Client.Get().TrackTrace(String.Format("ParamHelp Session ended on nCMDID = {0}; typedChar = {1}", commandID, typedChar));
                }
            }

            // Trigger autocomplete?
            if (JavaSessionCompletions.AutocompleteTriggers.Contains(typedChar))
            {
                if (CompletionSession == null || CompletionSession.IsDismissed)
                {
                    // If there is no active session, begin one
                    TriggerCompletion();
                    Telemetry.Client.Get().TrackTrace(String.Format("ACL Session started on nCMDID = {0}; typedChar = {1}", commandID, typedChar));
                }
                else
                {
                    CompletionSession.SelectedCompletionSet.SelectBestMatch();
                }
                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.AUTOCOMPLETE)
            {
                if (CompletionSession != null)
                {
                    CompletionSession.Dismiss();
                }

                TriggerCompletion();
                Telemetry.Client.Get().TrackTrace(String.Format("ACL Session started on nCMDID = {0}; typedChar = {1}", commandID, typedChar));

                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                // Redo the filter if there is a deletion
                if (CompletionSession != null && !CompletionSession.IsDismissed)
                {
                    CompletionSession.SelectedCompletionSet.SelectBestMatch();
                }
                handled = true;
            }
            // For any other char, we update the list if a session is already started
            else if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar))
            {
                if (CompletionSession != null && !CompletionSession.IsDismissed)
                {
                    CompletionSession.SelectedCompletionSet.SelectBestMatch();
                }
                handled = true;
            }

            if (handled)
            {
                return(VSConstants.S_OK);
            }
            return(retVal);
        }
Exemplo n.º 2
0
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            Logger.Exec(pguidCmdGroup, nCmdID);
            if (VsShellUtilities.IsInAutomationFunction(Provider.ServiceProvider))
            {
                return NextCmdHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            }

            uint commandID = nCmdID;
            char typedChar = char.MinValue;
            //make sure the input is a char before getting it 
            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            }

            while (true)
            {
                //check for a commit character 
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN ||
                    nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||
                    (char.IsWhiteSpace(typedChar) ||
                    JavaSessionCompletions.AutocompleteCommitChars.Contains(typedChar)))
                {
                    if (CompletionSession != null && !CompletionSession.IsDismissed)
                    {
                        if (CompletionSession.SelectedCompletionSet.SelectionStatus.IsSelected)
                        {
                            // Only commit selection if typedChar is not part of the current selection. This will allow typing . when autocompleting package names without closing ACL
                            if (CompletionSession.SelectedCompletionSet.SelectionStatus.Completion.InsertionText.Contains(typedChar))
                                break;
                        
                            int adjustCursor = 0;
                            if (CompletionSession.SelectedCompletionSet.SelectionStatus.Completion.InsertionText.EndsWith(")")) // Eclipse returns functions already appended with (); we'll fix up cursor position post insertion
                                adjustCursor = -1;

                            JavaSessionCompletions sessionCompletions = null;
                            if (CompletionSession.Properties.TryGetProperty<JavaSessionCompletions>(typeof(JavaSessionCompletions), out sessionCompletions))
                            {
                                sessionCompletions.Commit(CompletionSession, typedChar);
                            }

                            if (adjustCursor != 0)
                            {
                                TextView.Caret.MoveTo(TextView.Caret.Position.BufferPosition.Add(adjustCursor));
                                if (SignatureSession != null)
                                    SignatureSession.Dismiss();
                                TriggerSignatureHelp();
                            }

                            Telemetry.Client.Get().TrackTrace(String.Format("ACL Session completed on nCMDID = {0}; typedChar = {1}; adjustCursor = {2}", nCmdID, typedChar, adjustCursor));

                            if (typedChar == char.MinValue || (typedChar == '(' && adjustCursor != 0))
                                return VSConstants.S_OK; // don't add the character to the buffer if it's an ENTER, TAB or a open-paran (in the case of a method call)
                        }
                        else
                        {
                            // If no selection, dismiss the session
                            CompletionSession.Dismiss();

                            Telemetry.Client.Get().TrackTrace(String.Format("ACL Session dismissed on nCMDID = {0}; typedChar = {1}", nCmdID, typedChar));
                        }
                    }
                }
                break;
            }

            // Update param help?
            if (commandID == (uint)VSConstants.VSStd2KCmdID.LEFT)
            {
                if (SignatureSession != null)
                    UpdateCurrentParameter(TextView.Caret.Position.BufferPosition.Position - 1);
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.RIGHT)
            {
                if (SignatureSession != null)
                    UpdateCurrentParameter(TextView.Caret.Position.BufferPosition.Position + 1);
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE)
            {
                if (SignatureSession != null)
                {
                    SnapshotPoint? caretPoint = TextView.Caret.Position.Point.GetPoint(
                                                    textBuffer => (!textBuffer.ContentType.IsOfType("projection")),
                                                    PositionAffinity.Predecessor);
                    if (caretPoint.HasValue && caretPoint.Value.Position != 0)
                    {
                        var deleting = TextView.TextSnapshot.GetText(caretPoint.Value.Position - 1, 1).First();
                        if (JavaSignatureHelpSessionSignatures.ParamHelpReevaluateTriggers.Contains(deleting))
                        {
                            UpdateCurrentParameter(caretPoint.Value.Position - 1);
                        }
                        else if (JavaSignatureHelpSessionSignatures.ParamHelpTriggers.Contains(deleting))
                        {
                            SignatureSession.Dismiss();
                            // TODO: May need to launch the nested param help 
                        }
                    }
                }
            }

            if (commandID == (uint)VSConstants.VSStd97CmdID.GotoDefn)
            {
                SnapshotPoint? caretPoint = TextView.Caret.Position.Point.GetPoint(
                                                textBuffer => (!textBuffer.ContentType.IsOfType("projection")),
                                                PositionAffinity.Predecessor);
                if (caretPoint.HasValue && caretPoint.Value.Position != 0)
                {
                    var fireAndForgetTask = new JavaGotoDefinition(TextView, Provider, caretPoint.Value).Run(Provider.EditorFactory);
                }
                return VSConstants.S_OK;
            }

            // Pass along the command so the char is added to the buffer
            int retVal = NextCmdHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
            bool handled = false;

            // Trigger Param help?
            if (JavaSignatureHelpSessionSignatures.ParamHelpTriggers.Contains(typedChar) ||
                commandID == (uint)VSConstants.VSStd2KCmdID.PARAMINFO)
            {
                if (SignatureSession != null)
                    SignatureSession.Dismiss();
                TriggerSignatureHelp();

                Telemetry.Client.Get().TrackTrace(String.Format("ParamHelp Session started on nCMDID = {0}; typedChar = {1}", VSConstants.VSStd2KCmdID.PARAMINFO.ToString(), typedChar));
            }
            // Comma found while typing -> update paramhelp
            else if (JavaSignatureHelpSessionSignatures.ParamHelpReevaluateTriggers.Contains(typedChar))
            {
                if (SignatureSession != null)
                    UpdateCurrentParameter();
            }
            // End of param help?
            else if (JavaSignatureHelpSessionSignatures.ParamHelpEndTrigger.Contains(typedChar))
            {
                if (SignatureSession != null)
                {
                    SignatureSession.Dismiss();
                    TriggerSignatureHelp(); // Just in case there is a nested call

                    Telemetry.Client.Get().TrackTrace(String.Format("ParamHelp Session ended and restarted on nCMDID = {0}; typedChar = {1}", commandID, typedChar));
                }
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.HOME ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.BOL ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.BOL_EXT ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.END ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.WORDPREV ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.WORDPREV_EXT ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETEWORDLEFT)
            {
                if (SignatureSession != null)
                {
                    SignatureSession.Dismiss();
                
                    Telemetry.Client.Get().TrackTrace(String.Format("ParamHelp Session ended on nCMDID = {0}; typedChar = {1}", commandID, typedChar));
                }
            }

            // Trigger autocomplete?
            if (JavaSessionCompletions.AutocompleteTriggers.Contains(typedChar))
            {
                if (CompletionSession == null || CompletionSession.IsDismissed)
                {
                    // If there is no active session, begin one
                    TriggerCompletion();
                    Telemetry.Client.Get().TrackTrace(String.Format("ACL Session started on nCMDID = {0}; typedChar = {1}", commandID, typedChar));
                }
                else
                    CompletionSession.SelectedCompletionSet.SelectBestMatch();
                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.COMPLETEWORD ||
                commandID == (uint)VSConstants.VSStd2KCmdID.AUTOCOMPLETE)
            {
                if (CompletionSession != null)
                    CompletionSession.Dismiss();

                TriggerCompletion();
                Telemetry.Client.Get().TrackTrace(String.Format("ACL Session started on nCMDID = {0}; typedChar = {1}", commandID, typedChar));

                handled = true;
            }
            else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE ||
                     commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
            {
                // Redo the filter if there is a deletion
                if (CompletionSession != null && !CompletionSession.IsDismissed)
                    CompletionSession.SelectedCompletionSet.SelectBestMatch();
                handled = true;
            }
            // For any other char, we update the list if a session is already started
            else if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar))
            {
                if (CompletionSession != null && !CompletionSession.IsDismissed)
                    CompletionSession.SelectedCompletionSet.SelectBestMatch();
                handled = true;
            }

            if (handled)
                return VSConstants.S_OK;
            return retVal;
        }