Example #1
0
        private void UpdateJavaScriptBlockSpans()
        {
            if (IsHtmlFile)
            {
                _javaScriptBlockSpans = JScriptEditorUtil.GetJavaScriptBlockSpans(_lbm);
            }
            else
            {
                if (_javaScriptBlockSpans == null)
                {
                    _javaScriptBlockSpans = new List <BlockSpan>(1);
                }
                else
                {
                    _javaScriptBlockSpans.Clear();
                }

                _javaScriptBlockSpans.Add(new BlockSpan(0, _buffer.CurrentSnapshot.Length, false));
            }

            _javaScriptBlockStarts.Clear();
            _javaScriptBlockEnds.Clear();

            foreach (BlockSpan javaScriptBlockSpan in _javaScriptBlockSpans)
            {
                _javaScriptBlockStarts.Add(javaScriptBlockSpan.Start);
                _javaScriptBlockEnds.Add(javaScriptBlockSpan.End);
            }
        }
        public void AugmentCompletionSession(ICompletionSession session, IList <CompletionSet> completionSets)
        {
            if (IsHtmlFile && completionSets.Any())
            {
                var bottomSpan = completionSets.First().ApplicableTo;
                if (!JScriptEditorUtil.IsInJScriptLanguageBlock(_lbm, bottomSpan.GetStartPoint(bottomSpan.TextBuffer.CurrentSnapshot)))
                {
                    // This is an HTML statement completion session, so do nothing
                    return;
                }
            }

            // TODO: Reflect over the ShimCompletionSet to see where the Description value comes from
            //       as setting the property does not actually change the value.
            var newCompletionSets = completionSets
                                    .Select(cs => cs == null ? cs : new ScriptCompletionSet(
                                                cs.Moniker,
                                                cs.DisplayName,
                                                cs.ApplicableTo,
                                                cs.Completions
                                                .Select(c => c == null ? c : new Completion(
                                                            c.DisplayText,
                                                            c.InsertionText,
                                                            DocCommentHelper.ProcessParaTags(c.Description),
                                                            c.IconSource,
                                                            c.IconAutomationText))
                                                .ToList(),
                                                cs.CompletionBuilders))
                                    .ToList();

            completionSets.Clear();

            newCompletionSets.ForEach(cs => completionSets.Add(cs));
        }
Example #3
0
        void UpdateWordAdornments()
        {
            var currentRequest = RequestedPoint;
            var wordSpans      = new List <SnapshotSpan>();
            var word           = GetExtentOfWord(currentRequest);

            // Find all words in the buffer like the one the caret is on
            bool foundWord = true;

            // If we've selected something not worth highlighting, we might have missed a "word" by a little bit
            if (!WordExtentIsValid(currentRequest, word))
            {
                // Before we retry, make sure it is worthwhile
                if (word.Span.Start != currentRequest ||
                    currentRequest == currentRequest.GetContainingLine().Start ||
                    char.IsWhiteSpace((currentRequest - 1).GetChar()))
                {
                    foundWord = false;
                }
                else
                {
                    // Try again, one character previous.
                    // If the caret is at the end of a word, pick up the word.
                    word = GetExtentOfWord(currentRequest - 1);

                    // If the word still isn't valid, we're done
                    if (!WordExtentIsValid(currentRequest, word))
                    {
                        foundWord = false;
                    }
                }
            }

            SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null);
            if (!foundWord)
            {
                return;
            }

            SnapshotSpan currentWord = word.Span;

            // If this is the current word, and the caret moved within a word, we're done.
            if (CurrentWord.HasValue && currentWord == CurrentWord)
            {
                return;
            }

            // If the word is not an identifier, then don't search for matches.
            if (!JScriptEditorUtil.IsClassifiedAs(Classifier, currentWord.Start, JScriptClassifications.Identifier))
            {
                return;
            }

            var request = new FindMatchesRequest {
                WordSpan = currentWord, RequestPoint = currentRequest
            };

            FindAllMatches(request);
        }
