示例#1
0
        internal int ComputeCurrentParameter(ITextSnapshot snapshot, AstRoot ast, int position)
        {
            ParameterInfo parameterInfo = SignatureHelp.GetParametersInfoFromBuffer(ast, snapshot, position);
            int           index         = 0;

            if (parameterInfo != null)
            {
                index = parameterInfo.ParameterIndex;
                if (parameterInfo.NamedParameter)
                {
                    // A function f <- function(foo, bar) is said to have formal parameters "foo" and "bar",
                    // and the call f(foo=3, ba=13) is said to have (actual) arguments "foo" and "ba".
                    // R first matches all arguments that have exactly the same name as a formal parameter.
                    // Two identical argument names cause an error. Then, R matches any argument names that
                    // partially matches a(yet unmatched) formal parameter. But if two argument names partially
                    // match the same formal parameter, that also causes an error. Also, it only matches
                    // formal parameters before ... So formal parameters after ... must be specified using
                    // their full names. Then the unnamed arguments are matched in positional order to
                    // the remaining formal arguments.

                    int argumentIndexInSignature = _signatureInfo.GetArgumentIndex(parameterInfo.ParameterName, REditorSettings.PartialArgumentNameMatch);
                    if (argumentIndexInSignature >= 0)
                    {
                        index = argumentIndexInSignature;
                    }
                }
            }
            return(index);
        }
示例#2
0
        /// <summary>
        /// Determines if current caret position is in the same function
        /// argument list as before or is it a different one and signature
        /// help session should be dismissed and re-triggered. This is helpful
        /// when user types nested function calls such as 'a(b(c(...), d(...)))'
        /// </summary>
        public static bool IsSameSignatureContext(ITextView textView, ITextBuffer subjectBuffer)
        {
            ISignatureHelpBroker signatureBroker = EditorShell.Current.ExportProvider.GetExportedValue <ISignatureHelpBroker>();
            var sessions = signatureBroker.GetSessions(textView);

            Debug.Assert(sessions.Count < 2);
            if (sessions.Count == 1)
            {
                IFunctionInfo sessionFunctionInfo = null;
                sessions[0].Properties.TryGetProperty <IFunctionInfo>("functionInfo", out sessionFunctionInfo);

                if (sessionFunctionInfo != null)
                {
                    try {
                        IREditorDocument document = REditorDocument.FromTextBuffer(textView.TextBuffer);
                        document.EditorTree.EnsureTreeReady();

                        ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer(
                            document.EditorTree.AstRoot, subjectBuffer.CurrentSnapshot,
                            textView.Caret.Position.BufferPosition);

                        return(parametersInfo != null && parametersInfo.FunctionName == sessionFunctionInfo.Name);
                    } catch (Exception) { }
                }
            }

            return(false);
        }
示例#3
0
        public bool AugmentSignatureHelpSession(ISignatureHelpSession session, IList <ISignature> signatures, AstRoot ast, Action <object> triggerSession)
        {
            ITextSnapshot snapshot = _textBuffer.CurrentSnapshot;
            int           position = session.GetTriggerPoint(_textBuffer).GetPosition(snapshot);

            // Retrieve parameter positions from the current text buffer snapshot
            ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer(ast, snapshot, position);

            if (parametersInfo != null)
            {
                position = Math.Min(parametersInfo.SignatureEnd, position);
                int start = Math.Min(position, snapshot.Length);
                int end   = Math.Min(parametersInfo.SignatureEnd, snapshot.Length);

                ITrackingSpan applicableToSpan = snapshot.CreateTrackingSpan(Span.FromBounds(start, end), SpanTrackingMode.EdgeInclusive);

                // Get collection of function signatures from documentation (parsed RD file)
                IFunctionInfo functionInfo = FunctionIndex.GetFunctionInfo(parametersInfo.FunctionName, triggerSession, session.TextView);
                if (functionInfo != null && functionInfo.Signatures != null)
                {
                    foreach (ISignatureInfo signatureInfo in functionInfo.Signatures)
                    {
                        ISignature signature = CreateSignature(session, functionInfo, signatureInfo, applicableToSpan, ast, position);
                        signatures.Add(signature);
                    }

                    session.Properties["functionInfo"] = functionInfo;
                    return(true);
                }
            }

            return(false);
        }
