Пример #1
0
        public IEnumerable <ITagSpan <TextMarkerTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            DateTime oStart, oEnd;
            TimeSpan timeSpan;

            oStart = DateTime.Now;

            Debug("Start get brackets: " + oStart.ToString("hh:mm:ss.fff"));

            if (spans.Count == 0)   //there is no content in the buffer
            {
                yield break;
            }

            if (CurrentChar == null || SourceBuffer == null)
            {
                yield break;
            }

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


            //hold on to a snapshot of the current character
            SnapshotPoint ssp = CurrentChar.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 != ssp.Snapshot)
            {
                ssp = ssp.TranslateTo(spans[0].Snapshot, PointTrackingMode.Positive);
            }

            //get the current char and the previous char
            char          currentText = '\0';
            char          lastText    = '\0';
            SnapshotSpan  pairSpan    = new SnapshotSpan();
            SnapshotPoint lastChar    = new SnapshotPoint();

            try
            {
                currentText = ssp.GetChar();
                lastChar    = ssp == 0 ? ssp : ssp - 1; //if ssp is 0 (beginning of buffer), don't move it back
                lastText    = lastChar.GetChar();
            }
            catch (Exception)
            {
                yield break;
            }


            // use the tokens stored in the buffer properties
            XSharpTokens   xTokens = null;
            IList <IToken> tokens  = null;
            int            offset  = 0;

            if (m_braceList.ContainsKey(currentText) || (m_braceList.ContainsValue(lastText))) //FM#081219 #1 - Only need to get the tokens if either of these conditions is true
            {
                if (SourceBuffer.Properties != null && SourceBuffer.Properties.ContainsProperty(typeof(XSharpTokens)))
                {
                    xTokens = SourceBuffer.Properties.GetProperty <XSharpTokens>(typeof(XSharpTokens));
                    if (xTokens == null || xTokens.TokenStream == null || xTokens.SnapShot == null)
                    {
                        yield break;
                    }

                    tokens = xTokens.TokenStream.GetTokens();
                    if (tokens == null)
                    {
                        yield break;
                    }

                    if (xTokens.SnapShot.Version != ssp.Snapshot.Version)
                    {
                        // get source from the start of the file until the current entity
                        var xfile  = SourceBuffer.GetFile();
                        var member = XSharpTokenTools.FindMemberAtPosition(ssp.Position, xfile);
                        if (member != null)
                        {
                            try
                            {
                                var    sourceWalker = new SourceWalker(xfile);
                                string text         = ssp.Snapshot.GetText();
                                text   = text.Substring(member.Interval.Start, member.Interval.Width); //FM#081219 #2 - We are in a 'member'. For brace matching we should only ever need to look to the end of this member
                                offset = member.Interval.Start;
                                Debug("Start sourceWalker.Lex: " + DateTime.Now.ToString("hh:mm:ss.fff"));
                                var stream = (BufferedTokenStream)sourceWalker.Lex(text);
                                Debug("End sourceWalker.Lex: " + DateTime.Now.ToString("hh:mm:ss.fff"));
                                tokens = stream.GetTokens();
                            }
                            catch (Exception e)
                            {
                                // if it crashes, that might be because the snapshot used for the Lex/Parse is no more
                                // so, we may have a too much difference
                                // we do not break but simply use the 'old' tokens
                                System.Diagnostics.Debug.WriteLine(e.Message);
                            }
                        }
                    }
                }
            }

            // First, try to match Simple chars
            if (m_braceList.ContainsKey(currentText))   //the key is the open brace
            {
                char closeChar;
                m_braceList.TryGetValue(currentText, out closeChar);
                if (BraceMatchingTagger.FindMatchingCloseChar(ssp, currentText, closeChar, out pairSpan, tokens, offset) == true)
                {
                    yield return(new TagSpan <TextMarkerTag>(new SnapshotSpan(ssp, 1), new TextMarkerTag("blue")));

                    yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("blue")));
                }
            }
            else if (m_braceList.ContainsValue(lastText))    //the value is the close brace, which is the *previous* character
            {
                var open = from n in m_braceList
                           where n.Value.Equals(lastText)
                           select n.Key;
                if (BraceMatchingTagger.FindMatchingOpenChar(lastChar, (char)open.ElementAt <char>(0), lastText, out pairSpan, tokens, offset) == true)
                {
                    yield return(new TagSpan <TextMarkerTag>(new SnapshotSpan(lastChar, 1), new TextMarkerTag("blue")));

                    yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("blue")));
                }
            }
            else
            {
                // Second, try to Match Keywords
                // Try to retrieve an already parsed list of Tags
                XSharpClassifier xsClassifier = null;
                if (SourceBuffer.Properties.ContainsProperty(typeof(XSharpClassifier)))
                {
                    xsClassifier = SourceBuffer.Properties[typeof(XSharpClassifier)] as XSharpClassifier;
                }

                if (xsClassifier != null)
                {
                    ITextSnapshot snapshot = xsClassifier.Snapshot;
                    if (snapshot.Version != ssp.Snapshot.Version)
                    {
                        yield break;
                    }
                    SnapshotSpan Span            = new SnapshotSpan(snapshot, 0, snapshot.Length);
                    var          classifications = xsClassifier.GetTags();
                    // We cannot use SortedList, because we may have several Classification that start at the same position
                    List <ClassificationSpan> sortedTags = new List <ClassificationSpan>();
                    foreach (var tag in classifications)
                    {
                        // Only keep the Brace matching Tags
                        if ((tag.ClassificationType.IsOfType(ColorizerConstants.XSharpBraceOpenFormat)) ||
                            (tag.ClassificationType.IsOfType(ColorizerConstants.XSharpBraceCloseFormat)))
                        {
                            sortedTags.Add(tag);
                        }
                    }
                    sortedTags.Sort((a, b) => a.Span.Start.Position.CompareTo(b.Span.Start.Position) * 1000 + string.Compare(a.ClassificationType.Classification, b.ClassificationType.Classification));
                    //
                    var tags = sortedTags.Where(x => ssp.Position >= x.Span.Start.Position && ssp.Position <= x.Span.End.Position);
                    foreach (var currentTag in tags)
                    {
                        var index = sortedTags.IndexOf(currentTag);
                        if (currentTag.ClassificationType.IsOfType(ColorizerConstants.XSharpBraceOpenFormat))
                        {
                            if (FindMatchingCloseTag(sortedTags, index, snapshot, out pairSpan))
                            {
                                var span = currentTag.Span;
                                yield return(new TagSpan <TextMarkerTag>(span, new TextMarkerTag("bracehighlight")));

                                yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("bracehighlight")));
                            }
                        }
                        else
                        {
                            if (FindMatchingOpenTag(sortedTags, index, snapshot, out pairSpan))
                            {
                                var span = currentTag.Span;
                                yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("bracehighlight")));

                                yield return(new TagSpan <TextMarkerTag>(span, new TextMarkerTag("bracehighlight")));
                            }
                        }
                    }
                }
            }

            oEnd     = DateTime.Now;
            timeSpan = oEnd - oStart;

            Debug("Finished get brackets: " + oEnd.ToString("hh:mm:ss.fff"));
            Debug("Finished get brackets - total ms: " + timeSpan.TotalMilliseconds.ToString());
        }