Example #4
0
 private bool BraceShouldBeIgnored(SnapshotPoint bracePoint)
 {
     // if the prev char is a comment, string or operator then don't try matching
     // Note: The editor incorrectly classifies braces in regex literals as operators.
     //       We are using this fact to detect if the brace is in a regex literal and thus ignore it.
     //       Genuine braces have no classification at all.
     return(JScriptEditorUtil.IsClassifiedAs(_classifier, bracePoint,
                                             JScriptClassifications.Comment,
                                             JScriptClassifications.String,
                                             JScriptClassifications.Operator));
 }
Example #5
0
        internal static bool FindMatchingBrace(ILanguageBlockManager lbm, IClassifier classifier, SnapshotPoint startPoint, bool findClosing, char open, char close, int maxLines, ref bool maxLinesReached, out SnapshotSpan pairSpan)
        {
            // Get script block we're working in
            // lbm will be null if this is not in an HTML file
            var scriptBlock = lbm != null
                ? JScriptEditorUtil.GetJavaScriptBlockSpans(lbm)
                              .Single(b => b.Start <= startPoint.Position && b.End >= startPoint.Position)
                : new BlockSpan(0, startPoint.Snapshot.TextBuffer.CurrentSnapshot.Length, true);

            return(findClosing
                ? FindMatchingCloseChar(scriptBlock, classifier, startPoint, open, close, maxLines, ref maxLinesReached, out pairSpan)
                : FindMatchingOpenChar(scriptBlock, classifier, startPoint, close, open, maxLines, ref maxLinesReached, out pairSpan));
        }
Example #6
0
        private void SynchronousUpdate(SnapshotPoint currentRequest, IEnumerable <SnapshotSpan> newSpans, SnapshotSpan?newCurrentWord)
        {
            ViewDispatcher.BeginInvoke(new Action(() =>
            {
                if (currentRequest != RequestedPoint)
                {
                    return;
                }

                WordSpans = new NormalizedSnapshotSpanCollection(
                    newSpans.Where(s => JScriptEditorUtil.IsClassifiedAsJavaScript(Classifier, s.Start)));

                CurrentWord = newCurrentWord;

                OnTagsChanged(new SnapshotSpan(View.TextBuffer.CurrentSnapshot, 0, View.TextBuffer.CurrentSnapshot.Length));
            }));
        }
Example #7
0
        public IEnumerable <ITagSpan <TextMarkerTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
#if DEBUG
            Util.Log("GetTags called");
#endif
            if (spans.Count == 0) // there is no content in the buffer
            {
                yield break;
            }

            // don't do anything if the current SnapshotPoint is not initialized or after the end of the buffer
            if (!_currentCharPoint.HasValue || _currentCharPoint.Value.Position > _currentCharPoint.Value.Snapshot.Length)
            {
                yield break;
            }

            // hold on to a snapshot of the current character
            var currentCharPoint = _currentCharPoint.Value;

            // if the requested snapshot isn't the same as the one the brace is on, translate our spans to the expected snapshot
            if (spans[0].Snapshot != currentCharPoint.Snapshot)
            {
                currentCharPoint = currentCharPoint.TranslateTo(spans[0].Snapshot, PointTrackingMode.Positive);
            }

            // get the current char and the previous char
            var currentChar   = currentCharPoint.Position != currentCharPoint.Snapshot.Length ? (char?)currentCharPoint.GetChar() : null;
            var prevCharPoint = currentCharPoint == 0 ? currentCharPoint : currentCharPoint - 1; // if currentChar is 0 (beginning of buffer), don't move it back
            var prevChar      = prevCharPoint != 0 ? prevCharPoint.GetChar() : default(char?);   // Can't get prevChar if point is 0

            var  maxLines = _view.TextViewLines.Count * _viewScreensToSearchOver;
            char closeChar;

            // If neither current or previous char is in a JS language block, return
            if (IsHtmlFile && !JScriptEditorUtil.IsInJScriptLanguageBlock(_lbm, currentCharPoint) &&
                !JScriptEditorUtil.IsInJScriptLanguageBlock(_lbm, prevCharPoint))
            {
                yield break;
            }

            // Check if char to right of cursor is an opening brace
            if (currentChar.HasValue && _braceList.TryGetValue(currentChar.Value, out closeChar)) // the value is the open brace
            {
                foreach (var s in GetTagSpans(currentCharPoint, currentChar.Value, closeChar, maxLines))
                {
                    yield return(s);
                }
            }

            // Check if char to left of cursor is a closing brace
            var openChar = _braceList.Where(kvp => kvp.Value.Equals(prevChar))
                           .Select(n => n.Key)
                           .FirstOrDefault();

            if (openChar != default(char)) // the value is the close brace, which is the *previous* character
            {
                foreach (var s in GetTagSpans(prevCharPoint, prevChar.Value, openChar, maxLines))
                {
                    yield return(s);
                }
            }
        }
