예제 #1
0
        void HandleGotoResponse(BackgroundRequest req) {
            if (req == null || req.Source == null || req.Source.IsClosed) return;

            // Make sure caret hasn't moved since we kicked this off.
            TextSpan[] aSpan = new TextSpan[1];
            int line, col;
            NativeMethods.ThrowOnFailure(this.textView.GetCaretPos(out line, out col));
            if (req.Line != line || req.Col != col)
                return; // caret has moved.

            string url = null;
            TextSpan span;
            IntellisenseInfo scope = req.ResultIntellisenseInfo;
            if (scope != null && gotoCmd == VSConstants.VSStd97CmdID.GotoDefn)
            {
                var gotoResult = scope.Goto(textView, line, col);
                if (!gotoResult.Success)
                {
                    ShowErrorMessageBox(gotoResult.ErrorDescription);
                    return;
                }
                url = gotoResult.Url;
                span = gotoResult.Span;
            } else {
                return;
            }
            if (url == null || url.Trim().Length == 0) { // nothing to show
                return;
            }

            // Open the referenced document, and scroll to the given location.
            IVsUIHierarchy hierarchy;
            uint itemID;
            IVsWindowFrame frame;
            IVsTextView view;

            VsShell.OpenDocument(this.service.Site, url, NativeMethods.LOGVIEWID_Code, out hierarchy, out itemID, out frame, out view);
            if (view != null) {
                TextSpanHelper.MakePositive(ref span);
                NativeMethods.ThrowOnFailure(view.SendExplicitFocus());
                NativeMethods.ThrowOnFailure(view.EnsureSpanVisible(span));
                NativeMethods.ThrowOnFailure(view.SetSelection(span.iStartLine, span.iStartIndex, span.iEndLine, span.iEndIndex));
            }
        }
예제 #2
0
        private void HandleMethodTipResponse(BackgroundRequest req)
        {
            try
            {
                if (this.service == null)
                    return;

                // Don't do anything if the buffer is out of sync
                if (req.Timestamp != this.ChangeCount)
                    return;

                HandleResponseHelper(req);

                if (req.Timestamp != this.ChangeCount)
                {
                    // The user has been typing since we sent off the snapshot to be parsed
                    // TODO maybe this gets into infinite loop of wasted work if something goes wrong
                    this.MethodTip(req.View, req.Line, req.Col, req.TokenInfo, req.MethodTipMiscellany, RequireFreshResults.No);  // try again, need up-to-date parse
                }
                else
                {
                    MethodListForAMethodTip methods = req.ResultScope.GetMethodListForAMethodTip(true);
                    if (methods != null)
                    {
                        TextSpan spanNotToObscureWithTipPopup = new TextSpan();
                        spanNotToObscureWithTipPopup.iStartLine = methods.GetNoteworthyParamInfoLocations()[0].Item1 - 1;  // is 1-based, need 0-based
                        spanNotToObscureWithTipPopup.iStartIndex = methods.GetNoteworthyParamInfoLocations()[0].Item2 - 1; // is 1-based, need 0-based
                        spanNotToObscureWithTipPopup.iEndLine = req.Line;
                        spanNotToObscureWithTipPopup.iEndIndex = req.Col;
                        this.methodData.Refresh(req.View, methods, spanNotToObscureWithTipPopup, req.MethodTipMiscellany);
                    }
                    else if (req.MethodTipMiscellany == MethodTipMiscellany.JustPressedOpenParen && req.Timestamp != req.ResultTimestamp)
                    {
                        // Second-chance param info: we didn't get any result and the basis typecheck was stale. We need to retrigger the completion.
                        this.MethodTip(req.View, req.Line, req.Col, req.TokenInfo, req.MethodTipMiscellany, RequireFreshResults.Yes);
                    }
                    else
                    {
                        DismissCompletor();
                    }
                }
#if LANGTRACE
            } catch (Exception e) {
                Trace.WriteLine("HandleMethodTipResponse exception: " + e.Message);
#endif
            }
            catch { }
        }