Пример #2
0
        public IEnumerable <ITagSpan <TextMarkerTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            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 at the end of the buffer
            if (!CurrentChar.HasValue || CurrentChar.Value.Position >= CurrentChar.Value.Snapshot.Length)
            {
                yield break;
            }


            //hold on to a snapshot of the current character
            SnapshotPoint currentChar = CurrentChar.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 != currentChar.Snapshot)
            {
                //currentChar = currentChar.TranslateTo(spans[0].Snapshot, PointTrackingMode.Positive);
                yield break;
            }

            //get the current char and the previous char
            char          currentText = '\0';
            char          lastText    = '\0';
            SnapshotSpan  pairSpan    = new SnapshotSpan();
            SnapshotPoint lastChar    = new SnapshotPoint();

            try
            {
                currentText = currentChar.GetChar();
                lastChar    = currentChar == 0 ? currentChar : currentChar - 1; //if currentChar is 0 (beginning of buffer), don't move it back
                lastText    = lastChar.GetChar();
            }
            catch (Exception)
            {
            }
            // use the tokens stored in the buffer properties
            XSharpTokens   xTokens = null;
            IList <IToken> tokens  = null;
            int            offset  = 0;

            if (SourceBuffer.Properties.ContainsProperty(typeof(XSharpTokens)))
            {
                xTokens = SourceBuffer.Properties.GetProperty <XSharpTokens>(typeof(XSharpTokens));
                if (xTokens.SnapShot.Version != currentChar.Snapshot.Version)
                {
                    // get source from the start of the file until the current entity
                    var xfile  = SourceBuffer.GetFile();
                    var member = XSharpTokenTools.FindMemberAtPosition(currentChar.Position, xfile);
                    if (member != null)
                    {
                        try
                        {
                            offset = member.Interval.Start;
                            var length = member.Interval.Width;
                            if (offset + length > currentChar.Snapshot.Length)
                            {
                                length = currentChar.Snapshot.Length - offset;
                            }
                            //
                            string             text     = currentChar.Snapshot.GetText(offset, length);
                            var                reporter = new ErrorIgnorer();
                            ITokenStream       tokenStream;
                            XSharpParseOptions parseoptions;
                            var                prj = xfile.Project.ProjectNode;
                            parseoptions = prj.ParseOptions;
                            bool ok      = XSharp.Parser.VsParser.Lex(text, xfile.FullPath, parseoptions, reporter, out tokenStream);
                            var  bstream = tokenStream as BufferedTokenStream;
                            tokens = bstream.GetTokens();
                        }
                        catch
                        {
                            // if it crashes, that might be because the snapshot used for the Lex/Parse is no more
                            // so, we may have a too much difference
                            yield break;
                        }
                    }
                }
                else
                {
                    tokens = xTokens.TokenStream.GetTokens();
                }
            }

            // First, try to match Simple chars
            if (m_braceList.ContainsKey(currentText))   //the key is the open brace
            {
                char closeChar;
                m_braceList.TryGetValue(currentText, out closeChar);
                if (BraceMatchingTagger.FindMatchingCloseChar(currentChar, currentText, closeChar, out pairSpan, tokens, offset) == true)
                {
                    yield return(new TagSpan <TextMarkerTag>(new SnapshotSpan(currentChar, 1), new TextMarkerTag("blue")));

                    yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("blue")));
                }
            }
            else if (m_braceList.ContainsValue(lastText))    //the value is the close brace, which is the *previous* character
            {
                var open = from n in m_braceList
                           where n.Value.Equals(lastText)
                           select n.Key;
                if (BraceMatchingTagger.FindMatchingOpenChar(lastChar, (char)open.ElementAt <char>(0), lastText, out pairSpan, tokens, offset) == true)
                {
                    yield return(new TagSpan <TextMarkerTag>(new SnapshotSpan(lastChar, 1), new TextMarkerTag("blue")));

                    yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("blue")));
                }
            }
            else
            {
                // Second, try to Match Keywords
                // Try to retrieve an already parsed list of Tags
                XSharpClassifier xsClassifier = null;
                if (SourceBuffer.Properties.ContainsProperty(typeof(XSharpClassifier)))
                {
                    xsClassifier = SourceBuffer.Properties[typeof(XSharpClassifier)] as XSharpClassifier;
                }

                if (xsClassifier != null)
                {
                    ITextSnapshot snapshot = xsClassifier.Snapshot;
                    if (snapshot.Version != currentChar.Snapshot.Version)
                    {
                        yield break;
                    }
                    SnapshotSpan Span            = new SnapshotSpan(snapshot, 0, snapshot.Length);
                    var          classifications = xsClassifier.GetTags();
                    // We cannot use SortedList, because we may have several Classification that start at the same position
                    List <ClassificationSpan> sortedTags = new List <ClassificationSpan>();
                    foreach (var tag in classifications)
                    {
                        // Only keep the Brace matching Tags
                        if ((tag.ClassificationType.IsOfType(ColorizerConstants.XSharpBraceOpenFormat)) ||
                            (tag.ClassificationType.IsOfType(ColorizerConstants.XSharpBraceCloseFormat)))
                        {
                            sortedTags.Add(tag);
                        }
                    }
                    sortedTags.Sort((a, b) => a.Span.Start.Position.CompareTo(b.Span.Start.Position));
                    //
                    int indexTag = sortedTags.FindIndex(x => currentChar.Position >= x.Span.Start.Position && currentChar.Position <= x.Span.End.Position);
                    if (indexTag != -1)
                    {
                        var currentTag = sortedTags[indexTag];
                        if (currentTag.ClassificationType.IsOfType(ColorizerConstants.XSharpBraceOpenFormat))
                        {
                            if (FindMatchingCloseTag(sortedTags, indexTag, snapshot, out pairSpan))
                            {
                                var span = currentTag.Span;
                                yield return(new TagSpan <TextMarkerTag>(span, new TextMarkerTag("bracehighlight")));

                                yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("bracehighlight")));
                            }
                        }
                        else
                        {
                            if (FindMatchingOpenTag(sortedTags, indexTag, snapshot, out pairSpan))
                            {
                                var span = currentTag.Span;
                                yield return(new TagSpan <TextMarkerTag>(pairSpan, new TextMarkerTag("bracehighlight")));

                                yield return(new TagSpan <TextMarkerTag>(span, new TextMarkerTag("bracehighlight")));
                            }
                        }
                    }
                }
            }
        }