Example #8
0
 public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
 {
     //_broker.GetSessions(_textView).Any()
     //_broker.IsCompletionActive(_textView)
     if (_broker.IsCompletionActive(_textView))
     {
         if (!IsHtmlFile ||
             (_broker.GetSessions(_textView).Any(cs =>
                                                 cs.IsStarted && !cs.IsDismissed && cs.CompletionSets.Any(set =>
                                                                                                          JScriptEditorUtil.IsInJScriptLanguageBlock(_lbm, set.ApplicableTo.GetStartPoint(_textView.TextSnapshot))))))
         {
             var userTypedPeriod = UserTypedPeriod(pguidCmdGroup, nCmdID, pvaIn);
             var userTypedParens = UserTypedParens(pguidCmdGroup, nCmdID, pvaIn);
             if (UserPerfomedCommitAction(pguidCmdGroup, nCmdID, pvaIn) || userTypedPeriod || userTypedParens)
             {
                 ForActiveCompletionSessions(s =>
                 {
                     if (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB ||  // Always complete on TAB
                         s.SelectedCompletionSet.SelectionStatus.IsSelected)        // If completion is selected (not just highlighted)
                     {
                         s.Commit();
                     }
                     else
                     {
                         s.Dismiss();
                     }
                 });
                 if (!userTypedPeriod && !userTypedParens)
                 {
                     return(VSConstants.S_OK); // Don't let anybody else handle this command
                 }
             }
             if (UserTypedOperator(pguidCmdGroup, nCmdID, pvaIn) && !userTypedPeriod)
             {
                 ForActiveCompletionSessions(s => s.Dismiss());
                 Debug.WriteLine("Dismissed all active completion sessions because user typed an operator");
             }
         }
     }
     return(NextCmdTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
 }
Example #9
0
        List <ITrackingSpan> ReparseRange(ITextSnapshot snapshot, int reparseRangeStart, int reparseRangeEnd, out bool unbalanced)
        {
            var  currentSections = new List <ITrackingSpan>();
            var  openCurlies     = new Stack <int>();
            bool isInJavaScript  = IsInJavaScriptBlock(reparseRangeStart);

            unbalanced = false;

            for (int i = reparseRangeStart; i < reparseRangeEnd; i++)
            {
                var point = new SnapshotSpan(snapshot, i, 1).Start;

                // If current point is not in a JS language block, return
                if (!isInJavaScript)
                {
                    if (_javaScriptBlockStarts.Contains(i))
                    {
                        // Our scan just barely entered a JavaScript block
                        isInJavaScript = true;

                        // We don't want opening curly from open JavaScript block to match with
                        // a closing curly from another block, so purge all unmatched (dangling)
                        // opening curlies from the previous block.
                        openCurlies.Clear();
                    }
                    else
                    {
                        continue;
                    }
                }

                if (_javaScriptBlockEnds.Contains(i))
                {
                    isInJavaScript = false;
                }

                var ch = snapshot[i];
                if (ch == '{' || ch == '}')
                {
                    if (JScriptEditorUtil.IsClassifiedAs(_classifier, point,
                                                         JScriptClassifications.Comment,
                                                         JScriptClassifications.String,
                                                         JScriptClassifications.Operator))
                    {
                        continue;
                    }
                }
                switch (ch)
                {
                case '{':
                    openCurlies.Push(i);
                    break;

                case '}':
                    if (openCurlies.Count > 0)
                    {
                        int start = openCurlies.Pop();
                        var line  = _buffer.CurrentSnapshot.GetLineFromPosition(i);
                        if (start < line.Start.Position)
                        {
                            currentSections.Add(snapshot.CreateTrackingSpan(start, i - start + 1, SpanTrackingMode.EdgeExclusive));
                        }
                    }
                    else
                    {
                        unbalanced = true;
                    }
                    break;

                default:
                    break;
                }
            }

            if (openCurlies.Count > 0)
            {
                unbalanced = true;
            }

            return(currentSections);
        }
Example #10
0
        // TODO: Can we refactor FindMatchingCloseChar and FindMatchingOpenChar into a single method?

        static bool FindMatchingCloseChar(BlockSpan scriptBlock, IClassifier classifier, SnapshotPoint startPoint, char open, char close, int maxLines, ref bool maxLinesReached, out SnapshotSpan pairSpan)
        {
            var isHTML = startPoint.Snapshot.ContentType.TypeName.Equals("HTML", StringComparison.OrdinalIgnoreCase);

            pairSpan = new SnapshotSpan(startPoint.Snapshot, 1, 1);
            var line       = startPoint.GetContainingLine();
            var lineText   = line.GetText();
            var lineNumber = line.LineNumber;
            var offset     = startPoint.Position - line.Start.Position + 1;
            var endOfScriptBlockReached = false;

            var stopLineNumber = startPoint.Snapshot.LineCount - 1;

            if (maxLines > 0)
            {
                stopLineNumber = Math.Min(stopLineNumber, lineNumber + maxLines);
            }
#if DEBUG
            var startTicks = DateTime.Now.Ticks;
            Util.Log("Looking for matching closing brace '{0}'", close);
#endif
            var openCount = 0;

            while (true)
            {
                // walk the entire line
                while (offset < line.Length)
                {
                    // Check if we've hit the end of the script block
                    if (scriptBlock.End < line.Start + offset)
                    {
                        // We've hit the end of a script block
                        endOfScriptBlockReached = true;
                        break;
                    }

                    char currentChar      = lineText[offset];
                    var  currentCharPoint = line.Start + offset;

                    if (currentChar == close) // found the close character
                    {
                        if (JScriptEditorUtil.IsClassifiedAs(classifier, currentCharPoint,
                                                             JScriptClassifications.Comment,
                                                             JScriptClassifications.String,
                                                             JScriptClassifications.Operator))
                        {
#if DEBUG
                            Util.Log("Candidate closing brace found but ignored because it was a comment, string or operator");
#endif
                        }
                        else if (openCount > 0)
                        {
                            openCount--;
                        }
                        else // found the matching close
                        {
#if DEBUG
                            Util.Log("Matching closing brace '{0}' found after {1}ms", close, TimeSpan.FromTicks(DateTime.Now.Ticks - startTicks).TotalMilliseconds);
#endif
                            pairSpan = new SnapshotSpan(startPoint.Snapshot, currentCharPoint, 1);
                            return(true);
                        }
                    }
                    else if (currentChar == open) // this is another open
                    {
                        if (JScriptEditorUtil.IsClassifiedAs(classifier, currentCharPoint,
                                                             JScriptClassifications.Comment,
                                                             JScriptClassifications.String,
                                                             JScriptClassifications.Operator))
                        {
#if DEBUG
                            Util.Log("New opening brace found but ignored because it was a comment, string or operator");
#endif
                        }
                        else
                        {
                            openCount++;
                        }
                    }
                    offset++;
                }

                if (endOfScriptBlockReached)
                {
                    break;
                }

                // move on to the next line
                if (++lineNumber > stopLineNumber)
                {
#if DEBUG
                    Util.Log("Reached max lines ({0}), stopped looking at line {1} after {2}ms", maxLines, stopLineNumber, TimeSpan.FromTicks(DateTime.Now.Ticks - startTicks).TotalMilliseconds);
#endif
                    // Set maxLinesReached flag only if we actually hit max lines limit, not just end of buffer
                    maxLinesReached = stopLineNumber >= maxLines;
                    break;
                }

                // Move to next line
                line     = line.Snapshot.GetLineFromLineNumber(lineNumber);
                lineText = line.GetText();
                offset   = 0;
            }
#if DEBUG
            Util.Log("Matching closing brace '{0}' was not found. Open count: {1} after {2}ms", close, openCount, TimeSpan.FromTicks(DateTime.Now.Ticks - startTicks).TotalMilliseconds);
#endif
            return(false);
        }
Example #11
0
        static bool FindMatchingOpenChar(BlockSpan scriptBlock, IClassifier classifier, SnapshotPoint startPoint, char open, char close, int maxLines, ref bool maxLinesReached, out SnapshotSpan pairSpan)
        {
            var isHTML = startPoint.Snapshot.ContentType.TypeName.Equals("HTML", StringComparison.OrdinalIgnoreCase);

            pairSpan = new SnapshotSpan(startPoint, startPoint);
            ITextSnapshotLine line        = startPoint.GetContainingLine();
            var lineNumber                = line.LineNumber;
            var offset                    = startPoint - line.Start - 1; // move the offset to the character before this one
            var startOfScriptBlockReached = false;

            // if the offset is negative, move to the previous line
            if (offset < 0)
            {
                line   = line.Snapshot.GetLineFromLineNumber(--lineNumber);
                offset = line.Length - 1;
            }

            var lineText = line.GetText();

            var stopLineNumber        = 0;
            var nominalStopLineNumber = lineNumber - maxLines;

            if (maxLines > 0)
            {
                stopLineNumber = Math.Max(stopLineNumber, nominalStopLineNumber);
            }
#if DEBUG
            var startTicks = DateTime.Now.Ticks;
            Util.Log("Looking for matching opening brace '{0}'", open);
#endif
            var closeCount = 0;

            Debug.Assert(scriptBlock != null);

            while (true)
            {
                // Walk the entire line
                while (offset >= 0)
                {
                    // Check if we've hit the start of the script block
                    if (scriptBlock.Start > line.Start + offset)
                    {
                        // We've hit the end of a script block
                        startOfScriptBlockReached = true;
                        break;
                    }

                    char currentChar      = lineText[offset];
                    var  currentCharPoint = line.Start + offset;

                    if (currentChar == open) // found the open character
                    {
                        if (JScriptEditorUtil.IsClassifiedAs(classifier, currentCharPoint,
                                                             JScriptClassifications.Comment,
                                                             JScriptClassifications.String,
                                                             JScriptClassifications.Operator))
                        {
#if DEBUG
                            Util.Log("Candidate opening brace found but ignored because it was a comment, string or operator");
#endif
                        }
                        else if (closeCount > 0)
                        {
                            closeCount--;
                        }
                        else // We've found the matching open character
                        {
#if DEBUG
                            Util.Log("Matching opening brace '{0}' found in {1}ms", open, TimeSpan.FromTicks(DateTime.Now.Ticks - startTicks).TotalMilliseconds);
#endif
                            pairSpan = new SnapshotSpan(currentCharPoint, 1); // we just want the character itself
                            return(true);
                        }
                    }
                    else if (currentChar == close)
                    {
                        if (JScriptEditorUtil.IsClassifiedAs(classifier, currentCharPoint,
                                                             JScriptClassifications.Comment,
                                                             JScriptClassifications.String,
                                                             JScriptClassifications.Operator))
                        {
#if DEBUG
                            Util.Log("New closing brace found but ignored because it was a comment, string or operator");
#endif
                        }
                        else
                        {
                            closeCount++;
                        }
                    }
                    offset--;
                }

                if (startOfScriptBlockReached)
                {
                    break;
                }

                // Move to the previous line
                if (--lineNumber < stopLineNumber)
                {
                    // Set maxLinesReached flag only if we actually hit max lines limit, not just start of buffer
                    maxLinesReached = stopLineNumber == nominalStopLineNumber;
#if DEBUG
                    Util.Log("Reached max lines ({0}, stopped looking at line {1} after {2}ms", maxLines, stopLineNumber, TimeSpan.FromTicks(DateTime.Now.Ticks - startTicks).TotalMilliseconds);
#endif
                    break;
                }

                line     = line.Snapshot.GetLineFromLineNumber(lineNumber);
                lineText = line.GetText();
                offset   = line.Length - 1;
            }
#if DEBUG
            Util.Log("Matching opening brace '{0}' was not found. Open count: {1} after {2}ms", open, closeCount, TimeSpan.FromTicks(DateTime.Now.Ticks - startTicks).TotalMilliseconds);
#endif
            return(false);
        }