示例#4
0
 private void UpdateCurrentParameter()
 {
     if (SubjectBuffer != null && TextView != null)
     {
         IREditorDocument document = REditorDocument.TryFromTextBuffer(SubjectBuffer);
         if (document != null)
         {
             SnapshotPoint?p = REditorDocument.MapCaretPositionFromView(TextView);
             if (p.HasValue)
             {
                 document.EditorTree.InvokeWhenReady((o) => {
                     if (TextView != null)
                     {
                         // Session is still active
                         p = REditorDocument.MapCaretPositionFromView(TextView);
                         if (p.HasValue)
                         {
                             ComputeCurrentParameter(document.EditorTree.AstRoot, p.Value.Position);
                         }
                     }
                 }, null, this.GetType());
             }
             else
             {
                 SignatureHelp.DismissSession(TextView);
             }
         }
     }
 }
 private void TriggerSignatureHelp(object o, string packageName)
 {
     _packageName = packageName;
     if (o != null && packageName != null)
     {
         var session = o as ISignatureHelpSession;
         SignatureHelp.TriggerSignatureHelp(session.TextView, _shell);
     }
 }
        private int GetCurrentParameterIndex(SignatureHelp sh, IParameter parameter) {
            for (int i = 0; i < sh.Parameters.Count; i++) {
                if (sh.Parameters[i] == parameter) {
                    return i;
                }
            }

            return -1;
        }
        public bool AugmentSignatureHelpSession(ISignatureHelpSession session, IList <ISignature> signatures, AstRoot ast, Action <object, string> triggerSession, string packageName)
        {
            ITextSnapshot snapshot = _textBuffer.CurrentSnapshot;
            int           position = session.GetTriggerPoint(_textBuffer).GetPosition(snapshot);

            // Retrieve parameter positions from the current text buffer snapshot
            ParameterInfo parametersInfo = SignatureHelp.GetParametersInfoFromBuffer(ast, snapshot, position);

            if (parametersInfo != null)
            {
                position = Math.Min(parametersInfo.SignatureEnd, position);
                int start = Math.Min(position, snapshot.Length);
                int end   = Math.Min(parametersInfo.SignatureEnd, snapshot.Length);

                ITrackingSpan applicableToSpan = snapshot.CreateTrackingSpan(Span.FromBounds(start, end), SpanTrackingMode.EdgeInclusive);
                IFunctionInfo functionInfo     = null;

                // First try user-defined function
                if (string.IsNullOrEmpty(parametersInfo.PackageName))
                {
                    functionInfo = ast.GetUserFunctionInfo(parametersInfo.FunctionName, position);
                }
                else
                {
                    packageName = parametersInfo.PackageName;
                }

                if (functionInfo == null)
                {
                    var functionIndex = _shell.ExportProvider.GetExportedValue <IFunctionIndex>();
                    // Then try package functions
                    packageName  = packageName ?? _packageName;
                    _packageName = null;
                    // Get collection of function signatures from documentation (parsed RD file)
                    functionInfo = functionIndex.GetFunctionInfo(parametersInfo.FunctionName, packageName, triggerSession, session);
                }

                if (functionInfo != null && functionInfo.Signatures != null)
                {
                    foreach (ISignatureInfo signatureInfo in functionInfo.Signatures)
                    {
                        ISignature signature = CreateSignature(session, parametersInfo.FunctionName, functionInfo, signatureInfo, applicableToSpan, ast, position);
                        signatures.Add(signature);
                    }

                    session.Properties["functionInfo"] = functionInfo;
                    return(true);
                }
            }

            return(false);
        }
示例#8
0
 private void OnCaretPositionChanged(object sender, CaretPositionChangedEventArgs e)
 {
     if (TextView != null)
     {
         if (SignatureHelper.IsSameSignatureContext(TextView, SubjectBuffer))
         {
             UpdateCurrentParameter();
         }
         else
         {
             SignatureHelp.DismissSession(TextView, retrigger: true);
         }
     }
     else
     {
         e.TextView.Caret.PositionChanged -= OnCaretPositionChanged;
     }
 }
示例#9
0
        protected virtual void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
        {
            if (Session != null && e.Changes.Count > 0)
            {
                int start, oldLength, newLength;
                TextUtility.CombineChanges(e, out start, out oldLength, out newLength);

                int position = start + newLength;
                if (position < _initialPosition)
                {
                    SignatureHelp.DismissSession(TextView);
                }
                else
                {
                    UpdateCurrentParameter();
                }
            }
        }