예제 #3
0
        internal void GetDataTipResponse(BackgroundRequest req)
        {
            if (req == null || req.Source == null || req.Source.IsClosed) return;

            if ((req.ResultQuickInfoText != null) && TextSpanHelper.ContainsInclusive(req.ResultQuickInfoSpan, this.quickInfoRequestLine, this.quickInfoRequestCol))
            {
                this.quickInfoText = req.ResultQuickInfoText;
                this.gotQuickInfo = true;
                this.quickInfoSpan = req.ResultQuickInfoSpan;

            }
        }
예제 #4
0
        void HandleQuickInfoResponse(BackgroundRequest req){
            if (req == null || req.Source == null || req.Source.IsClosed) return;

            int line;
            int col;
            // Get the caret position
            NativeMethods.ThrowOnFailure(this.textView.GetCaretPos(out line, out col));

            string text = null;
            if (req.ResultIntellisenseInfo != null) {
                text = req.ResultQuickInfoText;
                if (text == null || !TextSpanHelper.ContainsInclusive(req.ResultQuickInfoSpan, line, col))
                {
                    return; // caret has moved.
                }
            } else {
                return;
            }

            string fullText;
            TextSpan ts = new TextSpan();
            ts.iStartLine = ts.iEndLine = line;
            ts.iStartIndex = ts.iEndIndex = col;
            NativeMethods.ThrowOnFailure(GetFullDataTipText(text, ts, out fullText));

            if (String.IsNullOrEmpty(fullText)) {
                return;
            }

            int iPos, iSpace, iLength;

            // Calculate the stream position
            NativeMethods.ThrowOnFailure(textView.GetNearestPosition(ts.iStartLine, ts.iStartIndex, out iPos, out iSpace));
            iLength = 0;

            // Tear down the method tip window if it's there
            this.source.DismissCompletor();

            // Update the text tip window
            TextTipData textTipData = this.TextTipData;

            textTipData.Update(fullText, iPos, iLength, this.textView);
        }
예제 #5
0
 internal BackgroundRequestAsyncResult(BackgroundRequest req, ManualResetEvent globalRequestCompletedEvent)
 {
     this.globalRequestCompletedEvent = globalRequestCompletedEvent;
     this.req = req;
 }
예제 #6
0
 /// <summary>Override this method if you need to do any post-parse work on the main UI thread.
 /// Be sure to call this base method in order to get the dynamic help context updated.</summary>
 internal virtual void OnUntypedParseOrFullTypeCheckComplete(BackgroundRequest req)
 {
     if (req == null || req.Source == null || req.Source.IsClosed) return;
     SetUserContextDirty(req.FileName);
     RefreshUI();
 }
예제 #7
0
 private static RequestType GetRequestType(BackgroundRequest r)
 {
     switch (r.Reason)
     {
         case BackgroundRequestReason.UntypedParse:
         case BackgroundRequestReason.FullTypeCheck:
             return RequestType.NonUi;
         default:
             return RequestType.Ui;        
     }
 }
예제 #8
0
        public void HandleResponseHelper(BackgroundRequest req)
        {
            try
            {
                if (this.service == null) return;
                // If the request is out of sync with the buffer, then the error spans
                // and hidden regions could be wrong, so we ignore this parse and wait 
                // for the next OnIdle parse.
                if (req.ResultClearsDirtinessOfFile && req.Timestamp == this.ChangeCount)
                {
                    this.RecordViewRefreshed();
                    if (req.ResultScope != null)
                    {

                        int end = Environment.TickCount;
                        if (req.StartTimeForOnIdleRequest != 0 && end > req.StartTimeForOnIdleRequest)
                        {
#if LANGTRACE
                            Trace.WriteLine("BackgroundRequest in " + (end - start) + " ticks");
#endif
                            this.lastOnIdleRequestDuration = end - req.StartTimeForOnIdleRequest; // for OnIdle loop
                        }

                        if (req.View == this.service.LastActiveTextView)
                        {
                            this.service.RecentFullTypeCheckResults = req.ResultScope;
                            this.service.RecentFullTypeCheckFile = req.FileName;
                        }
                        ReportTasks(req.ResultSink.errors);
                    }
                    this.service.OnUntypedParseOrFullTypeCheckComplete(req);
                }
            }
            catch
            {
            }

        }
