public void Refresh()

in vsintegration/src/FSharp.LanguageService.Base/Source.cs [2374:2481]


        public void Refresh(MethodTipMiscellany_DEPRECATED methodTipMiscellany)
        {
            var wpfTextView = FSharpSourceBase_DEPRECATED.GetWpfTextViewFromVsTextView(textView);
            var ranges = methods.GetParameterRanges();
            Debug.Assert(ranges != null && ranges.Length > 0);

            // Don't do anything for open parens and commas that aren't intrinsic to a method call
            if (!this.displayed && methodTipMiscellany == MethodTipMiscellany_DEPRECATED.JustPressedCloseParen)
            {
                return;  // close paren must never cause it to appear
            }
            if (!this.displayed && methodTipMiscellany == MethodTipMiscellany_DEPRECATED.JustPressedOpenParen)
            {
                // the only good open paren is the start of the first param, don't want to cause a tip to be displayed $here$:  foo(x, $($y+z), w)
                if (!ranges[0].GetSpan(wpfTextView.TextSnapshot).Start.Equals(wpfTextView.Caret.Position.BufferPosition))
                    return;
            }
            if (!this.displayed && methodTipMiscellany == MethodTipMiscellany_DEPRECATED.JustPressedComma)
            {
                // the only good commas will be, interestingly, at the start of the following param span
                // this by virtue of fact that we assume comma is one character after where the previous parameter range ends (and thus the first character of the next range)
                var ok = false;
                for (int i = 1; i < ranges.Length; ++i)
                {
                    if (ranges[i].GetSpan(wpfTextView.TextSnapshot).Start.Equals(wpfTextView.Caret.Position.BufferPosition))
                    {
                        ok = true;
                        break;
                    }
                }
                if (!ok)
                    return;
            }

            // Figure out which parameter we are in based on location of caret within the parse
            var caretPoint = wpfTextView.Caret.Position.BufferPosition;
            var endOfLinePoint = wpfTextView.Caret.ContainingTextViewLine.End;
            bool caretIsAtEndOfLine = caretPoint == endOfLinePoint;
            this.currentParameter = -1;
            for (int i = ranges.Length - 1; i >= 0; --i) // need to traverse backwards, so that "f(1," at end of line sets curParam to 1, not 0
            {
                if (ranges[i].GetSpan(wpfTextView.TextSnapshot).Contains(caretPoint)
                    // ranges are half-open [...), so end-of-line is a special case...
                    || caretIsAtEndOfLine
                       && ranges[i].GetSpan(wpfTextView.TextSnapshot).End == caretPoint
                       && !(i == ranges.Length - 1 && this.methods.IsThereACloseParen())) // ...except on the closing paren (when caret at close paren, should dismiss tip, even if at EOL)
                {
                    this.currentParameter = i;
                    break;
                }
            }
            if (this.currentParameter == -1)
            {
                // a bit of a kludge; if they just backspaced over the last comma and there's no close parenthesis, the caret is just to the right of all the param
                // ranges, but we don't want to dismiss the tip.  so look just left of the caret and see if that would be inside the final param
                if (methodTipMiscellany == MethodTipMiscellany_DEPRECATED.JustPressedBackspace
                    && ranges[ranges.Length - 1].GetSpan(wpfTextView.TextSnapshot).Contains(wpfTextView.Caret.Position.BufferPosition.Subtract(1)))
                {
                    this.currentParameter = ranges.Length - 1;
                }
                else
                {
                    // the caret moved left of the open parenthesis or right of the close parenthesis
                    this.currentParameter = 0;
                    this.Dismiss();
                }
            }
            // possibly select a method from overload list based on current num of params the user has
            if (methodTipMiscellany == MethodTipMiscellany_DEPRECATED.ExplicitlyInvokedViaCtrlShiftSpace
                || methodTipMiscellany == MethodTipMiscellany_DEPRECATED.JustPressedComma)
            {
                Debug.Assert(this.methods != null, "this can happen if we just called Dismiss() because we erroneously decided the caret moves outside the parens");

                var actualParamNames = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(this.methods.GetParameterNames(), s => null != s));

                int numOfParamsUserHasSoFar = methods.GetNoteworthyParamInfoLocations().Length - 3; // -3 because first 3 ranges are [LID.start, LID.end, Paren], rest are params
                // however note that this is never zero, "foo(" and "foo(x"  both report 1

                int curMeth = this.currentMethod;  // start wherever the user already is.  the methods are already ordered in increasing order-of-params; only can increase of user has longer param list.
                while (curMeth < this.methods.GetCount()
                       && this.methods.GetParameterCount(curMeth) < numOfParamsUserHasSoFar
                       // if we're on a zero-arg overload, don't go past it when user has one arg; be like C#, good for e.g. Console.WriteLine(
                       && !(numOfParamsUserHasSoFar == 1 && this.methods.GetParameterCount(curMeth) == 0))
                {
                    curMeth++;
                }
                if (curMeth == this.methods.GetCount())
                {
                    // if they have 'too many' parameters, always just start at the beginning of the list
                    curMeth = 0;
                }
                else if (actualParamNames.Count > 0)
                {
                    // there are named parameters, additionally ensure the selected overload has those names, or keep advancing until it does
                    while (curMeth < this.methods.GetCount()
                           && !FormalParamNames(this.methods, curMeth).IsSupersetOf(actualParamNames))
                    {
                        curMeth++;
                    }
                }
                this.currentMethod = curMeth;
            }
            else
            {
                // in other cases, don't update which overload we're on, the user is in control
            }
            this.UpdateView();
        }