示例#10
0
        private ISignature CreateSignature(ISignatureHelpSession session,
                                           IFunctionInfo functionInfo, ISignatureInfo signatureInfo,
                                           ITrackingSpan span, AstRoot ast, int position)
        {
            SignatureHelp     sig       = new SignatureHelp(session, _textBuffer, functionInfo.Name, string.Empty, signatureInfo);
            List <IParameter> paramList = new List <IParameter>();

            // Locus points in the pretty printed signature (the one displayed in the tooltip)
            var    locusPoints     = new List <int>();
            string signatureString = signatureInfo.GetSignatureString(locusPoints);

            sig.Content          = signatureString;
            sig.ApplicableToSpan = span;

            sig.Documentation = functionInfo.Description?.Wrap(Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length));

            Debug.Assert(locusPoints.Count == signatureInfo.Arguments.Count + 1);
            for (int i = 0; i < signatureInfo.Arguments.Count; i++)
            {
                IArgumentInfo p = signatureInfo.Arguments[i];
                if (p != null)
                {
                    int locusStart  = locusPoints[i];
                    int locusLength = locusPoints[i + 1] - locusStart;

                    Debug.Assert(locusLength >= 0);
                    Span locus = new Span(locusStart, locusLength);

                    /// VS may end showing very long tooltip so we need to keep
                    /// description reasonably short: typically about
                    /// same length as the function signature.
                    paramList.Add(
                        new SignatureParameter(
                            p.Description.Wrap(
                                Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length)),
                            locus, locus, p.Name, sig));
                }
            }

            sig.Parameters = new ReadOnlyCollection <IParameter>(paramList);
            sig.ComputeCurrentParameter(ast, position);

            return(sig);
        }
示例#11
0
 private void UpdateCurrentParameter()
 {
     if (SubjectBuffer != null && TextView != null)
     {
         IREditorDocument document = REditorDocument.TryFromTextBuffer(SubjectBuffer);
         if (document != null)
         {
             SnapshotPoint?p = REditorDocument.MapCaretPositionFromView(TextView);
             if (p.HasValue)
             {
                 document.EditorTree.EnsureTreeReady();
                 ComputeCurrentParameter(document.EditorTree.AstRoot, p.Value.Position);
             }
             else
             {
                 SignatureHelp.DismissSession(TextView);
             }
         }
     }
 }
示例#12
0
 private void TriggerSignatureHelp(object o)
 {
     SignatureHelp.TriggerSignatureHelp(o as ITextView);
 }
示例#13
0
        private ISignature CreateSignature(ISignatureHelpSession session,
                                       string functionName, IFunctionInfo functionInfo, ISignatureInfo signatureInfo,
                                       ITrackingSpan span, AstRoot ast, int position) {
            SignatureHelp sig = new SignatureHelp(session, _textBuffer, functionName, string.Empty, signatureInfo, _shell);
            List<IParameter> paramList = new List<IParameter>();

            // Locus points in the pretty printed signature (the one displayed in the tooltip)
            var locusPoints = new List<int>();
            string signatureString = signatureInfo.GetSignatureString(functionName, locusPoints);
            sig.Content = signatureString;
            sig.ApplicableToSpan = span;

            sig.Documentation = functionInfo.Description?.Wrap(Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length));

            Debug.Assert(locusPoints.Count == signatureInfo.Arguments.Count + 1);
            for (int i = 0; i < signatureInfo.Arguments.Count; i++) {
                IArgumentInfo p = signatureInfo.Arguments[i];
                if (p != null) {
                    int locusStart = locusPoints[i];
                    int locusLength = locusPoints[i + 1] - locusStart;

                    Debug.Assert(locusLength >= 0);
                    Span locus = new Span(locusStart, locusLength);

                    /// VS may end showing very long tooltip so we need to keep 
                    /// description reasonably short: typically about
                    /// same length as the function signature.
                    paramList.Add(
                        new SignatureParameter(
                            p.Description.Wrap(
                                Math.Min(SignatureInfo.MaxSignatureLength, sig.Content.Length)),
                                locus, locus, p.Name, sig));
                }
            }

            sig.Parameters = new ReadOnlyCollection<IParameter>(paramList);
            sig.ComputeCurrentParameter(ast, position);

            return sig;
        }