예제 #9
0
 /// <summary>
 /// Gets request from queue
 /// </summary>
 /// <returns></returns>
 public BackgroundRequest Dequeue()
 {
     lock (syncRoot)
     {
         Debug.Assert(first != null);
         var tmp = first;
         
         first = second;
         second = null;
         
         return tmp;
     }
 }
예제 #10
0
        /// <summary>
        /// Discards all requests added so far and enqueues specified request.
        /// </summary>
        public void Set(BackgroundRequest r)
        {
            lock (syncRoot)
            {
                first = null;
                second = null;

                Enqueue(r);
            }
        }
예제 #11
0
 internal abstract void ExecuteBackgroundRequest(BackgroundRequest req);
예제 #12
0
 /// <summary>
 /// Checks if request queue contains request similar to the given one.
 /// </summary>
 public bool ContainsSimilarRequest(BackgroundRequest request)
 {
     var requestType = GetRequestType(request); 
     lock (syncRoot)
     {
         if (first == null)
         {
             // 0 items
             return false;
         }
         else if (second == null)
         {
             // 1 item
             return requestType == GetRequestType(first);
         }
         else
         {
             // 2 items (both Ui and non-Ui)
             return true;
         }
     }
 }
예제 #13
0
        public void Enqueue(BackgroundRequest newRequest)
        {
            if (newRequest == null)
                throw new ArgumentNullException("newRequest");

            lock (syncRoot)
            {
                if (first == null)
                {
                    // 0-items                    
                    // just add request to the queue
                    first = newRequest;
                }
                else if (second == null)
                {
                    // 1-item                    
                    var currentType = GetRequestType(newRequest);
                    var previousType = GetRequestType(first);

                    if (currentType == RequestType.Ui || (currentType == previousType))
                    {
                        // - Ui requests discard everything
                        // - non-Ui request discard non-Ui request
                        first = newRequest;
                    }
                    else
                    {
                        // we got here if current type is non-Ui and prev type is Ui
                        second = newRequest;
                    }

                }
                else
                {
                    // 2 items

                    // the only situation with we can have 2 requests in queue is [Ui; Non-Ui]
                    Debug.Assert(GetRequestType(first) == RequestType.Ui);
                    Debug.Assert(GetRequestType(second) == RequestType.NonUi);

                    var requestType = GetRequestType(newRequest);
                    if (requestType == RequestType.Ui)
                    {
                        // discard both old requests
                        first = newRequest;
                        second = null;
                    }
                    else
                    {
                        // replace non-Ui request with a new one
                        second = newRequest;
                    }
                }
            }
        }
