NoahRic (owner)

Revisions

gist: 214665 Download_button fork
public
Public Clone URL: git://gist.github.com/214665.git
Embed All Files: show embed
KeywordClassifier.cs #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* Modified version of Thomas Restrepo's KeywordClassifier.cs.
* The original can be found here:
* http://github.com/tomasr/KeywordClassifier/blob/b2472cc2bbdd823a4d8a2ff5fdbfc82c4da1423e/KeywordClassifier.cs
* This has been updated for Beta 2, and switched from using a classifier to a view-specific
* tagger, to avoid issues around self-consumption.
*/
 
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;
 
namespace Winterdom.VisualStudio.Extensions.Text
{
    static class Constants
    {
        public const String CLASSIF_NAME = "FlowControl";
        public const String LINQ_CLASSIF_NAME = "LinqOperator";
        public const String VISIBILITY_CLASSIF_NAME = "VisibilityKeyword";
    }
 
[Export(typeof(IViewTaggerProvider))]
[ContentType(CSharp.ContentType)]
[ContentType(Cpp.ContentType)]
[TagType(typeof(ClassificationTag))]
    public class KeywordClassifierProvider : IViewTaggerProvider
    {
[Import]
        internal IClassificationTypeRegistryService ClassificationRegistry = null;
 
[Import]
        internal IBufferTagAggregatorFactoryService Aggregator = null;
 
        public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag
        {
            return new KeywordClassifier(ClassificationRegistry, Aggregator.CreateTagAggregator<ClassificationTag>(buffer)) as ITagger<T>;
        }
    }
 
    class KeywordClassifier : ITagger<ClassificationTag>
    {
        private IClassificationType keywordClassification;
        private IClassificationType linqClassification;
        private IClassificationType visClassification;
        private ITagAggregator<ClassificationTag> aggregator;
 
#pragma warning disable 67
        public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
#pragma warning restore 67
 
        internal KeywordClassifier(
              IClassificationTypeRegistryService registry,
              ITagAggregator<ClassificationTag> aggregator)
        {
            keywordClassification = registry.GetClassificationType(Constants.CLASSIF_NAME);
            linqClassification = registry.GetClassificationType(Constants.LINQ_CLASSIF_NAME);
            visClassification = registry.GetClassificationType(Constants.VISIBILITY_CLASSIF_NAME);
            this.aggregator = aggregator;
        }
 
        private ILanguageKeywords GetKeywordsByContentType(IContentType contentType)
        {
            if (contentType.IsOfType(CSharp.ContentType))
            {
                return new CSharp();
            }
            else if (contentType.IsOfType(Cpp.ContentType))
            {
                return new Cpp();
            }
            else
            {
                Debug.Fail("How were we called with an invalid content type?");
                return null;
            }
        }
 
        public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
        {
            if (spans.Count == 0)
            {
                yield break;
            }
 
            ITextSnapshot snapshot = spans[0].Snapshot;
 
            ILanguageKeywords keywords = GetKeywordsByContentType(snapshot.TextBuffer.ContentType);
            if (keywords == null)
            {
                yield break;
            }
 
            // find spans that the language service has already classified as keywords ...
            foreach (var classifiedSpan in from cs in aggregator.GetTags(spans)
                                           let name = cs.Tag.ClassificationType.Classification.ToLower()
                                           where name.Contains("keyword")
                                           let classifiedSpans = cs.Span.GetSpans(snapshot)
                                           where classifiedSpans.Count > 0
                                           select classifiedSpans[0])
            {
                string text = classifiedSpan.GetText();
 
                if (keywords.ControlFlow.Contains(text))
                    yield return new TagSpan<ClassificationTag>(classifiedSpan, new ClassificationTag(keywordClassification));
                else if (keywords.Linq.Contains(text))
                    yield return new TagSpan<ClassificationTag>(classifiedSpan, new ClassificationTag(linqClassification));
                else if (keywords.Visibility.Contains(text))
                    yield return new TagSpan<ClassificationTag>(classifiedSpan, new ClassificationTag(visClassification));
            }
        }
    }
}