예제 #14
0
        public void HandleMatchBracesResponse(BackgroundRequest req)
        {
            try
            {
                if (this.service == null || req.Timestamp != this.ChangeCount)
                    return;

                // save request so it can later be reused in GetPairExtent
                HandleGetPairExtentResponse(req);
#if LANGTRACE
                Trace.WriteLine("HandleMatchBracesResponse");
#endif
                // Filter matching braces and find spans to highlight - we want to highlight 
                // matches only before opening and after closing brace
                int line;
                int idx;
                NativeMethods.ThrowOnFailure(req.View.GetCaretPos(out line, out idx));

                // Get all braces from language service and filter them
                List<BraceMatch> braces = new List<BraceMatch>();
                foreach (BraceMatch m in req.ResultSink.Braces) braces.Add(m);
                braces.RemoveAll(delegate(BraceMatch match)
                {
                    if (match.a.iStartLine == line && match.a.iStartIndex == idx) return false;
                    if (match.b.iEndLine == line && match.b.iEndIndex == idx) return false;
                    return true;
                });

                // Transform collection of braces into an array of spans
                List<TextSpan> spans = new List<TextSpan>();
                foreach (BraceMatch m in braces)
                {
                    spans.Add(m.a); spans.Add(m.b);
                }

                // Highlight
                if (spans.Count == 0) return;
                NativeMethods.ThrowOnFailure(req.View.HighlightMatchingBrace((uint)this.service.Preferences.HighlightMatchingBraceFlags, (uint)spans.Count, spans.ToArray()));

                //try to show the matching line in the statusbar
                if (spans.Count > 0 && this.service.Preferences.EnableShowMatchingBrace)
                {
                    IVsStatusbar statusBar = (IVsStatusbar)service.Site.GetService(typeof(SVsStatusbar));
                    if (statusBar != null)
                    {
                        TextSpan span = spans[0];
                        bool found = false;
                        // Gather up the other side of the brace match so we can 
                        // display the text in the status bar. There could be more than one
                        // if MatchTriple was involved, in which case we merge them.
                        for (int i = 0, n = spans.Count; i < n; i++)
                        {
                            TextSpan brace = spans[i];
                            if (brace.iStartLine != req.Line)
                            {
                                if (brace.iEndLine != brace.iStartLine)
                                {
                                    brace.iEndLine = brace.iStartLine;
                                    brace.iEndIndex = this.GetLineLength(brace.iStartLine);
                                }
                                if (!found)
                                {
                                    span = brace;
                                }
                                else if (brace.iStartLine == span.iStartLine)
                                {
                                    span = TextSpanHelper.Merge(span, brace);
                                }
                                found = true;
                            }
                        }
                        if (found)
                        {
                            Debug.Assert(TextSpanHelper.IsPositive(span));
                            string text = this.GetText(span);

                            int start;
                            int len = text.Length;

                            for (start = 0; start < len && Char.IsWhiteSpace(text[start]); start++) ;

                            if (start < span.iEndIndex)
                            {
                                if (text.Length > 80)
                                {
                                    text = String.Format(CultureInfo.CurrentUICulture, SR.GetString(SR.Truncated), text.Substring(0, 80));
                                }
                                text = String.Format(CultureInfo.CurrentUICulture, SR.GetString(SR.BraceMatchStatus), text);
                                NativeMethods.ThrowOnFailure(statusBar.SetText(text));
                            }
                        }
                    }
                }
#if LANGTRACE
            } catch (Exception e) {
                Trace.WriteLine("HandleMatchBracesResponse exception: " + e.Message);
#endif
            }
            catch
            {
            }
        }
예제 #15
0
 internal void HandleUpdateLanguageContextResponse(BackgroundRequest req)
 {
 }
예제 #16
0
 void HandleGetPairExtentResponse(BackgroundRequest request)
 {
     if (this.service == null)
     {
         return;
     }
     this.lastBraceMatchRequest = request;
 }
예제 #17
0
 internal BackgroundRequestAsyncResult BeginBackgroundRequest(BackgroundRequest request, BackgroundRequestResultHandler handler)
 {
     EnsureBackgroundThreadStarted();
     lock (this)
     {
         request.Callback = handler;
         this.requests.Enqueue(request);
         this.isServingBackgroundRequest = true;
         this.backgroundRequestPending.Set();
         this.backgroundRequestDone.Reset();
         // Return a capability to wait on the completion of the background request
         return new BackgroundRequestAsyncResult(request, this.backgroundRequestDone);
     }
 }
예제 #18
0
        public void HandleUntypedParseOrFullTypeCheckResponse(BackgroundRequest req)
        {
            if (this.service == null) return;
            try
            {
                Debug.Assert((req.Reason == BackgroundRequestReason.UntypedParse || req.Reason == BackgroundRequestReason.FullTypeCheck), "this callback is being used for the wrong type of parse request");
#if LANGTRACE
                Trace.WriteLine("HandleUntypedParseOrFullTypeCheckResponse:" + req.Timestamp);
#endif
                if (this.service == null) return;

                HandleResponseHelper(req);
#if LANGTRACE
            } catch (Exception e) {
                Trace.WriteLine("HandleUntypedParseOrFullTypeCheckResponse exception: " + e.Message);
#endif
            }
            catch
            {
            }
        }
예제 #19
0
		// Implemented in FSharpLanguageService.fs
		internal abstract void OnParseFileOrCheckFileComplete(BackgroundRequest req);